Skip to content

Commit 092ea10

Browse files
committed
fixes to calculate image size automatically, needs tests written
1 parent 9dfbedd commit 092ea10

File tree

5 files changed

+80
-9
lines changed

5 files changed

+80
-9
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
name="singularity",
88

99
# Version number:
10-
version="0.38",
10+
version="0.39",
1111

1212
# Application author details:
1313
author="Vanessa Sochat",

singularity/build/google.py

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@
1111
api_post
1212
)
1313

14+
from singularity.build.utils import get_singularity_version
15+
1416
from singularity.package import (
1517
build_from_spec,
18+
estimate_image_size,
1619
package
1720
)
1821

@@ -112,7 +115,7 @@ def list_bucket(bucket,storage_service):
112115

113116

114117
def run_build(build_dir=None,spec_file=None,repo_url=None,token=None,size=None,bucket_name=None,
115-
repo_id=None,commit=None,verbose=True,response_url=None,secret=None):
118+
repo_id=None,commit=None,verbose=True,response_url=None,secret=None,branch=None):
116119
'''run_build will generate the Singularity build from a spec_file from a repo_url.
117120
If no arguments are required, the metadata api is queried for the values.
118121
:param build_dir: directory to do the build in. If not specified,
@@ -121,13 +124,14 @@ def run_build(build_dir=None,spec_file=None,repo_url=None,token=None,size=None,b
121124
:param repo_url: the url to download the repo from
122125
:param repo_id: the repo_id to uniquely identify the repo (in case name changes)
123126
:param commit: the commit to checkout. If none provided, will use most recent.
124-
:param size: the size of the image to build. If none set, builds default 1024.
127+
:param size: the size of the image to build. If none set, builds folder size + 200MB padding
125128
:param bucket_name: the name of the bucket to send files to
126129
:param verbose: print out extra details as we go (default True)
127130
:param token: a token to send back to the server to authenticate the collection
128131
:param secret: a secret to match to the correct container
129132
:param response_url: the build url to send the response back to. Should also come
130133
from metadata. If not specified, no response is sent
134+
:param branch: the branch to checkout for the build.
131135
:: note: this function is currently configured to work with Google Compute
132136
Engine metadata api, and should (will) be customized if needed to work elsewhere
133137
'''
@@ -151,7 +155,9 @@ def run_build(build_dir=None,spec_file=None,repo_url=None,token=None,size=None,b
151155
{'key': 'token', 'value': token, 'return_text': False },
152156
{'key': 'commit', 'value': commit, 'return_text': True },
153157
{'key': 'secret', 'value': secret, 'return_text': True },
154-
{'key': 'size', 'value': size, 'return_text': True }]
158+
{'key': 'size', 'value': size, 'return_text': True },
159+
{'key': 'branch', 'value': branch, 'return_text': True },
160+
{'key': 'container_id', 'value': None, 'return_text': True }]
155161

156162
# Default spec file is Singularity
157163
if spec_file == None:
@@ -168,6 +174,10 @@ def run_build(build_dir=None,spec_file=None,repo_url=None,token=None,size=None,b
168174
destination=build_dir)
169175

