def get_config_data(key): """ Get a configuration definition. Parameters: ---------- key: str Key from the configuration data if not None, full configuration otherwise. Return: The configuration data. """ _logger.debug('__ Get config data: %s' % key) try: with OciMigrateConfParam(migrate_data.oci_migrate_conf_file, key) as config: return config.get_values() except FileNotFoundError as fnf: _logger.debug('File %s not foud: %s, using data structure.' % (migrate_data.oci_migrate_conf_file, str(fnf))) if key in migrate_data.oci_image_migrate_config: return migrate_data.oci_image_migrate_config[key] else: raise OciMigrateException('Failed to get data for %s: does ' 'not exist' % key) except Exception as e: raise OciMigrateException('Failed to get data for %s: %s' % (key, str(e)))
def run_call_cmd(command): """ Execute an os command which does not return data. Parameters ---------- command: list The os command and its arguments. Returns ------- int: The return value. """ _logger.debug('__ Executing %s' % command) assert (len(command) > 0), 'empty command list' try: return (subprocess.call(command, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)) except OSError as oserr: raise OciMigrateException('OS error encountered while running %s: %s' % (command, str(oserr))) except subprocess.CalledProcessError as e: raise OciMigrateException('Error encountered while running %s: %s' % (command, str(e)))
def run_popen_cmd(command, valid_return=frozenset([0])): """ Execute an os command and collect stdout and stderr. Parameters ---------- command: list The os command and its arguments. valid_return: frozenset A set of valid return codes, default = [0] Returns ------- dict: {'output': output, 'error': error, 'return_code: return_code} raises an exception on failure. """ _logger.debug('__ Executing %s.', command) output_dict = dict() if exec_exists(command[0]) is not None: _logger.debug('running %s', command) try: ext_process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = ext_process.communicate() return_code = ext_process.returncode output_dict['output'] = output output_dict['error'] = error output_dict['return_code'] = return_code #if return_code != 0: # if bool(error): # _logger.debug('Error occurred while running %s: %s - %s', # command, return_code, error.decode('utf-8'), exc_info=True) # raise OciMigrateException('Error encountered while running %s: %s - %s' # % (command, return_code, error.decode('utf-8'))) if not bool(output): _logger.debug('%s did not return output.', command) if bool(error): # not necessarily fatal _logger.debug('%s returned message %s.', command, error.decode('utf-8')) _logger.debug('%s returned code %s', command, str(return_code)) if return_code not in valid_return: raise OciMigrateException( 'Error encountered while running %s: %s - %s' % (command, return_code, error.decode('utf-8'))) return output_dict except OSError as os_error: raise OciMigrateException( 'OS error encountered while running %s:' % command) from os_error except Exception as e: raise OciMigrateException('Error encountered while running %s:' % command) from e else: _logger.critical(' %s not found.', command[0]) raise OciMigrateException('%s does not exist' % command[0])
def enter_chroot(newroot): """ Execute the chroot command. Parameters ---------- newroot: str Full path of new root directory. Returns ------- file descriptor, str, str: The file descriptor of the current root on success, path to restore, current working dir; raises an exception on failure. """ _logger.debug('__ Entering chroot jail at %s.' % newroot) root2return = -1 current_dir = '' try: # # current working directory current_dir = os.getcwd() # # change root root2return = os.open('/', os.O_RDONLY) os.chdir(newroot) os.chroot(newroot) _logger.debug('Changed root to %s.' % newroot) except Exception as e: _logger.error(' Failed to change root to %s: %s' % (newroot, str(e))) # # need to return environment. if root2return > 0: os.fchdir(root2return) os.chroot('.') os.close(root2return) raise OciMigrateException('Failed to change root to %s: %s' % (newroot, str(e))) try: # # adjust PATH to make sure. currentpath = os.environ['PATH'] newpath = currentpath.replace('/bin', '')\ .replace('/usr/bin', '')\ .replace('/sbin', '')\ .replace('/usr/sbin', '')\ .replace('/usr/local/sbin', '')\ .replace('::', ':') \ + ':/root/bin:/bin:/usr/bin:/usr/sbin:/usr/local/sbin:/sbin' os.environ['PATH'] = newpath _logger.debug('Set path to %s' % newpath) return root2return, currentpath, current_dir except Exception as e: _logger.error(' Failed to set path to %s: %s' % (newpath, str(e))) raise OciMigrateException('Failed to set path to %s: %s' % (newpath, str(e)))
def mount_imgfn(imgname): """ Link vm image with an nbd device. Parameters ---------- imgname: str Full path of the image file. Returns ------- str: Device name on success, raises an exception otherwise. """ # # create nbd devices _logger.debug('__ Running mount image file %s.' % imgname) result_msg(msg='Load nbd') if not system_tools.create_nbd(): raise OciMigrateException('Failed ot load nbd module') else: _logger.debug('nbd module loaded') # # find free nbd device result_msg(msg='Find free nbd device') devpath = system_tools.get_free_nbd() _logger.debug('Device %s is free.' % devpath) # # link img with first free nbd device result_msg(msg='Mount image %s' % imgname, result=True) _, nbcols = terminal_dimension() try: mountwait = ProgressBar(nbcols, 0.2, progress_chars=['mounting image']) mountwait.start() qemucmd = ['-c', devpath, imgname] pause_msg(qemucmd) qemunbd_ret = system_tools.exec_qemunbd(qemucmd) if qemunbd_ret == 0: time.sleep(5) _logger.debug('qemu-nbd %s succeeded' % qemucmd) return devpath else: _logger.critical('\n Failed to create nbd devices: %d' % qemunbd_ret) raise Exception('Failed to create nbd devices: %d' % qemunbd_ret) except Exception as e: _logger.critical('\n Something wrong with creating nbd devices: %s' % str(e)) raise OciMigrateException('Unable to create nbd devices: %s' % str(e)) finally: if system_tools.is_thread_running(mountwait): mountwait.stop()
def __init__(self, filename): """ Initialisation of the vmdk header analysis. Parameters ---------- filename: str Full path of the vmdk image file. """ super(VmdkHead, self).__init__(filename) _logger.debug('VMDK header size: %d bytes' % self.head_size) try: with open(self._fn, 'rb') as f: head_bin = f.read(self.head_size) _logger.debug('%s header successfully read' % self._fn) except Exception as e: _logger.critical(' Failed to read header of %s: %s' % (self._fn, str(e))) raise OciMigrateException('Failed to read the header of %s: %s' % (self._fn, str(e))) vmdkheader = struct.unpack(VmdkHead.vmdkhead_fmt, head_bin) try: with open(self._fn, 'rb') as f: f.seek(512) head_descr = [ it for it in f.read(1024).decode('utf-8').splitlines() if '=' in it ] except Exception as e: _logger.critical(' Failed to read description of %s: %s' % (self._fn, str(e))) raise OciMigrateException( 'Failed to read the description of %s: %s' % (self._fn, str(e))) self.stat = os.stat(self._fn) self.img_tag = os.path.splitext(os.path.split(self._fn)[1])[0] self.vmdkhead_dict = dict( (name[2], vmdkheader[i]) for i, name in enumerate(VmdkHead.header0_structure)) self.vmdkdesc_dict = dict( [re.sub(r'"', '', kv).split('=') for kv in head_descr]) self.img_header = dict() self.img_header['head'] = self.vmdkhead_dict self.img_header['desc'] = self.vmdkdesc_dict migrate_tools.result_msg(msg='Got image %s header' % filename, result=False)
def get_package_mgr_tool(): """ Find out which package to use for package manipulation (yum or dnf) and define the essential parameters. Returns ------- dict: dictionary with method and command parameters. """ # # look for package install tool. package_mgr_dict = dict() if bool(system_tools.exec_exists('dnf')): _logger.debug('Upgrade using dnf') package_mgr_dict['pkg_mgr'] = 'dnf' package_mgr_dict['package_available'] = ['--showduplicates', 'search'] package_mgr_dict['package_remove'] = ['erase', '-y'] package_mgr_dict['package_install'] = ['install', '-y'] elif bool(system_tools.exec_exists('yum')): _logger.debug('Upgrade using yum') package_mgr_dict['pkg_mgr'] = 'yum' package_mgr_dict['package_available'] = ['--showduplicates', 'search'] package_mgr_dict['package_remove'] = ['remove', '-y'] package_mgr_dict['package_install'] = ['install', '-y'] else: raise OciMigrateException('Failed to find upgrade tool') _logger.debug('Package install tool data:\n %s' % package_mgr_dict) return package_mgr_dict
def exec_vgscan(vgscan_args): """ Scan the system for (new) volume groups. Parameters ---------- vgscan_args: list list of strings, arguments for vgscan Returns ------- bool: True on success, raises an exeception on failure. """ cmd = ['vgscan'] + vgscan_args _logger.debug('__ Executing %s' % cmd) pause_msg(cmd) try: output = run_popen_cmd(cmd).decode('utf-8') _logger.debug('Volume groups scanned:\n%s' % str(output)) return True except Exception as e: # # vgscan failed _logger.critical(' Failed to scan for volume groups: %s' % str(e)) raise OciMigrateException('Failed to scan for volume groups: %s' % str(e))
def exec_lvscan(lvscan_args): """ Scan the system for logical volumes. Parameters ---------- lvscan_args: list list of strings, arguments for lvscan Returns ------- list: A list of strings, the output of lvscan --verbose on success, raises an exeception on failure. """ cmd = ['lvscan'] + lvscan_args _logger.debug('__ Running: %s' % cmd) pause_msg(cmd) try: _logger.debug('command: %s' % cmd) output = run_popen_cmd(cmd).decode('utf-8') _logger.debug('Logical volumes scanned:\n%s' % str(output)) return output.splitlines() except Exception as e: # # lvscan failed _logger.critical(' Failed to scan for logical volumes: %s' % str(e)) raise OciMigrateException('Failed to scan for logical volume: %s' % str(e))
def exec_pvscan(pvscan_args, devname=None): """ Update the lvm cache. Parameters ---------- pvscan_args: list List of strings, arguments for pvscan devname: str Device name to scan. Returns ------- bool: True on success, raises an exception on failure. """ _logger.debug('__ Running pvscan %s' % pvscan_args) cmd = ['pvscan'] + pvscan_args if devname is not None: cmd.append(devname) pause_msg(cmd) try: _logger.debug('command: %s' % cmd) cmdret = run_call_cmd(cmd) _logger.debug('Physical volumes scanned on %s: %d' % (devname, cmdret)) if cmdret != 0: _logger.error(' Physical volume scan failed.') raise Exception('Physical volume scan failed.') return True except Exception as e: # # pvscan failed _logger.critical(' Failed to scan %s for physical volumes: %s' % (devname, str(e))) raise OciMigrateException('Failed to scan %s for physical ' 'volumes: %s' % (devname, str(e)))
def mount_pseudo(rootdir): """ Remount proc, sys and dev. Parameters ---------- rootdir: str The mountpoint of the root partition. Returns ------- list: The list of new mountpoints on success, None otherwise. """ pseudodict = {'proc': ['-t', 'proc', 'none', '%s/proc' % rootdir], 'dev': ['-o', 'bind', '/dev', '%s/dev' % rootdir], 'sys': ['-o', 'bind', '/sys', '%s/sys' % rootdir]} pseudomounts = [] _logger.debug('__ Mounting: %s', pseudodict) for dirs, cmd_par in list(pseudodict.items()): cmd = ['mount'] + cmd_par _logger.debug('Mounting %s', dirs) pause_msg(cmd, pause_flag='_OCI_MOUNT') try: _logger.debug('Command: %s', cmd) cmdret = run_call_cmd(cmd) _logger.debug('%s : %d', cmd, cmdret) if cmdret != 0: _logger.error(' Failed to %s', cmd) raise Exception('%s Failed: %d' % (cmd, cmdret)) pseudomounts.append(cmd_par[3]) except Exception as e: _logger.critical(' Failed to %s: %s', cmd, str(e)) raise OciMigrateException('Failed to %s:' % cmd) from e return pseudomounts
def restore_nameserver(): """ Restore nameserver configuration. Returns ------- bool: True on success, False otherwise. """ _logger.debug('__ Restore nameserver data.') # global resolv_conf_path resolvpath = '/etc/resolv.conf' try: # # save used one if os.path.isfile(resolvpath): if not bool(exec_rename(resolvpath, resolvpath + '_temp_' + migrate_data.current_time)): _logger.debug('Failed to rename %s to %s, no harm done.', resolvpath, resolvpath + '_temp_' + migrate_data.current_time) else: _logger.debug('No %s found.', resolvpath) # # restore original one if os.path.isfile(migrate_data.resolv_conf_path): if bool(exec_rename(migrate_data.resolv_conf_path, resolvpath)): _logger.debug('Successfully restored %s', resolvpath) else: _logger.debug('Failed to restore %s.', resolvpath) raise OciMigrateException('Failed to restore nameserver config.') else: _logger.debug('No %s found.', migrate_data.resolv_conf_path) return True except Exception as e: error_msg('Continuing but might cause issues installing cloud-init: %s' % str(e)) return False
def read_from_url(url): """ Read from an url Parameters ---------- url: str The url. Returns ------- obj: the contents of the url on success, raises an exception otherwise. """ _logger.debug('__ Read from url %s.', url) # # to keep the encodings import in place _ = dir(encodings.idna) try: url_ref = requests.get(url) if url_ref.status_code != 200: raise Exception('url get status: %s while looking for %s' % (str(url_ref.status_code), url)) url_contents = url_ref.content url_ref.close() return url_contents except Exception as e: _logger.warning('Failed to read from %s: %s', url, str(e)) raise OciMigrateException('Failed to read from %s: %s' % (url, str(e)))
def leave_chroot(root2return, dir2return): """ Leave a chroot environment and return to another one. Parameters ---------- root2return: file descriptor The file descriptor of the root to return to. dir2return: str The original working dir to return to. Returns ------- bool: True on success, raises exception on failure. """ _logger.debug('__ Leaving chroot jail.') try: # # leave chroot os.fchdir(root2return) os.chroot('.') os.close(root2return) _logger.debug('Left change root environment.') # # return to working directory os.chdir(dir2return) return True except Exception as e: _logger.error(' Failed to return from chroot: %s' % str(e)) OciMigrateException('Failed to return from chroot: %s' % str(e))
def upload_image(imgname, bucket_name, ociname): """ Upload the validated and updated image imgname to the OCI object storage bucket_name as ociname. Parameters ---------- imgname: str The on-premise custom image. bucket_name: str The OCI object storage name. ociname: The OCI image name. Returns ------- bool: True on success, raises an exception otherwise. """ cmd = ['oci', 'os', 'object', 'put', '--bucket-name', bucket_name, '--file', imgname, '--name', ociname, '--part-size', '100', '--parallel-upload-count', '6'] _logger.debug('__ Running %s', cmd) pause_msg(cmd) try: upload_result = system_tools.run_popen_cmd(cmd)['output'].decode('utf-8') _logger.debug('Successfully uploaded %s to %s as %s: %s.', imgname, bucket_name, ociname, upload_result) return True except Exception as e: _logger.critical(' Failed to upload %s to object storage %s as %s: %s.', imgname, bucket_name, ociname, str(e)) raise OciMigrateException('Failed to upload %s to object storage %s as %s:' % (imgname, bucket_name, ociname)) from e
def get_lifecycle_state(display_name, compartment_id): """ Collect the lifecycle state of on object in a compartment. Parameters ---------- display_name: str The object name. compartment_id: str The compartment ocid. Returns ------- str: the lifecycle state. """ _logger.debug('__ Retrieving the lifecycle state of %s', display_name) cmd = ['oci', 'compute', 'image', 'list', '--compartment-id', '%s' % compartment_id, '--display-name', '%s' % display_name] try: object_list = json.loads(system_tools.run_popen_cmd(cmd)['output'].decode('utf-8')) for object_x in object_list['data']: if object_x['display-name'] == display_name: return object_x['lifecycle-state'] _logger.debug('object %s not found.', display_name) return None except Exception as e: raise OciMigrateException('Failed to collect the compute image list:') from e
def __init__(self, filename): """ Initialisation of the qcow2 header analysis. Parameters ---------- filename: str Full path of the qcow2 image file. """ _logger.debug('qcow2 header size: %d bytes', self.head_size) super().__init__(filename) head_size = struct.calcsize(Qcow2Head.qcowhead_fmt) try: with open(self._fn, 'rb') as f: head_bin = f.read(head_size) _logger.debug('%s header successfully read', self._fn) except Exception as e: _logger.critical(' Failed to read header of %s: %s', self._fn, str(e)) raise OciMigrateException('Failed to read the header of %s' % self._fn) from e qcow2header = struct.unpack(Qcow2Head.qcowhead_fmt, head_bin) self.stat = os.stat(self._fn) self.img_tag = os.path.splitext(os.path.split(self._fn)[1])[0] self.qcowhead_dict = dict( (name[2], qcow2header[i]) for i, name in enumerate(Qcow2Head.header2_structure)) self.img_header = dict() self.img_header['head'] = self.qcowhead_dict result_msg(msg='Got image %s header' % filename, result=False)
def exec_search(file_name, rootdir='/', dirnames=False): """ Find the filename in the rootdir tree. Parameters ---------- file_name: str The filename to look for. rootdir: str The directory to start from, default is root. dirnames: bool If True, also consider directory names. Returns ------- str: The full path of the filename if found, None otherwise. """ _logger.debug('__ Looking for %s in %s', file_name, rootdir) result_msg(msg='Looking for %s in %s, might take a while.' % (file_name, rootdir)) try: for path_name, directories, files in os.walk(rootdir): # _logger.debug('%s %s %s', path_name, directories, files) if file_name in files: _logger.debug('Found %s', os.path.join(rootdir, path_name, file_name)) return os.path.join(rootdir, path_name, file_name) if dirnames and file_name in directories: _logger.debug('Found %s as directory.', os.path.join(rootdir, path_name, file_name)) return os.path.join(rootdir, path_name, file_name) except Exception as e: _logger.error(' Error while looking for %s: %s', file_name, str(e)) raise OciMigrateException('Error while looking for %s:' % file_name) from e return None
def read_from_url(url): """ Read from an url Parameters ---------- url: str The url. Returns ------- obj: the contents of the url on success, raises an exception otherwise. """ _logger.debug('__ Read from url %s.', url) # # to keep the encodings import in place _ = dir(encodings.idna) try: url_request = Request(url=url, headers={'Authorization': 'Bearer Oracle'}) with urlopen(url_request) as url_ref: if url_ref.status != 200: raise Exception('url get status: %s while looking for %s' % (str(url_ref.status), url)) url_contents = url_ref.read() return url_contents except Exception as e: _logger.warning('Failed to read from %s: %s', url, str(e)) raise OciMigrateException('Failed to read from %s' % url) from e
def b10_is_cloud_init_enabled(): """ Verify if cloud-init package is enabled after install. Returns ------- bool: True on success, False otherwise. """ _logger.debug('__ Is cloud-init enabled.') cmd = ['systemctl', 'list-unit-files'] enabled = False try: _logger.debug('command: %s', cmd) output = system_tools.run_popen_cmd(cmd)['output'].decode( 'utf-8').splitlines() for service in output: svc = service.split() if len(service) > 1 else ['a', 'b'] if 'cloud-init' in svc[0]: _logger.debug('Found service cloud-init: %s', svc) if svc[-1] == 'enabled': _logger.debug('Service cloud-init is enabled.') enabled = True break return enabled except Exception as e: _logger.warning(' Failed to execute systemctl: %s', str(e)) raise OciMigrateException('\nFailed to execute systemctl: ') from e
def bucket_exists(bucket_name): """ Verify if bucket_name exits. Parameters ---------- bucket_name: str The bucket_name. Returns ------- dict: The bucket on success, raise an exception otherwise """ cmd = [ 'oci', 'os', 'object', 'list', '--all', '--bucket-name', bucket_name ] _logger.debug('__ Running %s.', cmd) pause_msg(cmd) try: bucket_result = json.loads( system_tools.run_popen_cmd(cmd)['output'].decode('utf-8')) _logger.debug('Result: \n%s', bucket_result) return bucket_result except Exception as e: _logger.debug( 'Bucket %s does not exists or the authorisation is missing: %s.', bucket_name, str(e)) raise OciMigrateException( 'Bucket %s does not exists or the authorisation is missing:' % bucket_name) from e
def find_compartment_id(compartment, compartment_dict): """ Find the compartment ocid for compartment in the compartment dictinary. Parameters ---------- compartment: str The compartment name. compartment_dict: dict The dictionary containing data for all? compartments in this tenancy. Returns ------- str: the ocid of the compartment on success, raises an exception on failure. """ _logger.debug('__ Looking for the ocid of compartment %s', compartment) for _, v in list(compartment_dict.items()): for x in v: if x['name'] == compartment: compartment_data = x console_msg(msg='Compartment: %s' % compartment_data['name']) compartment_id = compartment_data['id'] return compartment_id raise OciMigrateException('Failed to find the ocid for %s' % compartment)
def collect_image_data(img_object): """ Verify the prerequisites of the image file with respect to the migration to the Oracle Cloud Infrastructure. Parameters ---------- img_object: Qcow2Head, VmdkHead, TemplateTypeHead.. object The image object. Returns ------- dict: The image data. """ _logger.debug('__ Collect the image data.') try: res, img_info = img_object.image_data() except Exception as e: _logger.critical(' Unable to collect or invalid image data: %s' % str(e), exc_info=True) raise OciMigrateException('Unable to collect or invalid image data: %s' % str(e)) # need to return the img_info object in the end... return res, img_info
def mount_partition(devname, mountpoint=None): """ Create the mountpoint /mnt/<last part of device specification> and mount a partition on on this mountpoint. Parameters ---------- devname: str The full path of the device. mountpoint: str The mountpoint, will be generated if not provided. Returns ------- str: The mounted partition on Success, None otherwise. """ _logger.debug('__ Mount partition %s.', devname) # # create mountpoint /mnt/<devname> if not specified. if mountpoint is None: mntpoint = migrate_data.loopback_root + '/' + devname.rsplit('/')[-1] _logger.debug('Loopback mountpoint: %s', mntpoint) try: if system_tools.exec_mkdir(mntpoint): _logger.debug('Mountpoint: %s created.', mntpoint) except Exception as e: _logger.critical(' Failed to create mountpoint %s: %s', mntpoint, str(e)) raise OciMigrateException('Failed to create mountpoint %s:' % mntpoint) from e else: mntpoint = mountpoint # # actual mount cmd = ['mount', devname, mntpoint] pause_msg(cmd, pause_flag='_OCI_MOUNT') _, nbcols = terminal_dimension() try: mountpart = ProgressBar(nbcols, 0.2, progress_chars=['mount %s' % devname]) mountpart.start() _logger.debug('command: %s', cmd) cmdret = system_tools.run_call_cmd(cmd) if cmdret == 0: _logger.debug('%s mounted on %s.', devname, mntpoint) return mntpoint raise Exception('Mount %s failed: %d' % (devname, cmdret)) except Exception as e: # # mount failed, need to remove mountpoint. _logger.critical(' Failed to mount %s, missing driver, filesystem corruption...: %s', devname, str(e)) if mountpoint is None: if system_tools.exec_rmdir(mntpoint): _logger.debug('%s removed', mntpoint) else: _logger.critical(' Failed to remove mountpoint %s', mntpoint) finally: if system_tools.is_thread_running(mountpart): mountpart.stop() return None
def get_oci_config(section='DEFAULT'): """ Read the oci configuration file. Parameters ---------- section: str The section from the oci configuration file. DEFAULT is the default. (todo: add command line option to use other user/sections) Returns ------- dict: the contents of the configuration file as a dictionary. """ _logger.debug('__ Reading the %s configuration file.' % get_config_data('ociconfigfile')) oci_config_file = get_config_data('ociconfigfile') _logger.debug('oci config file path: %s' % oci_config_file) if oci_config_file.startswith('~/'): oci_config_file = os.path.expanduser('~') + oci_config_file[1:] _logger.debug('oci config file expected at %s' % oci_config_file) oci_cli_configer = ConfigParser() try: rf = oci_cli_configer.read(oci_config_file) sectiondata = dict(oci_cli_configer.items(section)) _logger.debug('OCI configuration: %s' % sectiondata) return sectiondata except Exception as e: _logger.error(' Failed to read OCI configuration %s: %s.' % (get_config_data('ociconfigfile'), str(e))) raise OciMigrateException('Failed to read OCI configuration %s: %s.' % (get_config_data('ociconfigfile'), str(e)))
def image_data(self): """ Collect data about contents of the image file. Returns ------- bool: True on success, False otherwise; dict: The image data. """ _logger.debug('Image data: %s' % self._fn) # # initialise the dictionary for the image data self._img_info['img_name'] = self._fn self._img_info['img_type'] = 'VMDK' self._img_info['img_header'] = self.img_header self._img_info['img_size'] = self.image_size() # # mount the image using the nbd try: result = self.handle_image() except Exception as e: _logger.critical(' Error %s' % str(e)) raise OciMigrateException(str(e)) return result, self._img_info
def exec_rename(some_name, to_name=None): """ Renames a file, symbolic link or directory to path/bck_filename_current_time. Parameters ---------- some_name: str Full path of the original file. to_name: str Full path of the destination file, if specified, using default otherwise. Returns ------- str: the path of the renamed file on success, None otherwise. """ if not bool(to_name): to_name = generate_backup_name(some_name) _logger.debug('__ Rename %s to %s' % (some_name, to_name)) # try: # # delete to_ if already exists # # if file, symlink or directory if os.path.exists(to_name): _logger.debug('%s already exists' % to_name) if os.path.isfile(to_name): os.remove(to_name) elif os.path.isdir(to_name): os.rmdir(to_name) elif os.path.islink(to_name): if os.unlink(to_name): _logger.debug('Removed symbolic link %s' % to_name) else: _logger.error(' Failed to remove symbolic link %s' % to_name) else: _logger.error(' Failed to remove %s.' % to_name) else: _logger.debug('%s does not exists' % to_name) # # rename if os.path.exists(some_name) or os.path.islink(some_name): _logger.debug('%s exists and is a file or symbolic link.' % some_name) os.rename(some_name, to_name) _logger.debug('Renamed %s to %s.' % (some_name, to_name)) return to_name else: _logger.debug(' %s does not exists' % some_name) except Exception as e: _logger.error(' Failed to rename %s to %s: %s' % (some_name, to_name, str(e))) raise OciMigrateException('Failed to rename %s to %s: %s' % (some_name, to_name, str(e))) return None
def __init__(self, filename): """ Initialisation of the templatetype header analysis. Parameters ---------- filename: str Full path of the template_type image file. """ super(TemplateTypeHead, self).__init__(filename) _logger.debug('templatetype header size: %d bytes' % self.head_size) try: with open(self._fn, 'rb') as f: head_bin = f.read(self.head_size) _logger.debug('%s header successfully read' % self._fn) except Exception as e: _logger.critical(' Failed to read header of %s: %s' % (self._fn, str(e))) raise OciMigrateException('Failed to read the header of %s: %s' % (self._fn, str(e))) templatetypeheader = struct.unpack(TemplateTypeHead.templatetypehead_fmt, head_bin) self.stat = os.stat(self._fn) self.img_tag = os.path.splitext(os.path.split(self._fn)[1])[0] self.templatehead_dict = dict((name[2], templatetypeheader[i]) for i, name in enumerate(TemplateTypeHead.header2_structure)) self.img_header = dict() self.img_header['head'] = self.templatehead_dict migrate_tools.result_msg(msg='Got image %s header' % filename, result=False) # # mount the image using the nbd try: self.devicename = self.mount_img() _logger.debug('Image data %s' % self.devicename) migrate_tools.result_msg(msg='Mounted %s' % self.devicename, result=False) deviceinfo = self.handle_image() except Exception as e: _logger.critical(' Error %s' % str(e)) raise OciMigrateException(str(e))
def run_popen_cmd(command): """ Execute an os command and collect stdout and stderr. Parameters ---------- command: list The os command and its arguments. Returns ------- <type>: The output of the command on success, raises an exception on failure. """ _logger.debug('__ Executing %s.' % command) if exec_exists(command[0]) is not None: _logger.debug('running %s' % command) try: ext_process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = ext_process.communicate() retcode = ext_process.returncode if retcode != 0: if error: _logger.debug('Error occured while running %s: %s - %s' % (command, retcode, error.decode('utf-8')), exc_info=True) raise OciMigrateException( 'Error encountered while running %s: ' '%s - %s' % (command, retcode, error.decode('utf-8'))) # _logger.debug('output from %s: %s' % (command, output)) if output: return output except OSError as oserr: raise OciMigrateException('OS error encountered while ' 'running %s: %s' % (command, str(oserr))) except Exception as e: raise OciMigrateException( 'Error encountered while running %s: %s' % (command, str(e))) else: _logger.critical(' %s not found.' % command[0]) raise OciMigrateException('%s does not exist' % command[0])
def unmount_imgfn(devname): """ Unlink a device. Parameters ---------- devname: str The device name Returns ------- bool: True on succes, raise an exception otherwise. """ _logger.debug('__ Unmount %s' % devname) try: # # release device qemucmd = ['-d', devname] pause_msg(qemucmd) qemunbd_ret = system_tools.exec_qemunbd(qemucmd) if qemunbd_ret == 0: _logger.debug('qemu-nbd %s succeeded: %d' % (qemucmd, qemunbd_ret)) else: raise Exception('%s returned %d' % (qemucmd, qemunbd_ret)) # # clear lvm cache, if necessary. if system_tools.exec_pvscan(['--cache']): _logger.debug('lvm cache updated') else: _logger.error(' Failed to clear LVM cache.') raise OciMigrateException('Failed to clear LVM cache.') # # remove nbd module if not system_tools.rm_nbd(): raise OciMigrateException('Failed to remove nbd module.') else: _logger.debug('Successfully removed nbd module.') except Exception as e: _logger.critical(' Something wrong with removing nbd devices: %s' % str(e)) raise OciMigrateException('\nSomething wrong with removing nbd ' 'devices: %s' % str(e)) return True