def upload_image(self, image, owner, image_file, gzip=False, hypervisor='xen'): log.info("Checking to see if image slot exists on repository") if owner: resp = self._get('/api/images/%s/%s' % (owner, image)) else: resp = self._get('/api/images/%s' % (image)) if resp.status != 200: log.info("Image slot does not yet exist.") raise RepomanError('Image does not yet exist. Create an image before uploading to it', resp) # Check if the source is a directory. If it is, then raise an # exception. if os.path.isdir(image_file): raise RepomanError('Specified source is a directory: %s\nSource must be a file.' % (image_file)) # Check if the source file exists. if not os.path.exists(image_file): raise RepomanError('Specified source not found: %s' % (image_file)) if owner: url = 'https://' + config.host + '/api/images/raw/%s/%s/%s' % (owner, hypervisor, image) else: url = 'https://' + config.host + '/api/images/raw/%s/%s' % (hypervisor, image) try: if gzip: log.info("Performing gzip on image prior to upload") print "Gzipping image before upload" gzip_image = os.path.join(os.path.dirname(image_file), image) gzip = subprocess.Popen("gzip --stdout %s > %s" % (image_file, gzip_image), shell=True, env=config.get_restricted_env()) gzip.wait() image_file = gzip_image log.info('Gzip complete') args = ['curl', '--cert', config.proxy, '--insecure', '-T', image_file, url] cmd = " ".join(args) log.info("Running command: '%s'" % cmd) curl = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, env=config.get_restricted_env()) for line in curl.stdout.readlines(): print line log.info("Command complete") # Cleanup gzip file if needed. if gzip: try: log.info("Cleaning up %s" % (image_file)) os.remove(image_file) except Exception, e: pass except Exception, e: log.error("%s" % e) raise RepomanError(str(e))
def label_image(self, path, label='/'): cmd = ['tune2fs', '-L', label, path] log.debug("Labeling image: '%s'" % cmd) if subprocess.Popen(cmd, shell=False, env=config.get_restricted_env()).wait(): log.error("Unable to label image") raise ImageUtilError("Unable to label image") log.debug("%s labeled as %s" % (path, label))
def sync_fs(self, verbose): #TODO: add progress bar into rsync somehow log.info("Starting Sync Process") exclude_list = "" if self.system_excludes != None and len(self.system_excludes) > 0: for exclude_item in self.system_excludes: exclude_list += '--exclude "%s" ' % (exclude_item) if self.user_excludes != None and len(self.user_excludes) > 0: for exclude_item in self.user_excludes: exclude_list += '--exclude "%s" ' % (exclude_item) # Let's not forget to add the --delete-exclude flag to rsync else # previously synced files which now match an exclude rule will not get # deleted and will stay in the synced image. if len(exclude_list) > 0: exclude_list += " --delete-excluded" flags = '' if verbose: flags += '--stats --progress ' cmd = "rsync -a --sparse %s --delete %s / %s" % (flags, exclude_list, self.mountpoint) log.debug("%s" % cmd) p = subprocess.Popen(cmd, shell=True, env=config.get_restricted_env()).wait() if p: log.error("Rsync encountered an issue. return code: '%s'" % p) raise ImageUtilError("Rsync failed. Aborting.") log.info("Sync Complete")
def dd_sparse(self, path, size_bytes): cmd = ['dd', 'if=/dev/zero', 'of=%s' % path, 'count=0', 'bs=1', 'seek=%s' % size_bytes] log.debug("Creating sparse file: '%s'" % cmd) null_f = open('/dev/null', 'w') if subprocess.Popen(cmd, shell=False, stdout=null_f, stderr=null_f, env=config.get_restricted_env()).wait(): log.error("Unable to create sparse file") raise ImageUtilError("Error creating sparse file") null_f.close()
def mkfs(self, path, fs_type='ext3', label='/'): if fs_type == None: fs_type = 'ext3' # Default to ext3 if autodetection failed. cmd = ['mkfs', '-t', fs_type, '-I', '128', '-F', '-L', label, path] log.debug("Creating file system: '%s'" % cmd) null_f = open('/dev/null', 'w') if subprocess.Popen(cmd, shell=False, stdout=null_f, stderr=null_f, env=config.get_restricted_env()).wait(): log.error("Unable to create filesystem") raise ImageUtilError("Error creating filesystem.") null_f.close()
def umount_image(self): if not self.check_mounted(): log.debug('Image already unmounted') return cmd = ['umount', self.mountpoint] if subprocess.Popen(cmd, shell=False, env=config.get_restricted_env()).wait(): raise ImageUtilError("Unable to unmount image") log.debug("Image unmounted: '%s'" % cmd) if self.partition and self.device_map != None: log.debug("Deleting %s device map for image %s" % (self.device_map, self.imagepath)) self.delete_device_map(self.imagepath)
def mount_image(self): if self.check_mounted(): log.debug('Image Already Mounted') return if not os.path.exists(self.mountpoint): log.debug("Creating mount point") os.makedirs(self.mountpoint) cmd = None if self.partition: if not self.device_map: self.create_device_map(self.imagepath) cmd = ['mount', self.device_map, self.mountpoint] else: cmd = ['mount', '-o', 'loop', self.imagepath, self.mountpoint] log.debug("running [%s]" % (cmd)) if subprocess.Popen(cmd, shell=False, env=config.get_restricted_env()).wait(): raise ImageUtilError("Unable to Mount image") log.debug("Image mounted: '%s'" % cmd)
def get_fs_label(self, fs = '/'): """ Returns the given filesystem's label, or None if the filesystem has no label. """ log.debug("Detecting label for %s ..." % (fs)) # First detect the filesystem's partition. partition = self.get_partition_for_fs(fs) # Now use tune2fs to extract that partition's label cmd = ['tune2fs', '-l', partition] p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=config.get_restricted_env()) if not p: log.error("Error calling: %s" % (cmd)) raise ImageUtilError("Error getting label for partition %s" % (partition)) stdout = p.communicate()[0] log.debug("[%s] output:\n%s" % (cmd, stdout)) label = None for l in stdout.split('\n'): if l.startswith('Filesystem volume name'): label = l.split(':')[1].strip() if label == '<none>': log.debug("Filesystem %s has no label." % (partition)) label = None break return label
def get_partition_for_fs(self, fs): """ Returns the disk for a given fs. """ cmd = ['df', fs] p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=config.get_restricted_env()) if not p: log.error("Error calling: %s" % (cmd)) raise ImageUtilError("Error getting partition for filesystem %s" % (fs)) stdout = p.communicate()[0] log.debug("[%s] output:\n%s" % (cmd, stdout)) feilds = stdout.split('\n')[1].split() log.debug("Filesystem %s is on partition %s" % (fs, feilds[0])) return feilds[0]
def destroy_files(self, *args): cmd = ['rm', '-rf'] + list(args) subprocess.call(cmd, shell=False, env=config.get_restricted_env()) log.debug("Destroyed files: '%s'" % cmd)
def install_mbr(self, path): cmd = ['grub'] log.debug("Creating MBR on %s" % (path)) p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, env=config.get_restricted_env()) if not p: log.error("Error calling: %s" % (cmd)) raise ImageUtilError("Error creating MBR on %s." % (path)) p.stdin.write('device (hd0) %s\n' % (path)) p.stdin.write('root (hd0,0)\n') p.stdin.write('setup (hd0)\n') p.stdin.write('quit\n') p.stdin.close() p.wait() if p.returncode == 0: log.debug("MBR created on %s" % (path)) else: log.error("Error creating MBR on %s\nReturn code: %d" % (path, p.returncode)) raise ImageUtilError("Error creating MBR.")
def uploaded_image_exist(self, image, owner, hypervisor='xen'): """ This method will test if an image has an uploaded file for a given hypervisor. """ log.info("Checking to see if image %s, owner %s, has an uploaded file for hypervisor %s" % (image, owner, hypervisor)) if owner: resp = self._get('/api/images/%s/%s' % (owner, image)) else: resp = self._get('/api/images/%s' % (image)) if resp.status != 200: log.info("Image slot does not yet exist.") raise RepomanError('Image does not yet exist.', resp) if owner: url = 'https://' + config.host + '/api/images/raw/%s/%s/%s' % (owner, hypervisor, image) else: url = 'https://' + config.host + '/api/images/raw/%s/%s' % (hypervisor, image) try: cmd = ['curl', '--cert', config.proxy, '--insecure', '--head', url] log.debug(" ".join(cmd)) p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=config.get_restricted_env()) if not p: log.error("Error calling: %s" % (cmd)) raise RepomanError("Error checking if image %s, owner %s, has an uploaded file for hypervisor %s" % (image, owner, hypervisor)) log.info("Command complete") stdout = p.communicate()[0] log.debug(stdout) m = re.search('^HTTP/.+200 OK', stdout, flags=re.M) if m: log.info("Uploaded file exist for image %s, owner %s, hypervisor %s." % (image, owner, hypervisor)) return True else: log.info("Uploaded file does not exist for image %s, owner %s, hypervisor %s." % (image, owner, hypervisor)) return False except Exception, e: log.error("%s" % e) raise RepomanError(str(e))
def create_device_map(self, path): if self.device_map != None: log.error("Attempt to create device map over existing one. Aborting.") raise ImageUtilError("Error creating device map.") cmd = ['kpartx', '-av' , path] log.debug("Creating device map for %s" % (path)) log.debug(cmd) p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=config.get_restricted_env()) if not p: log.error("Error calling: %s" % (cmd)) raise ImageUtilError("Error creating device map.") (stdout, stderr) = p.communicate() log.debug("[%s] kpartx output stdout:\n%s\n\nkpartx output stderr:\n%s" % (cmd, stdout, stderr)) if p.returncode != 0: log.error("Device map creation command returned error: %d" % (p.returncode)) raise ImageUtilError("Error creating device map.") # Search the output to extract the location of the new device map m = re.search('^add map (\w+) .+$', stdout, flags=re.M) if not m: log.error("Error extracting location of new device map from:\n%s" % (stdout)) raise ImageUtilError("Error extracting location of new device map.") log.debug("Device map created for %s" % (path)) self.device_map = '/dev/mapper/%s' % (m.group(1)) return self.device_map
def create_bootable_partition(self, path): cmd = ['sfdisk', path] log.debug("Creating bootable partition on %s" % (path)) p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, env=config.get_restricted_env()) if not p: log.error("Error calling: %s" % (cmd)) raise ImageUtilError("Error creating bootable partition.") p.stdin.write(',,L,*\n') p.stdin.close() p.wait() if p.returncode != 0: log.error("Command to create bootable partition returned error: %d" % (p.returncode)) raise ImageUtilError("Error creating bootable partition.") log.debug("Bootable partition created on %s" % (path))
def is_disk_partitioned(self): """ Detects if the disk is partitioned or not. Returns True if the disk is partitioned, False otherwise. """ cmd = ['df', '/'] log.debug("Checking if disk is partitioned...") p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=config.get_restricted_env()) if not p: log.error("Error calling: %s" % (cmd)) raise ImageUtilError("Error checking if disk is partitioned.") stdout = p.communicate()[0] log.debug("[%s] output:\n%s" % (cmd, stdout)) feilds = stdout.split('\n')[1].split() if feilds[0][-1].isdigit(): log.debug('Disk is partitioned.') return True else: log.debug('Disk is not partitioned.') return False
def delete_device_map(self, path): cmd = ['kpartx', '-d', path] log.debug("Deleting device map for %s" % (path)) p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=config.get_restricted_env()) if not p: log.error("Error calling: %s" % (cmd)) raise ImageUtilError("Error deleting device map.") stdout = p.communicate()[0] log.debug("[%s] output:\n%s" % (cmd, stdout)) if p.returncode != 0: log.error("Error deleting device map for %s" % (path)) raise ImageUtilError("Error deleting device map.") log.debug("Device map deleted for %s" % (path)) self.device_map = None
# Check to make sure destination is not an existing directory. if os.path.isdir(dest): raise RepomanError('Cannot create %s. Specified destination already exist and is a directory.' % (dest)) # If the destination already exists, make sure we can overwrite it. if os.path.isfile(dest): try: fp = open(dest, 'w') except IOError, e: if e.errno == errno.EACCES: raise RepomanError('Cannot overwrite %s. Specified destination already exist and you don\'t have permissions to write to it.' % (dest)) url = 'https://' + config.host + '/api/images/raw/%s' % image log.info("Downloading image From:'%s' To:'%s'" % (url, dest)) try: args = ['curl', '--cert', config.proxy, '--insecure', url, '>', dest] cmd = " ".join(args) log.info("Running Command: '%s'" % cmd) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, env=config.get_restricted_env()) for line in p.stdout.readlines(): print line log.info("Command complete") except Exception, e: log.error("%s" % e) print e