170176
os.chdir(build_dir)
177+
if params['branch'] != None:
178+
bot.logger.info('Checking out branch %s',params['branch'])
179+
os.system('git checkout %s' %(params['branch']))
180+
171181
if params['commit'] != None:
172182
bot.logger.info('Checking out commit %s',params['commit'])
173183
os.system('git checkout %s .' %(params['commit']))
@@ -181,6 +191,12 @@ def run_build(build_dir=None,spec_file=None,repo_url=None,token=None,size=None,b
181191
if os.path.exists(spec_file):
182192
bot.logger.info("Found spec file %s in repository",spec_file)
183193

194+
# If size is None, get from image + 200 padding
195+
if params['size'] == None:
196+
bot.logger.info("Size not detected for build. Will estimate with 200MB padding.")
197+
params['size'] = estimate_image_size(spec=spec_file,
198+
sudopw='')
199+
184200
image = build_from_spec(spec=spec_file, # default will package the image
185201
size=params['size'],
186202
sudopw='', # with root should not need sudo
@@ -238,7 +254,17 @@ def run_build(build_dir=None,spec_file=None,repo_url=None,token=None,size=None,b
238254
"repo_url": params['repo_url'],
239255
"commit": params['commit'],
240256
"repo_id": params['repo_id'],
241-
"secret": params['secret']}
257+
"secret": params['secret'],
258+
"container_id": params['container_id']}
259+
260+
# Did the user specify a specific log file?
261+
logfile = get_build_metadata(key='logfile')
262+
if logfile != None:
263+
response['logfile'] = logfile
264+
265+
if params['branch'] != None:
266+
response['branch'] = params['branch']
267+
242268

243269
if params['token'] != None:
244270
response['token'] = params['token']
@@ -258,7 +284,7 @@ def run_build(build_dir=None,spec_file=None,repo_url=None,token=None,size=None,b
258284
shutil.rmtree(build_dir)
259285

260286

261-
def finish_build(logfile,repo_url=None,bucket_name=None,commit=None,verbose=True,repo_id=None,
287+
def finish_build(logfile,singularity_version=None,repo_url=None,bucket_name=None,commit=None,verbose=True,repo_id=None,
262288
logging_response_url=None,secret=None,token=None):
263289
'''finish_build will finish the build by way of sending the log to the same bucket.
264290
:param build_dir: directory to do the build in. If not specified,
@@ -268,6 +294,7 @@ def finish_build(logfile,repo_url=None,bucket_name=None,commit=None,verbose=True
268294
:param repo_id: the repo_id to uniquely identify the repo (in case name changes)
269295
:param commit: the commit to checkout. If none provided, will use most recent.
270296
:param bucket_name: the name of the bucket to send files to
297+
:param singularity_version: the version of singularity installed
271298
:param verbose: print out extra details as we go (default True)
272299
:param secret: a secret to match to the correct container
273300
:param logging_response_url: the logging response url to send the response back to.
@@ -279,6 +306,9 @@ def finish_build(logfile,repo_url=None,bucket_name=None,commit=None,verbose=True
279306
if go == None:
280307
sys.exit(0)
281308

309+
if singularity_version == None:
310+
singularity_version = get_singularity_version(singularity_version)
311+
282312
# Get variables from the instance metadata API
283313
metadata = [{'key': 'logging_url', 'value': logging_response_url, 'return_text': True },
284314
{'key': 'repo_url', 'value': repo_url, 'return_text': False },

singularity/build/scripts/singularity-build-latest.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ sudo apt-get install -y build-essential libtool autotools-dev automake autoconf
55
sudo apt-get install -y python3-pip
66
cd /tmp && git clone http://www.github.com/singularityware/singularity
77
cd singularity && ./autogen.sh && ./configure --prefix=/usr/local && make && sudo make install
8-
SINGULARITY_VERSION=$(singularity --version)
8+
export SINGULARITY_VERSION=$(singularity --version)
99
sudo pip3 install --upgrade pip
1010
sudo pip3 install --upgrade google-api-python-client
1111
sudo pip3 install --upgrade google
@@ -14,5 +14,5 @@ sudo pip3 install gitpython
1414
cd /tmp && git clone https://github.com/singularityware/singularity-python
1515
cd singularity-python && python3 setup.py sdist && sudo python3 setup.py install
1616
python3 -c "from singularity.build.google import run_build; run_build()" > /tmp/.shub-log 2>&1
17-
command=$(echo "from singularity.build.google import finish_build; finish_build(logfile='/tmp/.shub-log',version='$SINGULARITY_VERSION')")
17+
command=$(echo "from singularity.build.google import finish_build; finish_build(logfile='/tmp/.shub-log')")
1818
python3 -c "$command"

singularity/build/utils.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414

1515
from singularity.utils import (
1616
get_installdir,
17-
read_file
17+
read_file,
18+
run_command
1819
)
1920

2021
import sys
@@ -59,3 +60,19 @@ def get_build_template(template_name,params=None,to_file=None):
5960
else:
6061
bot.logger.warning("Template %s not found.",template_file)
6162
return None
63+
64+
65+
def get_singularity_version(singularity_version=None):
66+
'''get_singularity_version will determine the singularity version for a build
67+
first, an environmental variable is looked at, followed by using the system
68+
version.
69+
'''
70+
if singularity_version == None:
71+
singularity_version = os.environ.get("SINGULARITY_VERSION",None)
72+
73+
# Next get from system
74+
if singularity_version == None:
75+
cmd = ['singularity','--version']
76+
singularity_version = run_command(cmd,error_message="Cannot determine Singularity version!").decode('utf-8').strip('\n')
77+
78+
return singularity_version

singularity/package.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,34 @@
2323
import os
2424

2525

26+
def estimate_image_size(spec=None,sudopw=None,padding=200):
27+
'''estimate_image_size will generate an image in a directory, and add
28+
some padding to it to estimate the size of the image file to generate
29+
:param sudopw: the sudopw for Singularity, root should provide ''
30+
:param spec: the spec file, called "Singuarity"
31+
:param padding: the padding (MB) to add to the image
32+
'''
33+
size_dir = tempfile.mkdtemp()
34+
tmp_dir = tempfile.mkdtemp()
35+
image_folder = build_from_spec(spec=spec_file, # default will package the image
36+
sudopw=sudopw, # with root should not need sudo
37+
output_folder=size_dir,
38+
build_dir=tmp_dir,
39+
build_folder=True)
40+
original_size = calculate_folder_size(image_folder)
41+
bot.logger.debug("Original image size calculated as %s",original_size)
42+
padded_size = original_size + padding
43+
bot.logger.debug("Size with padding will be %s",padded_size)
44+
shutil.rmtree(size_dir)
45+
os.system('sudo rm -rf %s' %tmp_dir)
46+
return padded_size
47+
48+
2649
def build_from_spec(spec=None,build_dir=None,size=None,sudopw=None,
2750
output_folder=None,build_folder=False):
2851
'''build_from_spec will build a "spec" file in a "build_dir" and return the directory
2952
:param spec: the spec file, called "Singuarity"
53+
:param sudopw: the sudopw for Singularity, root should provide ''
3054
:param build_dir: the directory to build in. If not defined, will use tmpdir.
3155
:param size: the size of the image
3256
:param output_folder: where to output the image package

0 commit comments

Comments
 (0)