def register_image(session): """Register image with the compute service""" d = session["dialog"] image = session['image'] assert 'clouds' in session try: cloud_name = session['current_cloud'] cloud = session['clouds'][cloud_name] account = cloud['account'] except KeyError: cloud = None if cloud is None or account is None: d.msgbox("You need to select a valid cloud before you can register an " "images with it", width=SMALL_WIDTH) return False if "uploaded" not in cloud: d.msgbox("You need to upload the image to a cloud before you can " "register it", width=SMALL_WIDTH) return False is_public = False _, _, _, container, remote = cloud['uploaded'].split('/') name = "" if 'registered' not in cloud else cloud['registered'] descr = image.meta['DESCRIPTION'] if 'DESCRIPTION' in image.meta else "" while 1: fields = [("Registration name:", name, 60), ("Description (optional):", descr, 80)] (code, output) = d.form( "Please provide the following registration info:", create_form_elements(fields), height=11, width=WIDTH, form_height=2) if code in (d.CANCEL, d.ESC): return False name, descr = output name = name.strip() descr = descr.strip() if len(name) == 0: d.msgbox("Registration name cannot be empty", width=SMALL_WIDTH) continue answer = d.yesno("Make the image public?\\nA public image is " "accessible by every user of the service.", defaultno=1, width=WIDTH) if answer == d.ESC: continue is_public = (answer == d.OK) break image.meta['DESCRIPTION'] = descr metadata = {} metadata.update(image.meta) if 'task_metadata' in session: for key in session['task_metadata']: metadata[key] = 'yes' img_type = "public" if is_public else "private" gauge = GaugeOutput(d, "Image Registration", "Registering image ...") try: out = session['image'].out out.append(gauge) try: try: out.info("Registering %s image with the cloud ..." % img_type, False) kamaki = Kamaki(cloud['account'], out) cloud['registered'] = kamaki.register( name, cloud['uploaded'], metadata, is_public) out.success('done') # Upload metadata file out.info("Uploading metadata file ...", False) metastring = json.dumps(cloud['registered'], indent=4, ensure_ascii=False) kamaki.upload(StringIO.StringIO(metastring), size=len(metastring), remote_path="%s.meta" % remote, container=container, content_type="application/json") out.success("done") if is_public: out.info("Sharing metadata and md5sum files ...", False) kamaki.share("%s.meta" % remote) kamaki.share("%s.md5sum" % remote) out.success('done') except ClientError as error: d.msgbox("Error in storage service client: %s" % error.message) return False finally: out.remove(gauge) finally: gauge.cleanup() d.msgbox("%s image `%s' was successfully registered with the cloud as `%s'" % (img_type.title(), remote, name), width=SMALL_WIDTH) return True
def upload_image(session): """Upload the image to the storage service""" d = session["dialog"] image = session['image'] assert 'clouds' in session try: cloud_name = session['current_cloud'] cloud = session['clouds'][cloud_name] account = cloud['account'] except KeyError: cloud = None if cloud is None or not account: d.msgbox( "You need to select a valid cloud before you can upload " "images to it", width=SMALL_WIDTH) return False while 1: if 'uploaded' in cloud: _, _, _, container, name = cloud['uploaded'].split('/') elif 'OS' in session['image'].meta: name = "%s.diskdump" % session['image'].meta['OS'] container = CONTAINER else: name = "" container = CONTAINER fields = [("Remote Name:", name, 60), ("Container:", container, 60)] (code, output) = d.form("Please provide the following upload info:", create_form_elements(fields), height=11, width=WIDTH, form_height=2) if code in (d.CANCEL, d.ESC): return False name, container = output name = name.strip() container = container.strip() if len(name) == 0: d.msgbox("Remote Name cannot be empty", width=SMALL_WIDTH) continue if len(container) == 0: d.msgbox("Container cannot be empty", width=SMALL_WIDTH) continue kamaki = Kamaki(cloud['account'], None) overwrite = [] for f in (name, "%s.md5sum" % name, "%s.meta" % name): if kamaki.object_exists(container, f): overwrite.append(f) if len(overwrite) > 0: if d.yesno("The following storage service object(s) already " "exist(s):\n%s\nDo you want to overwrite them?" % "\n".join(overwrite), width=WIDTH, defaultno=1) != d.OK: continue break gauge = GaugeOutput(d, "Image Upload", "Uploading ...") try: out = image.out out.append(gauge) kamaki.out = out try: if 'checksum' not in session: session['checksum'] = image.md5() try: # Upload image file with image.raw_device() as raw: with open(raw, 'rb') as f: cloud["uploaded"] = \ kamaki.upload(f, image.size, name, container, None, "Calculating block hashes", "Uploading missing blocks") # Upload md5sum file out.info("Uploading md5sum file ...") md5str = "%s %s\n" % (session['checksum'], name) kamaki.upload(StringIO.StringIO(md5str), size=len(md5str), remote_path="%s.md5sum" % name, container=container, content_type="text/plain") out.success("done") except ClientError as e: d.msgbox("Error in storage service client: %s" % e.message, title="Storage Service Client Error", width=SMALL_WIDTH) if 'uploaded' in cloud: del cloud['uploaded'] return False finally: out.remove(gauge) finally: gauge.cleanup() d.msgbox("Image file `%s' was successfully uploaded" % name, width=SMALL_WIDTH) return True
def upload_image(session): """Upload the image to the storage service""" d = session["dialog"] image = session['image'] assert 'clouds' in session try: cloud_name = session['current_cloud'] cloud = session['clouds'][cloud_name] account = cloud['account'] except KeyError: cloud = None if cloud is None or not account: d.msgbox("You need to select a valid cloud before you can upload " "images to it", width=SMALL_WIDTH) return False while 1: if 'uploaded' in cloud: _, _, _, container, name = cloud['uploaded'].split('/') elif 'OS' in session['image'].meta: name = "%s.diskdump" % session['image'].meta['OS'] container = CONTAINER else: name = "" container = CONTAINER fields = [("Remote Name:", name, 60), ("Container:", container, 60)] (code, output) = d.form("Please provide the following upload info:", create_form_elements(fields), height=11, width=WIDTH, form_height=2) if code in (d.CANCEL, d.ESC): return False name, container = output name = name.strip() container = container.strip() if len(name) == 0: d.msgbox("Remote Name cannot be empty", width=SMALL_WIDTH) continue if len(container) == 0: d.msgbox("Container cannot be empty", width=SMALL_WIDTH) continue kamaki = Kamaki(cloud['account'], None) overwrite = [] for f in (name, "%s.md5sum" % name, "%s.meta" % name): if kamaki.object_exists(container, f): overwrite.append(f) if len(overwrite) > 0: if d.yesno("The following storage service object(s) already " "exist(s):\n%s\nDo you want to overwrite them?" % "\n".join(overwrite), width=WIDTH, defaultno=1 ) != d.OK: continue break gauge = GaugeOutput(d, "Image Upload", "Uploading ...") try: out = image.out out.append(gauge) kamaki.out = out try: if 'checksum' not in session: session['checksum'] = image.md5() try: # Upload image file with image.raw_device() as raw: with open(raw, 'rb') as f: cloud["uploaded"] = \ kamaki.upload(f, image.size, name, container, None, "Calculating block hashes", "Uploading missing blocks") # Upload md5sum file out.info("Uploading md5sum file ...") md5str = "%s %s\n" % (session['checksum'], name) kamaki.upload(StringIO.StringIO(md5str), size=len(md5str), remote_path="%s.md5sum" % name, container=container, content_type="text/plain") out.success("done") except ClientError as e: d.msgbox( "Error in storage service client: %s" % e.message, title="Storage Service Client Error", width=SMALL_WIDTH) if 'uploaded' in cloud: del cloud['uploaded'] return False finally: out.remove(gauge) finally: gauge.cleanup() d.msgbox("Image file `%s' was successfully uploaded" % name, width=SMALL_WIDTH) return True
def register_image(session): """Register image with the compute service""" d = session["dialog"] image = session['image'] assert 'clouds' in session try: cloud_name = session['current_cloud'] cloud = session['clouds'][cloud_name] account = cloud['account'] except KeyError: cloud = None if cloud is None or account is None: d.msgbox( "You need to select a valid cloud before you can register an " "images with it", width=SMALL_WIDTH) return False if "uploaded" not in cloud: d.msgbox( "You need to upload the image to a cloud before you can " "register it", width=SMALL_WIDTH) return False is_public = False _, _, _, container, remote = cloud['uploaded'].split('/') name = "" if 'registered' not in cloud else cloud['registered'] descr = image.meta['DESCRIPTION'] if 'DESCRIPTION' in image.meta else "" while 1: fields = [("Registration name:", name, 60), ("Description (optional):", descr, 80)] (code, output) = d.form("Please provide the following registration info:", create_form_elements(fields), height=11, width=WIDTH, form_height=2) if code in (d.CANCEL, d.ESC): return False name, descr = output name = name.strip() descr = descr.strip() if len(name) == 0: d.msgbox("Registration name cannot be empty", width=SMALL_WIDTH) continue answer = d.yesno( "Make the image public?\\nA public image is " "accessible by every user of the service.", defaultno=1, width=WIDTH) if answer == d.ESC: continue is_public = (answer == d.OK) break image.meta['DESCRIPTION'] = descr metadata = {} metadata.update(image.meta) if 'task_metadata' in session: for key in session['task_metadata']: metadata[key] = 'yes' img_type = "public" if is_public else "private" gauge = GaugeOutput(d, "Image Registration", "Registering image ...") try: out = session['image'].out out.append(gauge) try: try: out.info("Registering %s image with the cloud ..." % img_type, False) kamaki = Kamaki(cloud['account'], out) cloud['registered'] = kamaki.register(name, cloud['uploaded'], metadata, is_public) out.success('done') # Upload metadata file out.info("Uploading metadata file ...", False) metastring = json.dumps(cloud['registered'], indent=4, ensure_ascii=False) kamaki.upload(StringIO.StringIO(metastring), size=len(metastring), remote_path="%s.meta" % remote, container=container, content_type="application/json") out.success("done") if is_public: out.info("Sharing metadata and md5sum files ...", False) kamaki.share("%s.meta" % remote) kamaki.share("%s.md5sum" % remote) out.success('done') except ClientError as error: d.msgbox("Error in storage service client: %s" % error.message) return False finally: out.remove(gauge) finally: gauge.cleanup() d.msgbox( "%s image `%s' was successfully registered with the cloud as `%s'" % (img_type.title(), remote, name), width=SMALL_WIDTH) return True
def extract_image(session): """Dump the image to a local file""" d = session['dialog'] dir = os.getcwd() while 1: if dir and dir[-1] != os.sep: dir = dir + os.sep path = select_file(d, title="Save image as...", existing=False, basedir=dir) if path is None: return False if os.path.isdir(path): dir = path continue if os.path.isdir("%s.meta" % path): d.msgbox("Can't overwrite directory `%s.meta'" % path, width=SMALL_WIDTH) continue if os.path.isdir("%s.md5sum" % path): d.msgbox("Can't overwrite directory `%s.md5sum'" % path, width=SMALL_WIDTH) continue basedir = os.path.dirname(path) name = os.path.basename(path) if not os.path.exists(basedir): d.msgbox("Directory `%s' does not exist" % basedir, width=SMALL_WIDTH) continue dir = basedir if len(name) == 0: continue files = ["%s%s" % (path, ext) for ext in ('', '.meta', '.md5sum')] overwrite = filter(os.path.exists, files) if len(overwrite) > 0: if d.yesno("The following file(s) exist:\n" "%s\nDo you want to overwrite them?" % "\n".join(overwrite), width=SMALL_WIDTH) != d.OK: continue gauge = GaugeOutput(d, "Image Extraction", "Extracting image...") try: image = session['image'] out = image.out out.append(gauge) try: if "checksum" not in session: session['checksum'] = image.md5() # Extract image file image.dump(path) # Extract metadata file out.info("Extracting metadata file ...", False) with open('%s.meta' % path, 'w') as f: f.write(extract_metadata_string(session)) out.success('done') # Extract variant file out.info("Extracting variant file ...", False) with open('%s.meta' % path, 'w') as f: f.write(extract_variant_string(session, path)) out.success('done') # Extract md5sum file out.info("Extracting md5sum file ...", False) md5str = "%s %s\n" % (session['checksum'], name) with open('%s.md5sum' % path, 'w') as f: f.write(md5str) out.success("done") finally: out.remove(gauge) finally: gauge.cleanup() d.msgbox("Image file `%s' was successfully extracted!" % path, width=SMALL_WIDTH) break return True
def create_image(d, media, out, tmp, snapshot): """Create an image out of `media'""" d.setBackgroundTitle('snf-image-creator') gauge = GaugeOutput(d, "Initialization", "Initializing...") out.append(gauge) disk = Disk(media, out, tmp) # pylint: disable=unused-argument def signal_handler(signum, frame): gauge.cleanup() disk.cleanup() signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) try: device = disk.file if not snapshot else disk.snapshot() image = disk.get_image(device) gauge.cleanup() out.remove(gauge) # Make sure the signal handler does not call gauge.cleanup again def dummy(self): # pylint: disable=unused-argument pass gauge.cleanup = type(GaugeOutput.cleanup)(dummy, gauge, GaugeOutput) session = {"dialog": d, "disk": disk, "image": image} if image.is_unsupported(): session['excluded_tasks'] = [-1] session['task_metadata'] = ["EXCLUDE_ALL_TASKS"] msg = "The system on the input media is not supported." \ "\n\nReason: %s\n\n" \ "We highly recommend not to create an image out of this, " \ "since the image won't be cleaned up and you will not be " \ "able to configure it during the deployment. Press <YES> if " \ "you still want to continue with the image creation process." \ % image._unsupported if d.yesno(msg, width=WIDTH, defaultno=1, height=12) == d.OK: main_menu(session) d.infobox("Thank you for using snf-image-creator. Bye", width=53) return 0 msg = "snf-image-creator detected a %s system on the input media. " \ "Would you like to run a wizard to assist you through the " \ "image creation process?\n\nChoose <Wizard> to run the wizard," \ " <Expert> to run snf-image-creator in expert mode or press " \ "ESC to quit the program." \ % (image.ostype.capitalize() if image.ostype == image.distro or image.distro == "unknown" else "%s (%s)" % (image.ostype.capitalize(), image.distro.capitalize())) update_background_title(session) while True: code = d.yesno(msg, width=WIDTH, height=12, yes_label="Wizard", no_label="Expert") if code == d.OK: if start_wizard(session): break elif code == d.CANCEL: main_menu(session) break if confirm_exit(d): break d.infobox("Thank you for using snf-image-creator. Bye", width=53) finally: disk.cleanup() return 0