def _disable_lvm2_lvmetad(ssh): """Disables lvm2-lvmetad service. This service is responsible for automatically activating LVM2 volume groups when a disk is attached or when a volume group is created. During disk replication this service needs to be disabled. """ cfg = "/etc/lvm/lvm.conf" if utils.test_ssh_path(ssh, cfg): utils.exec_ssh_cmd( ssh, 'sudo sed -i "s/use_lvmetad.*=.*1/use_lvmetad = 0/g" ' '%s' % cfg, get_pty=True) # NOTE: lvm2-lvmetad is the name of the lvmetad service # on both debian and RHEL based systems. It needs to be stopped # before we begin disk replication. We disable it in the config # just in case some other process starts the daemon later on, as # a dependency. As the service may not actually exist, even though # the config is present, we ignore errors when stopping it. utils.ignore_exceptions(utils.exec_ssh_cmd)( ssh, "sudo service lvm2-lvmetad stop", get_pty=True) # disable volume groups. Any volume groups that have volumes in use # will remain online. However, volume groups belonging to disks # that have been synced at least once, will be deactivated. utils.ignore_exceptions(utils.exec_ssh_cmd)( ssh, "sudo vgchange -an", get_pty=True)
def _find_and_mount_root(self, devices): files = ["etc", "bin", "sbin", "boot"] os_root_dir = None os_root_device = self._find_dev_with_contents(devices, all_files=files) if os_root_device is None: raise exception.OperatingSystemNotFound( "Coriolis was unable to identify the root partition of the OS " "being migrated for mounting during OSMorphing. Please ensure " "that the source VM's root partition(s) are not encrypted, " "and that they are using a filesystem type and version which " "is supported by the OS images used for the OSMorphing minion " "machine. Also ensure that the source VM's mountpoint " "declarations in '/etc/fstab' are all correct, and are " "declared using '/dev/disk/by-uuid/' or 'UUID=' notation. " "If all else fails, please retry while using an OSMorphing " "minion machine image which is the same OS release as the VM " "being migrated.") try: tmp_dir = self._exec_cmd('mktemp -d').decode().splitlines()[0] self._exec_cmd('sudo mount %s %s' % (os_root_device, tmp_dir)) os_root_dir = tmp_dir except Exception as ex: self._event_manager.progress_update( "Exception occurred while Coriolis was attempting to mount the" " root device (%s) of the OS being migrated for OSMorphing. " "Please ensure that the source VM's root partition(s) are " "using a filesystem type and version which is supported by the" " OS images used for the OSMorphing minion machine. Also " "ensure that the source VM's mountpoint declarations in " "'/etc/fstab' are all correct, and are declared using " "'/dev/disk/by-uuid/' or 'UUID=' notation. If all else fails, " "please retry while using an OSMorphing minion machine image " "which is the same OS release as the VM being migrated. Error " "was: %s" % (os_root_device, str(ex))) LOG.error(ex) LOG.warn("Failed to mount root device '%s':\n%s", os_root_device, utils.get_exception_details()) utils.ignore_exceptions(self._exec_cmd)("sudo umount %s" % tmp_dir) utils.ignore_exceptions(self._exec_cmd)("sudo rmdir %s" % tmp_dir) raise for directory in ['proc', 'sys', 'dev', 'run']: mount_dir = os.path.join(os_root_dir, directory) if not utils.test_ssh_path(self._ssh, mount_dir): LOG.info("No '%s' directory in mounted OS. Skipping mount.", directory) continue self._exec_cmd('sudo mount -o bind /%(dir)s/ %(mount_dir)s' % { 'dir': directory, 'mount_dir': mount_dir }) if os_root_device in devices: devices.remove(os_root_device) return os_root_dir, os_root_device
def _find_dev_with_contents(self, devices, all_files=None, one_of_files=None): if all_files and one_of_files: raise exception.CoriolisException( "all_files and one_of_files are mutually exclusive") dev_name = None for dev_path in devices: dirs = None tmp_dir = self._exec_cmd('mktemp -d').decode().splitlines()[0] try: self._exec_cmd('sudo mount %s %s' % (dev_path, tmp_dir)) # NOTE: it's possible that the device was mounted successfully # but an I/O error occurs later along the line: dirs = utils.list_ssh_dir(self._ssh, tmp_dir) except Exception: self._event_manager.progress_update( "Failed to mount and scan device '%s'" % dev_path) LOG.warn( "Failed to mount and scan device '%s':\n%s", dev_path, utils.get_exception_details()) utils.ignore_exceptions(self._exec_cmd)( "sudo umount %s" % tmp_dir ) utils.ignore_exceptions(self._exec_cmd)( "sudo rmdir %s" % tmp_dir ) continue LOG.debug("Contents of device %s:\n%s", dev_path, dirs) if all_files and dirs: common = [i if i in dirs else None for i in all_files] if not all(common): self._exec_cmd('sudo umount %s' % tmp_dir) continue dev_name = dev_path self._exec_cmd('sudo umount %s' % tmp_dir) elif one_of_files and dirs: common = [i for i in one_of_files if i in dirs] if len(common) > 0: dev_name = dev_path self._exec_cmd('sudo umount %s' % tmp_dir) break else: self._exec_cmd('sudo umount %s' % tmp_dir) continue return dev_name
def _find_and_mount_root(self, devices): files = ["etc", "bin", "sbin", "boot"] os_root_dir = None os_root_device = self._find_dev_with_contents( devices, all_files=files) if os_root_device is None: raise exception.OperatingSystemNotFound( "root partition not found") try: tmp_dir = self._exec_cmd('mktemp -d').decode().splitlines()[0] self._exec_cmd('sudo mount %s %s' % (os_root_device, tmp_dir)) os_root_dir = tmp_dir except Exception: self._event_manager.progress_update( "Failed to mount root device '%s'" % os_root_device) LOG.warn( "Failed to mount root device '%s':\n%s", os_root_device, utils.get_exception_details()) utils.ignore_exceptions(self._exec_cmd)( "sudo umount %s" % tmp_dir ) utils.ignore_exceptions(self._exec_cmd)( "sudo rmdir %s" % tmp_dir ) raise for directory in ['proc', 'sys', 'dev', 'run']: mount_dir = os.path.join(os_root_dir, directory) if not utils.test_ssh_path(self._ssh, mount_dir): LOG.info( "No '%s' directory in mounted OS. Skipping mount.", directory) continue self._exec_cmd( 'sudo mount -o bind /%(dir)s/ %(mount_dir)s' % {'dir': directory, 'mount_dir': mount_dir}) if os_root_device in devices: devices.remove(os_root_device) return os_root_dir, os_root_device
def _reconnect_ssh(self): if self._ssh: utils.ignore_exceptions(self._ssh.close)() self._ssh = self._setup_ssh() return self._ssh
def __del__(self): if self._cert_dir is not None: utils.ignore_exceptions(shutil.rmtree)(self._cert_dir)