def package(image_path,output_folder=None,runscript=True,software=True,remove_image=False,verbose=False): '''package will take an image and generate a zip (including the image to a user specified output_folder. :param image_path: full path to singularity image file :param runscript: if True, will extract runscript to include in package as runscript :param software: if True, will extract files.txt and folders.txt to package :param remove_image: if True, will not include original image in package (default,False) :param verbose: be verbose when using singularity --export (default,False) ''' S = Singularity(verbose=verbose) tmptar = S.export(image_path=image_path,pipe=False) tar = tarfile.open(tmptar) members = tar.getmembers() image_name = os.path.basename(image_path) zip_name = "%s.zip" %(image_name.replace(" ","_")) # Include the image in the package? if remove_image: to_package = dict() else: to_package = {image_name:image_path} # Package the image with an md5 sum as VERSION version = get_image_hash(image_path) to_package["VERSION"] = version # Look for runscript if runscript == True: try: runscript_member = tar.getmember("./singularity") runscript_file = tar.extractfile("./singularity") runscript = runscript_file.read() to_package["runscript"] = runscript print("Found runscript!") # Try to extract input args, only python supported, will return None otherwise params_json = get_runscript_parameters(runscript=runscript, name=image_name, version=version) if params_json != None: print('Extracted runscript params!') to_package['%s.json' %(image_name)] = params_json except KeyError: print("No runscript found in image!") if software == True: print("Adding software list to package!") files = [x.path for x in members if x.isfile()] folders = [x.path for x in members if x.isdir()] to_package["files.txt"] = files to_package["folders.txt"] = folders # Do zip up here - let's start with basic structures zipfile = zip_up(to_package,zip_name=zip_name,output_folder=output_folder) print("Package created at %s" %(zipfile)) # return package to user return zipfile
def get_memory_tar(image_path): '''get an in memory tar of an image (does not require sudo!)''' cli = Singularity() if "pancakes" in os.environ: del os.environ['pancakes'] byte_array = cli.export(image_path) file_object = io.BytesIO(byte_array) tar = tarfile.open(mode="r|*", fileobj=file_object) return (file_object, tar)
def get_memory_tar(image_path): '''get an in memory tar of an image. Use carefully, not as reliable as get_image_tar ''' cli = Singularity() byte_array = cli.export(image_path) file_object = io.BytesIO(byte_array) tar = tarfile.open(mode="r|*", fileobj=file_object) return (file_object, tar)
def get_image_tar(image_path, S=None): '''get an image tar, either written in memory or to the file system. file_obj will either be the file object, or the file itself. ''' bot.debug('Generate file system tar...') if S is None: S = Singularity() file_obj = S.export(image_path=image_path) if file_obj is None: bot.error("Error generating tar, exiting.") sys.exit(1) tar = tarfile.open(file_obj) return file_obj, tar
# Get general help: S.help() # These are the defaults, which can be specified S = Singularity(sudo=True,verbose=False) # Let's define a path to an image # wget http://www.vbmis.com/bmi/project/singularity/package_image/ubuntu:latest-2016-04-06.img image_path = 'ubuntu:latest-2016-04-06.img' # Run singularity --exec S.execute(image_path=image_path,command='ls') # $'docker2singularity.sh\nget_docker_container_id.sh\nget_docker_meta.py\nmakeBases.py\nsingularity\nubuntu:latest-2016-04-06.img\n' # These are the defaults, which can be specified # For any function you can get the docs: S.help(command="exec") # or return as string help = S.help(command="exec",stdout=False) # export an image, default export_type="tar" , pipe=False , output_file = None will produce file in tmp tmptar = S.export(image_path=image_path) # create an empty image S.create(image_path='test.img') # import a docker image - no need to specify the file, the image name works # still under development docker_image = S.docker2singularity("ubuntu:latest")
# (Deprecated) create an image and import into it image = S.create('myimage.simg') S.importcmd(image, 'docker://ubuntu:latest') # Execute command to container result = S.execute(image, command='cat /singularity') print(result) ''' '#!/bin/sh\n\nexec "/bin/bash"\n' ''' # For any function you can get the docs: S.help(command="exec") # export an image to tar tar = S.export(image) # Show apps and inspect S.apps(image) S.inspect(image) ''' { "data": { "attributes": { "deffile": null, "help": null, "labels": null, "environment": "# Custom environment shell code should follow\n\n", "runscript": "#!/bin/sh\n\nexec \"/bin/bash\"\n", "test": null },
image = S.create('myimage.img') # Import into it S.importcmd(image, 'docker://*****:*****@" elif test -x /bin/sh; then exec /bin/sh "$@" else echo "ERROR: No valid shell within container" exit 255 fi ''' # For any function you can get the docs: S.help(command="exec") # export an image as a byte array byte_array = S.export(image) # Get an in memory tar from singularity.reproduce import get_memory_tar tar = get_memory_tar(image)
def package(image_path, spec_path=None, output_folder=None, runscript=True, software=True, remove_image=False, verbose=False, S=None, sudopw=None, old_version=False): '''package will take an image and generate a zip (including the image to a user specified output_folder. :param image_path: full path to singularity image file :param runscript: if True, will extract runscript to include in package as runscript :param software: if True, will extract files.txt and folders.txt to package :param remove_image: if True, will not include original image in package (default,False) :param verbose: be verbose when using singularity --export (default,False) :param S: the Singularity object (optional) will be created if not required. ''' # Run create image and bootstrap with Singularity command line tool. if S == None: if sudopw != None: S = Singularity(sudopw=sudopw, debug=verbose) else: S = Singularity( debug=verbose) # This command will ask the user for sudo # Singularity < version 2.3 if old_version == False: file_obj, tar = get_memory_tar(image_path) # Singularity 2.3 and up else: tmptar = S.export(image_path=image_path, old_version=True) tar = tarfile.open(tmptar) members = tar.getmembers() image_name = os.path.basename(image_path) zip_name = "%s.zip" % (image_name.replace(" ", "_")) # Include the image in the package? if remove_image: to_package = dict() else: to_package = {"files": [image_path]} # If the specfile is provided, it should also be packaged if spec_path is not None: singularity_spec = "".join(read_file(spec_path)) to_package['Singularity'] = singularity_spec # Package the image with an sha1, identical standard, as VERSION if old_version == False: hashes = get_image_hashes(image_path) to_package["HASHES"] = hashes to_package["VERSION"] = hashes['IDENTICAL'] else: to_package["VERSION"] = get_image_file_hash(image_path) # Look for runscript if runscript is True: try: to_package["runscript"] = extract_content(image_path, './singularity', cli=S) bot.logger.debug("Found runscript.") except KeyError: bot.logger.warning("No runscript found") if software == True: bot.logger.info("Adding software list to package.") files = [x.path for x in members if x.isfile()] folders = [x.path for x in members if x.isdir()] to_package["files.txt"] = files to_package["folders.txt"] = folders # Do zip up here - let's start with basic structures zipfile = zip_up(to_package, zip_name=zip_name, output_folder=output_folder) bot.logger.debug("Package created at %s" % (zipfile)) if old_version == False: file_obj.close() # return package to user return zipfile