def plug_ivs_hybrid(self, instance, vif): """Plug using hybrid strategy (same as OVS) Create a per-VIF linux bridge, then link that bridge to the OVS integration bridge via a veth device, setting up the other end of the veth device just like a normal IVS port. Then boot the VIF on the linux bridge using standard libvirt mechanisms. """ super(LibvirtGenericVIFDriver, self).plug(instance, vif) iface_id = self.get_ovs_interfaceid(vif) br_name = self.get_br_name(vif['id']) v1_name, v2_name = self.get_veth_pair_names(vif['id']) if not linux_net.device_exists(br_name): utils.execute('brctl', 'addbr', br_name, run_as_root=True) utils.execute('brctl', 'setfd', br_name, 0, run_as_root=True) utils.execute('brctl', 'stp', br_name, 'off', run_as_root=True) if not linux_net.device_exists(v2_name): linux_net._create_veth_pair(v1_name, v2_name) utils.execute('ip', 'link', 'set', br_name, 'up', run_as_root=True) utils.execute('brctl', 'addif', br_name, v1_name, run_as_root=True) linux_net.create_ivs_vif_port(v2_name, iface_id, vif['address'], instance['uuid'])
def cache(self, fetch_func, filename, size=None, *args, **kwargs): """Creates image from template. Ensures that template and image not already exists. Ensures that base directory exists. Synchronizes on template fetching. :fetch_func: Function that creates the base image Should accept `target` argument. :filename: Name of the file in the image directory :size: Size of created image in bytes (optional) """ @utils.synchronized(filename, external=True, lock_path=self.lock_path) def fetch_func_sync(target, *args, **kwargs): fetch_func(target=target, *args, **kwargs) base_dir = os.path.join(CONF.instances_path, CONF.image_cache_subdirectory_name) if not os.path.exists(base_dir): fileutils.ensure_tree(base_dir) base = os.path.join(base_dir, filename) if not self.check_image_exists() or not os.path.exists(base): self.create_image(fetch_func_sync, base, size, *args, **kwargs) if (size and self.preallocate and self._can_fallocate() and os.access(self.path, os.W_OK)): utils.execute('fallocate', '-n', '-l', size, self.path)
def clear_logical_volume(path): """Obfuscate the logical volume. :param path: logical volume path """ # TODO(p-draigbrady): We currently overwrite with zeros # but we may want to make this configurable in future # for more or less security conscious setups. vol_size = logical_volume_size(path) bs = 1024 * 1024 direct_flags = ('oflag=direct',) sync_flags = () remaining_bytes = vol_size # The loop caters for versions of dd that # don't support the iflag=count_bytes option. while remaining_bytes: zero_blocks = remaining_bytes / bs seek_blocks = (vol_size - remaining_bytes) / bs zero_cmd = ('dd', 'bs=%s' % bs, 'if=/dev/zero', 'of=%s' % path, 'seek=%s' % seek_blocks, 'count=%s' % zero_blocks) zero_cmd += direct_flags zero_cmd += sync_flags if zero_blocks: utils.execute(*zero_cmd, run_as_root=True) remaining_bytes %= bs bs /= 1024 # Limit to 3 iterations # Use O_DIRECT with initial block size and fdatasync otherwise direct_flags = () sync_flags = ('conv=fdatasync',)
def test_create_configdrive_vfat(self): imagefile = None try: self.mox.StubOutWithMock(utils, 'mkfs') self.mox.StubOutWithMock(utils, 'execute') self.mox.StubOutWithMock(utils, 'trycmd') utils.mkfs('vfat', mox.IgnoreArg(), label='config-2').AndReturn(None) utils.trycmd('mount', '-o', mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), run_as_root=True).AndReturn((None, None)) utils.execute('umount', mox.IgnoreArg(), run_as_root=True).AndReturn(None) self.mox.ReplayAll() with configdrive.ConfigDriveBuilder() as c: c._add_file('this/is/a/path/hello', 'This is some content') (fd, imagefile) = tempfile.mkstemp(prefix='cd_vfat_') os.close(fd) c._make_vfat(imagefile) # Check cleanup self.assertFalse(os.path.exists(c.tempdir)) # NOTE(mikal): we can't check for a VFAT output here because the # filesystem creation stuff has been mocked out because it # requires root permissions finally: if imagefile: utils.delete_if_exists(imagefile)
def create_cow_image(backing_file, path, size=None): """Create COW image Creates a COW image with the given backing file :param backing_file: Existing image on which to base the COW image :param path: Desired location of the COW image """ base_cmd = ['qemu-img', 'create', '-f', 'qcow2'] cow_opts = [] if backing_file: cow_opts += ['backing_file=%s' % backing_file] base_details = images.qemu_img_info(backing_file) else: base_details = None # Explicitly inherit the value of 'cluster_size' property of a qcow2 # overlay image from its backing file. This can be useful in cases # when people create a base image with a non-default 'cluster_size' # value or cases when images were created with very old QEMU # versions which had a different default 'cluster_size'. if base_details and base_details.cluster_size is not None: cow_opts += ['cluster_size=%s' % base_details.cluster_size] if size is not None: cow_opts += ['size=%s' % size] if cow_opts: # Format as a comma separated list csv_opts = ",".join(cow_opts) cow_opts = ['-o', csv_opts] cmd = base_cmd + cow_opts + [path] utils.execute(*cmd)
def copy_image(src, dest, host=None, receive=False, on_execute=None, on_completion=None, compression=True): """Copy a disk image to an existing directory :param src: Source image :param dest: Destination path :param host: Remote host :param receive: Reverse the rsync direction :param on_execute: Callback method to store pid of process in cache :param on_completion: Callback method to remove pid of process from cache :param compression: Allows to use rsync operation with or without compression """ if not host: # We shell out to cp because that will intelligently copy # sparse files. I.E. holes will not be written to DEST, # rather recreated efficiently. In addition, since # coreutils 8.11, holes can be read efficiently too. # we add '-r' argument because ploop disks are directories utils.execute('cp', '-r', src, dest) else: if receive: src = "%s:%s" % (utils.safe_ip_format(host), src) else: dest = "%s:%s" % (utils.safe_ip_format(host), dest) remote_filesystem_driver = remotefs.RemoteFilesystem() remote_filesystem_driver.copy_file(src, dest, on_execute=on_execute, on_completion=on_completion, compression=compression)
def unmnt_dev(self): """Unmount the device from the file system.""" if not self.mounted: return LOG.debug(_("Umount %s") % self.mapped_device) utils.execute('umount', self.mapped_device, run_as_root=True) self.mounted = False
def plug_iovisor(self, instance, vif): """Plug using PLUMgrid IO Visor Driver Connect a network device to their respective Virtual Domain in PLUMgrid Platform. """ super(LibvirtGenericVIFDriver, self).plug(instance, vif) dev = self.get_vif_devname(vif) iface_id = vif["id"] linux_net.create_tap_dev(dev) net_id = vif["network"]["id"] tenant_id = instance["project_id"] try: utils.execute("ifc_ctl", "gateway", "add_port", dev, run_as_root=True) utils.execute( "ifc_ctl", "gateway", "ifup", dev, "access_vm", vif["network"]["label"] + "_" + iface_id, vif["address"], "pgtag2=%s" % net_id, "pgtag1=%s" % tenant_id, run_as_root=True, ) except processutils.ProcessExecutionError: LOG.exception(_("Failed while plugging vif"), instance=instance)
def _make_vfat(self, path): # NOTE(mikal): This is a little horrible, but I couldn't find an # equivalent to genisoimage for vfat filesystems. with open(path, 'wb') as f: f.truncate(CONFIGDRIVESIZE_BYTES) utils.mkfs('vfat', path, label='config-2') mounted = False try: mountdir = tempfile.mkdtemp(dir=CONF.config_drive_tempdir, prefix='cd_mnt_') _out, err = utils.trycmd('mount', '-o', 'loop,uid=%d,gid=%d' % (os.getuid(), os.getgid()), path, mountdir, run_as_root=True) if err: raise exception.ConfigDriveMountFailed(operation='mount', error=err) mounted = True # NOTE(mikal): I can't just use shutils.copytree here, because the # destination directory already exists. This is annoying. for ent in os.listdir(self.tempdir): shutil.copytree(os.path.join(self.tempdir, ent), os.path.join(mountdir, ent)) finally: if mounted: utils.execute('umount', mountdir, run_as_root=True) shutil.rmtree(mountdir)
def mkswap(dev, label='swap1'): """Execute mkswap on a device.""" utils.execute('mkswap', '-L', label, dev, run_as_root=True, check_exit_code=[0])
def _sign_csr(csr_text, ca_folder): with utils.tempdir() as tmpdir: inbound = os.path.join(tmpdir, 'inbound.csr') outbound = os.path.join(tmpdir, 'outbound.csr') try: with open(inbound, 'w') as csrfile: csrfile.write(csr_text) except IOError: LOG.exception(_('Failed to write inbound.csr')) raise LOG.debug(_('Flags path: %s'), ca_folder) start = os.getcwd() # Change working dir to CA fileutils.ensure_tree(ca_folder) os.chdir(ca_folder) utils.execute('openssl', 'ca', '-batch', '-out', outbound, '-config', './openssl.cnf', '-infiles', inbound) out, _err = utils.execute('openssl', 'x509', '-in', outbound, '-serial', '-noout') serial = string.strip(out.rpartition('=')[2]) os.chdir(start) with open(outbound, 'r') as crtfile: return (serial, crtfile.read())
def _decrypt_image(self, context, encrypted_filename, encrypted_key, encrypted_iv, decrypted_filename): elevated = context.elevated() try: key = self.cert_rpcapi.decrypt_text(elevated, project_id=context.project_id, text=base64.b64encode(encrypted_key)) except Exception as exc: msg = _('Failed to decrypt private key: %s') % exc raise exception.NovaException(msg) try: iv = self.cert_rpcapi.decrypt_text(elevated, project_id=context.project_id, text=base64.b64encode(encrypted_iv)) except Exception as exc: raise exception.NovaException(_('Failed to decrypt initialization ' 'vector: %s') % exc) try: utils.execute('openssl', 'enc', '-d', '-aes-128-cbc', '-in', '%s' % (encrypted_filename,), '-K', '%s' % (key,), '-iv', '%s' % (iv,), '-out', '%s' % (decrypted_filename,)) except processutils.ProcessExecutionError as exc: raise exception.NovaException(_('Failed to decrypt image file ' '%(image_file)s: %(err)s') % {'image_file': encrypted_filename, 'err': exc.stdout})
def unmap_dev(self): """Remove partitions of the device from the file system namespace.""" if not self.mapped: return if self.partition: utils.execute('kpartx', '-d', self.device, run_as_root=True) self.mapped = False
def teardown_container(container_dir, container_root_device=None): """Teardown the container rootfs mounting once it is spawned. It will umount the container that is mounted, and delete any linked devices. """ try: img = _DiskImage(image=None, mount_dir=container_dir) img.teardown() # Make sure container_root_device is released when teardown container. if container_root_device: if 'loop' in container_root_device: LOG.debug("Release loop device %s", container_root_device) utils.execute('losetup', '--detach', container_root_device, run_as_root=True, attempts=3) elif 'nbd' in container_root_device: LOG.debug('Release nbd device %s', container_root_device) utils.execute('qemu-nbd', '-d', container_root_device, run_as_root=True) else: LOG.debug('No release necessary for block device {0!s}'.format( container_root_device)) except Exception: LOG.exception(_LE('Failed to teardown container filesystem'))
def generate_winrm_x509_cert(user_id, bits=2048): """Generate a cert for passwordless auth for user in project.""" subject = '/CN=%s' % user_id upn = '%s@localhost' % user_id with utils.tempdir() as tmpdir: keyfile = os.path.abspath(os.path.join(tmpdir, 'temp.key')) conffile = os.path.abspath(os.path.join(tmpdir, 'temp.conf')) _create_x509_openssl_config(conffile, upn) (certificate, _err) = utils.execute( 'openssl', 'req', '-x509', '-nodes', '-days', '3650', '-config', conffile, '-newkey', 'rsa:%s' % bits, '-outform', 'PEM', '-keyout', keyfile, '-subj', subject, '-extensions', 'v3_req_client', binary=True) (out, _err) = utils.execute('openssl', 'pkcs12', '-export', '-inkey', keyfile, '-password', 'pass:'******'ascii') certificate = certificate.decode('utf-8') return (private_key, certificate, fingerprint)
def __init__(self, driver, context, instance, image_meta): PCSTemplate.__init__(self, driver, context, instance, image_meta) self.driver = driver self.rpm_path = None self.instance = instance name, version, release = self._get_remote_info(context, image_meta) lname, lversion, lrelease = self._get_rpm_info(pkg=name) LOG.info("Glance template: %s-%s-%s, local rpm: %s-%s-%s" % (name, version, release, lname, lversion, lrelease)) self.name = name[:-3] if not lname: self._download_rpm(context, image_meta) LOG.info("installing rpm for template %s" % name) utils.execute('rpm', '-i', self.rpm_path, run_as_root=True) else: x = self._cmp_version_release(version, release, lversion, lrelease) if x == 0: return elif x < 0: self._download_rpm(context, image_meta) LOG.info("updating rpm for template %s" % name) utils.execute('rpm', '-U', file, run_as_root=True) else: LOG.warn("local rpm is newer than remote one!")
def attach(self, instance, vif, container_id): vif_type = vif['type'] if_remote_name = 'ns%s' % vif['id'][:11] gateway = network.find_gateway(instance, vif['network']) ip = network.find_fixed_ip(instance, vif['network']) LOG.debug('attach vif_type=%(vif_type)s instance=%(instance)s ' 'vif=%(vif)s', {'vif_type': vif_type, 'instance': instance, 'vif': vif}) try: utils.execute('ip', 'link', 'set', if_remote_name, 'netns', container_id, run_as_root=True) utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'link', 'set', if_remote_name, 'address', vif['address'], run_as_root=True) utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'addr', 'add', ip, 'dev', if_remote_name, run_as_root=True) utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'link', 'set', if_remote_name, 'up', run_as_root=True) if gateway is not None: utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'route', 'replace', 'default', 'via', gateway, 'dev', if_remote_name, run_as_root=True) except Exception: LOG.exception("Failed to attach vif")
def test_create_configdrive_iso(self): imagefile = None try: self.mox.StubOutWithMock(utils, 'execute') utils.execute('genisoimage', '-o', mox.IgnoreArg(), '-ldots', '-allow-lowercase', '-allow-multidot', '-l', '-publisher', mox.IgnoreArg(), '-quiet', '-J', '-r', '-V', 'config-2', mox.IgnoreArg(), attempts=1, run_as_root=False).AndReturn(None) self.mox.ReplayAll() with configdrive.ConfigDriveBuilder() as c: c._add_file('this/is/a/path/hello', 'This is some content') (fd, imagefile) = tempfile.mkstemp(prefix='cd_iso_') os.close(fd) c._make_iso9660(imagefile) # Check cleanup self.assertFalse(os.path.exists(c.tempdir)) finally: if imagefile: utils.delete_if_exists(imagefile)
def unget_dev(self): if not self.linked: return LOG.debug('Release nbd device %s', self.device) utils.execute('qemu-nbd', '-d', self.device, run_as_root=True) self.linked = False self.device = None
def stop_vz(self): """Manually shuts down the VZ. This does not use the _stop method in the driver since we need the status to _not_ be updated to shutdown for the resume case to work in the managers reboot path in the compute manager init_host""" utils.execute('vzctl', 'stop', self.local_id, run_as_root=True)
def plug(self, instance, vif): vif_type = vif['type'] LOG.debug('Plug vif_type=%(vif_type)s instance=%(instance)s ' 'vif=%(vif)s', {'vif_type': vif_type, 'instance': instance, 'vif': vif}) if_local_name = 'veth%s' % vif['id'][:8] if_remote_name = 'ns%s' % vif['id'][:8] # Device already exists so return. if linux_net.device_exists(if_local_name): return undo_mgr = utils.UndoManager() try: utils.execute('ip', 'link', 'add', if_local_name, 'type', 'veth', 'peer', 'name', if_remote_name, run_as_root=True) undo_mgr.undo_with(lambda: utils.execute( 'ip', 'link', 'delete', if_local_name, run_as_root=True)) utils.execute('ip', 'link', 'set', if_remote_name, 'address', vif['address'], run_as_root=True) except Exception: LOG.exception("Failed to configure network") msg = _('Failed to setup the network, rolling back') undo_mgr.rollback_and_reraise(msg=msg, instance=instance)
def activate_bootloader(self, context, node, instance): """Configure Tilera boot loader for an instance Kernel and ramdisk images are downloaded by cache_tftp_images, and stored in /tftpboot/{uuid}/ This method writes the instances config file, and then creates symlinks for each MAC address in the instance. By default, the complete layout looks like this: /tftpboot/ ./{uuid}/ kernel ./fs_node_id/ """ image_info = get_tftp_image_info(instance) (root_mb, swap_mb) = get_partition_sizes(instance) tilera_nfs_path = get_tilera_nfs_path(node['id']) image_file_path = get_image_file_path(instance) deployment_key = bm_utils.random_alnum(32) db.bm_node_update(context, node['id'], {'deploy_key': deployment_key, 'image_path': image_file_path, 'pxe_config_path': tilera_nfs_path, 'root_mb': root_mb, 'swap_mb': swap_mb}) if os.path.exists(image_file_path) and \ os.path.exists(tilera_nfs_path): utils.execute('mount', '-o', 'loop', image_file_path, tilera_nfs_path, run_as_root=True)
def __volume_not_present(cls, volume): try: utils.execute("lvdisplay", volume, run_as_root=True) except Exception: # If the volume isn't present return True return False
def test_disk_type(self): # Seems like lvm detection # if its in /dev ?? for p in ['/dev/b', '/dev/blah/blah']: d_type = libvirt_utils.get_disk_type(p) self.assertEqual('lvm', d_type) # Try rbd detection d_type = libvirt_utils.get_disk_type('rbd:pool/instance') self.assertEqual('rbd', d_type) # Try the other types template_output = """image: %(path)s file format: %(format)s virtual size: 64M (67108864 bytes) cluster_size: 65536 disk size: 96K """ path = '/myhome/disk.config' for f in ['raw', 'qcow2']: output = template_output % ({ 'format': f, 'path': path, }) self.mox.StubOutWithMock(os.path, 'exists') self.mox.StubOutWithMock(utils, 'execute') os.path.exists(path).AndReturn(True) utils.execute('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info', path).AndReturn((output, '')) self.mox.ReplayAll() d_type = libvirt_utils.get_disk_type(path) self.assertEqual(f, d_type) self.mox.UnsetStubs()
def cache(self, fetch_func, filename, size=None, *args, **kwargs): """Creates image from template. Ensures that template and image not already exists. Ensures that base directory exists. Synchronizes on template fetching. :fetch_func: Function that creates the base image Should accept `target` argument. :filename: Name of the file in the image directory :size: Size of created image in bytes (optional) """ @utils.synchronized(filename, external=True, lock_path=self.lock_path) def call_if_not_exists(target, *args, **kwargs): if not os.path.exists(target): fetch_func(target=target, *args, **kwargs) elif CONF.libvirt_images_type == "lvm" and \ 'ephemeral_size' in kwargs: fetch_func(target=target, *args, **kwargs) base_dir = os.path.join(CONF.instances_path, CONF.base_dir_name) if not os.path.exists(base_dir): fileutils.ensure_tree(base_dir) base = os.path.join(base_dir, filename) if not os.path.exists(self.path) or not os.path.exists(base): self.create_image(call_if_not_exists, base, size, *args, **kwargs) if size and self.preallocate and self._can_fallocate(): utils.execute('fallocate', '-n', '-l', size, self.path)
def test_qemu_backing_file_actual(self): path = "disk.config" example_output = """image: disk.config file format: raw virtual size: 64M (67108864 bytes) cluster_size: 65536 disk size: 96K Snapshot list: ID TAG VM SIZE DATE VM CLOCK 1 d9a9784a500742a7bb95627bb3aace38 0 2012-08-20 10:52:46 00:00:00.000 backing file: /var/lib/nova/a328c7998805951a_2 (actual path: /b/3a988059e51a_2) """ self.mox.StubOutWithMock(os.path, 'exists') self.mox.StubOutWithMock(utils, 'execute') os.path.exists(path).AndReturn(True) utils.execute('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info', path).AndReturn((example_output, '')) self.mox.ReplayAll() image_info = images.qemu_img_info(path) self.assertEqual('disk.config', image_info.image) self.assertEqual('raw', image_info.file_format) self.assertEqual(67108864, image_info.virtual_size) self.assertEqual(98304, image_info.disk_size) self.assertEqual(1, len(image_info.snapshots)) self.assertEqual('/b/3a988059e51a_2', image_info.backing_file)
def _setup_spawn_config_drive_mocks(self, use_cdrom): im = instance_metadata.InstanceMetadata(mox.IgnoreArg(), content=mox.IsA(list), extra_md=mox.IsA(dict)) cdb = self._mox.CreateMockAnything() m = configdrive.ConfigDriveBuilder(instance_md=mox.IgnoreArg()) m.AndReturn(cdb) # __enter__ and __exit__ are required by "with" cdb.__enter__().AndReturn(cdb) cdb.make_drive(mox.IsA(str)) cdb.__exit__(None, None, None).AndReturn(None) if not use_cdrom: utils.execute(CONF.qemu_img_cmd, 'convert', '-f', 'raw', '-O', 'vpc', mox.IsA(str), mox.IsA(str), attempts=1) fake.PathUtils.remove(mox.IsA(str)) m = vmutils.VMUtils.attach_ide_drive(mox.IsA(str), mox.IsA(str), mox.IsA(int), mox.IsA(int), mox.IsA(str)) m.WithSideEffects(self._add_ide_disk)
def chown(path, owner): """Change ownership of file or directory :param path: File or directory whose ownership to change :param owner: Desired new owner (given as uid or username) """ utils.execute('chown', owner, path, run_as_root=True)
def get_console_output(self, context, instance): """Get console output for an instance :param context: security context :param instance: nova.objects.instance.Instance """ LOG.debug('get_console_output called for instance', instance=instance) try: console_log = self.container_dir.get_console_path(instance.name) if not os.path.exists(console_log): return "" uid = pwd.getpwuid(os.getuid()).pw_uid utils.execute('chown', '%s:%s' % (uid, uid), console_log, run_as_root=True) utils.execute('chmod', '755', os.path.join( self.container_dir.get_container_dir( instance.name), instance.name), run_as_root=True) with open(console_log, 'rb') as fp: log_data, remaning = utils.last_bytes(fp, MAX_CONSOLE_BYTES) return log_data except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_LE('Failed to get container output' ' for %(instance)s: %(ex)s'), {'instance': instance.name, 'ex': ex}, instance=instance)
def unget_dev(self): if not self.linked: return utils.execute('qemu-nbd', '-d', self.device, run_as_root=True) self._free_nbd(self.device) self.linked = False self.device = None
def unplug_ovs_hybrid(self, instance, vif): """UnPlug using hybrid strategy Unhook port from OVS, unhook port from bridge, delete bridge, and delete both veth devices. """ super(LibvirtGenericVIFDriver, self).unplug(instance, vif) try: br_name = self.get_br_name(vif['id']) v1_name, v2_name = self.get_veth_pair_names(vif['id']) utils.execute('brctl', 'delif', br_name, v1_name, run_as_root=True) utils.execute('ip', 'link', 'set', br_name, 'down', run_as_root=True) utils.execute('brctl', 'delbr', br_name, run_as_root=True) linux_net.delete_ovs_vif_port(self.get_bridge_name(vif), v2_name) except processutils.ProcessExecutionError: LOG.exception(_("Failed while unplugging vif"), instance=instance)
def _inject_key_into_fs(key, fs, execute=None): """Add the given public ssh key to root's authorized_keys. key is an ssh key string. fs is the path to the base of the filesystem into which to inject the key. """ sshdir = _join_and_check_path_within_fs(fs, 'root', '.ssh') utils.execute('mkdir', '-p', sshdir, run_as_root=True) utils.execute('chown', 'root', sshdir, run_as_root=True) utils.execute('chmod', '700', sshdir, run_as_root=True) keyfile = os.path.join('root', '.ssh', 'authorized_keys') key_data = ''.join([ '\n', '# The following ssh key was injected by Nova', '\n', key.strip(), '\n', ]) _inject_file_into_fs(fs, keyfile, key_data, append=True)
def unplug_ivs_hybrid(self, instance, vif): """UnPlug using hybrid strategy (same as OVS) Unhook port from IVS, unhook port from bridge, delete bridge, and delete both veth devices. """ try: br_name = self.get_br_name(vif['id']) v1_name, v2_name = self.get_veth_pair_names(vif['id']) utils.execute('brctl', 'delif', br_name, v1_name, run_as_root=True) utils.execute('ip', 'link', 'set', br_name, 'down', run_as_root=True) utils.execute('brctl', 'delbr', br_name, run_as_root=True) linux_net.delete_ivs_vif_port(v2_name) except processutils.ProcessExecutionError: LOG.exception(_LE("Failed while unplugging vif"), instance=instance)
def create_ploop_image(disk_format, path, size, fs_type): """Create ploop image :param disk_format: Disk image format (as known by ploop) :param path: Desired location of the ploop image :param size: Desired size of ploop image. May be given as an int or a string. If given as an int, it will be interpreted as bytes. If it's a string, it should consist of a number with an optional suffix ('K' for Kibibytes, M for Mebibytes, 'G' for Gibibytes, 'T' for Tebibytes). If no suffix is given, it will be interpreted as bytes. :param fs_type: Filesystem type """ if not fs_type: fs_type = CONF.default_ephemeral_format or \ disk.FS_FORMAT_EXT4 utils.execute('mkdir', '-p', path) disk_path = os.path.join(path, 'root.hds') utils.execute('ploop', 'init', '-s', size, '-f', disk_format, '-t', fs_type, disk_path, run_as_root=True, check_exit_code=True) # Add read access for all users, because "ploop init" creates # disk with rw rights only for root. OpenStack user should have access # to the disk to request info via "qemu-img info" utils.execute('chmod', '-R', 'a+r', path, run_as_root=True, check_exit_code=True)
def detach_ephemeral(block_device_info, lxd_config, instance): """Detach ephemeral device from the instance.""" ephemeral_storage = driver.block_device_info_get_ephemerals( block_device_info) if ephemeral_storage: storage_driver = lxd_config['environment']['storage'] for ephemeral in ephemeral_storage: if storage_driver == 'zfs': zfs_pool = lxd_config['config']['storage.zfs_pool_name'] utils.execute( 'zfs', 'destroy', '%s/%s-ephemeral' % (zfs_pool, instance.name), run_as_root=True) if storage_driver == 'lvm': lvm_pool = lxd_config['config']['storage.lvm_vg_name'] lvm_path = '/dev/%s/%s-%s' % ( lvm_pool, instance.name, ephemeral['virtual_name']) utils.execute('umount', lvm_path, run_as_root=True) utils.execute('lvremove', '-f', lvm_path, run_as_root=True)
def _delete_iscsi_export_tgtadm(tid): try: utils.execute('tgtadm', '--lld', 'iscsi', '--mode', 'logicalunit', '--op', 'delete', '--tid', tid, '--lun', '1', run_as_root=True) except exception.ProcessExecutionError: pass try: utils.execute('tgtadm', '--lld', 'iscsi', '--mode', 'target', '--op', 'delete', '--tid', tid, run_as_root=True) except exception.ProcessExecutionError: pass # Check if the tid is deleted, that is, check the tid no longer exists. # If the tid dose not exist, tgtadm returns with exit_code 22. # utils.execute() can check the exit_code if check_exit_code parameter is # passed. But, regardless of whether check_exit_code contains 0 or not, # if the exit_code is 0, the function dose not report errors. So we have to # catch a ProcessExecutionError and test its exit_code is 22. try: utils.execute('tgtadm', '--lld', 'iscsi', '--mode', 'target', '--op', 'show', '--tid', tid, run_as_root=True) except exception.ProcessExecutionError as e: if e.exit_code == 22: # OK, the tid is deleted return raise raise exception.NovaException(_( 'baremetal driver was unable to delete tid %s') % tid)
def _attach_vifs(self, instance, network_info): """Plug VIFs into container.""" if not network_info: return if os.name == 'nt': return container_id = self._get_container_id(instance) if not container_id: return netns_path = '/var/run/netns' if not os.path.exists(netns_path): utils.execute('mkdir', '-p', netns_path, run_as_root=True) nspid = self._find_container_pid(container_id) if not nspid: msg = _('Cannot find any PID under container "{0}"') raise RuntimeError(msg.format(container_id)) netns_path = os.path.join(netns_path, container_id) utils.execute('ln', '-sf', '/proc/{0}/ns/net'.format(nspid), '/var/run/netns/{0}'.format(container_id), run_as_root=True) utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'link', 'set', 'lo', 'up', run_as_root=True) for vif in network_info: self.vif_driver.attach(instance, vif, container_id)
def plug(self, instance, network, mapping): iface_id = mapping['vif_uuid'] dev = self.get_dev_name(iface_id) if not linux_net._device_exists(dev): utils.execute('ip', 'tuntap', 'add', dev, 'mode', 'tap', run_as_root=True) utils.execute('ip', 'link', 'set', dev, 'up', run_as_root=True) utils.execute('ovs-vsctl', '--', '--may-exist', 'add-port', FLAGS.libvirt_ovs_bridge, dev, '--', 'set', 'Interface', dev, "external-ids:iface-id=%s" % iface_id, '--', 'set', 'Interface', dev, "external-ids:iface-status=active", '--', 'set', 'Interface', dev, "external-ids:attached-mac=%s" % mapping['mac'], run_as_root=True) result = {'script': '', 'name': dev, 'mac_address': mapping['mac']} return result
def unplug_ovs_hybrid(self, instance, vif): """UnPlug using hybrid strategy Unhook port from OVS, unhook port from bridge, delete bridge, and delete ovs port. """ try: br_name = self.get_br_name(vif['id']) vm_port_name = self.get_vm_ovs_port_name(vif['id']) if linux_net.device_exists(br_name): utils.execute('brctl', 'delif', br_name, vm_port_name, run_as_root=True) utils.execute('ip', 'link', 'set', br_name, 'down', run_as_root=True) utils.execute('brctl', 'delbr', br_name, run_as_root=True) linux_net.delete_ovs_vif_port(self.get_bridge_name(vif), vm_port_name) except processutils.ProcessExecutionError: LOG.exception(_LE("Failed while unplugging vif"), instance=instance)
def plug(self, instance, vif): network, mapping = vif iface_id = mapping['vif_uuid'] dev = self.get_dev_name(iface_id) if not linux_net._device_exists(dev): # Older version of the command 'ip' from the iproute2 package # don't have support for the tuntap option (lp:882568). If it # turns out we're on an old version we work around this by using # tunctl. try: # First, try with 'ip' utils.execute('ip', 'tuntap', 'add', dev, 'mode', 'tap', run_as_root=True) except exception.ProcessExecutionError: # Second option: tunctl utils.execute('tunctl', '-b', '-t', dev, run_as_root=True) utils.execute('ip', 'link', 'set', dev, 'up', run_as_root=True) self.create_ovs_vif_port(dev, iface_id, mapping['mac'], instance['uuid']) conf = config.LibvirtConfigGuestInterface() if FLAGS.libvirt_use_virtio_for_bridges: conf.model = "virtio" conf.net_type = "ethernet" conf.target_dev = dev conf.script = "" conf.mac_addr = mapping['mac'] return conf
def unplug(self, instance, vif): """UnPlug using hybrid strategy Unhook port from OVS, unhook port from bridge, delete bridge, and delete both veth devices. """ try: network, mapping = vif iface_id = mapping['vif_uuid'] br_name = self.get_br_name(iface_id) v1_name, v2_name = self.get_veth_pair_names(iface_id) utils.execute('brctl', 'delif', br_name, v1_name, run_as_root=True) utils.execute('ip', 'link', 'set', br_name, 'down', run_as_root=True) utils.execute('brctl', 'delbr', br_name, run_as_root=True) self.delete_ovs_vif_port(v2_name) except exception.ProcessExecutionError: LOG.exception(_("Failed while unplugging vif"), instance=instance)
def plug(self, instance, vif): """Plug using hybrid strategy Create a per-VIF linux bridge, then link that bridge to the OVS integration bridge via a veth device, setting up the other end of the veth device just like a normal OVS port. Then boot the VIF on the linux bridge using standard libvirt mechanisms """ network, mapping = vif iface_id = self.get_ovs_interfaceid(mapping) br_name = self.get_br_name(mapping['vif_uuid']) v1_name, v2_name = self.get_veth_pair_names(mapping['vif_uuid']) if not linux_net.device_exists(br_name): utils.execute('brctl', 'addbr', br_name, run_as_root=True) if not linux_net.device_exists(v2_name): linux_net._create_veth_pair(v1_name, v2_name) utils.execute('ip', 'link', 'set', br_name, 'up', run_as_root=True) utils.execute('brctl', 'addif', br_name, v1_name, run_as_root=True) linux_net.create_ovs_vif_port(self.get_bridge_name(network), v2_name, iface_id, mapping['mac'], instance['uuid'])
def unplug_ovs_hybrid(self, instance, vif): try: br_name = self.get_br_name(vif['id']) v1_name, v2_name = self.get_veth_pair_names(vif['id']) if linux_net.device_exists(br_name): utils.execute('brctl', 'delif', br_name, v1_name, run_as_root=True) utils.execute('ip', 'link', 'set', br_name, 'down', run_as_root=True) utils.execute('brctl', 'delbr', br_name, run_as_root=True) linux_net.delete_ovs_vif_port(self.get_bridge_name(vif), v2_name) except processutils.ProcessExecutionError: LOG.exception(_LE("Failed while unplugging vif"), instance=instance)
def plug_ovs_hybrid(self, instance, vif): """Plug using hybrid strategy Create a per-VIF linux bridge, then link that bridge to the OVS integration bridge via a veth device, setting up the other end of the veth device just like a normal OVS port. Then boot the VIF on the linux bridge. and connect the tap port to linux bridge """ if_local_name = 'tap%s' % vif['id'][:11] if_remote_name = 'ns%s' % vif['id'][:11] iface_id = self.get_ovs_interfaceid(vif) br_name = self.get_br_name(vif['id']) v1_name, v2_name = self.get_veth_pair_names(vif['id']) # Device already exists so return. if linux_net.device_exists(if_local_name): return undo_mgr = utils.UndoManager() try: if not linux_net.device_exists(br_name): utils.execute('brctl', 'addbr', br_name, run_as_root=True) # Incase of failure undo the Steps # Deleting/Undoing the interface will delete all # associated resources undo_mgr.undo_with(lambda: utils.execute( 'brctl', 'delbr', br_name, run_as_root=True)) # LOG.exception('Throw Test exception with bridgename %s' # % br_name) utils.execute('brctl', 'setfd', br_name, 0, run_as_root=True) utils.execute('brctl', 'stp', br_name, 'off', run_as_root=True) utils.execute( 'tee', ('/sys/class/net/%s/bridge/multicast_snooping' % br_name), process_input='0', run_as_root=True, check_exit_code=[0, 1]) if not linux_net.device_exists(v2_name): linux_net._create_veth_pair(v1_name, v2_name) undo_mgr.undo_with(lambda: utils.execute( 'ip', 'link', 'delete', v1_name, run_as_root=True)) utils.execute('ip', 'link', 'set', br_name, 'up', run_as_root=True) undo_mgr.undo_with(lambda: utils.execute( 'ip', 'link', 'set', br_name, 'down', run_as_root=True)) # Deleting/Undoing the interface will delete all # associated resources (remove from the bridge, its # pair, etc...) utils.execute('brctl', 'addif', br_name, v1_name, run_as_root=True) linux_net.create_ovs_vif_port(self.get_bridge_name(vif), v2_name, iface_id, vif['address'], instance['uuid']) undo_mgr.undo_with( lambda: utils.execute('ovs-vsctl', 'del-port', self.get_bridge_name(vif), v2_name, run_as_root=True)) utils.execute('ip', 'link', 'add', 'name', if_local_name, 'type', 'veth', 'peer', 'name', if_remote_name, run_as_root=True) undo_mgr.undo_with(lambda: utils.execute( 'ip', 'link', 'delete', if_local_name, run_as_root=True)) # Deleting/Undoing the interface will delete all # associated resources (remove from the bridge, its pair, etc...) utils.execute('brctl', 'addif', br_name, if_local_name, run_as_root=True) utils.execute('ip', 'link', 'set', if_local_name, 'up', run_as_root=True) except Exception: msg = "Failed to configure Network." \ " Rolling back the network interfaces %s %s %s %s " % ( br_name, if_local_name, v1_name, v2_name) undo_mgr.rollback_and_reraise(msg=msg, instance=instance)
def mkfs(os_type, fs_label, target): mkfs_command = (_MKFS_COMMAND.get(os_type, _DEFAULT_MKFS_COMMAND) or '') % locals() if mkfs_command: utils.execute(*mkfs_command.split())
def attach(self, instance, vif, container_id): vif_type = vif['type'] if_remote_name = 'ns%s' % vif['id'][:11] gateway = network.find_gateway(instance, vif['network']) ip = network.find_fixed_ip(instance, vif['network']) LOG.debug( 'attach vif_type=%(vif_type)s instance=%(instance)s ' 'vif=%(vif)s', { 'vif_type': vif_type, 'instance': instance, 'vif': vif }) try: utils.execute('ip', 'link', 'set', if_remote_name, 'netns', container_id, run_as_root=True) utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'link', 'set', if_remote_name, 'address', vif['address'], run_as_root=True) utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'addr', 'add', ip, 'dev', if_remote_name, run_as_root=True) utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'link', 'set', if_remote_name, 'up', run_as_root=True) # Setup MTU on if_remote_name is required if it is a non # default value mtu = CONF.network_device_mtu if vif.get('mtu') is not None: mtu = vif.get('mtu') if mtu is not None: utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'link', 'set', if_remote_name, 'mtu', mtu, run_as_root=True) if gateway is not None: utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'route', 'replace', 'default', 'via', gateway, 'dev', if_remote_name, run_as_root=True) # Disable TSO, for now no config option utils.execute('ip', 'netns', 'exec', container_id, 'ethtool', '--offload', if_remote_name, 'tso', 'off', run_as_root=True) except Exception: LOG.exception("Failed to attach vif")
def plug_bridge(self, instance, vif): if_local_name = 'tap%s' % vif['id'][:11] if_remote_name = 'ns%s' % vif['id'][:11] bridge = vif['network']['bridge'] gateway = network.find_gateway(instance, vif['network']) net = vif['network'] if net.get_meta('should_create_vlan', False): vlan = net.get_meta('vlan'), iface = (CONF.vlan_interface or vif['network'].get_meta('bridge_interface')) linux_net.LinuxBridgeInterfaceDriver.ensure_vlan_bridge( vlan, bridge, iface, net_attrs=vif, mtu=vif.get('mtu')) iface = 'vlan%s' % vlan else: iface = (CONF.flat_interface or vif['network'].get_meta('bridge_interface')) LOG.debug('Ensuring bridge for %s - %s' % (iface, bridge)) linux_net.LinuxBridgeInterfaceDriver.ensure_bridge(bridge, iface, net_attrs=vif, gateway=gateway) # Device already exists so return. if linux_net.device_exists(if_local_name): return undo_mgr = utils.UndoManager() try: utils.execute('ip', 'link', 'add', 'name', if_local_name, 'type', 'veth', 'peer', 'name', if_remote_name, run_as_root=True) undo_mgr.undo_with(lambda: utils.execute( 'ip', 'link', 'delete', if_local_name, run_as_root=True)) # NOTE(samalba): Deleting the interface will delete all # associated resources (remove from the bridge, its pair, etc...) utils.execute('ip', 'link', 'set', if_local_name, 'address', self._fe_random_mac(), run_as_root=True) utils.execute('brctl', 'addif', bridge, if_local_name, run_as_root=True) utils.execute('ip', 'link', 'set', if_local_name, 'up', run_as_root=True) except Exception: LOG.exception("Failed to configure network") msg = _('Failed to setup the network, rolling back') undo_mgr.rollback_and_reraise(msg=msg, instance=instance)
def _plug_bridge_with_port(self, instance, vif, port): iface_id = self.get_ovs_interfaceid(vif) br_name = self.get_br_name(vif['id']) v1_name, v2_name = self.get_veth_pair_names(vif['id']) if not linux_net.device_exists(br_name): utils.execute('brctl', 'addbr', br_name, run_as_root=True) utils.execute('brctl', 'setfd', br_name, 0, run_as_root=True) utils.execute('brctl', 'stp', br_name, 'off', run_as_root=True) utils.execute( 'tee', ('/sys/class/net/%s/bridge/multicast_snooping' % br_name), process_input='0', run_as_root=True, check_exit_code=[0, 1]) disv6 = '/proc/sys/net/ipv6/conf/%s/disable_ipv6' % br_name if os.path.exists(disv6): utils.execute('tee', disv6, process_input='1', run_as_root=True, check_exit_code=[0, 1]) if not linux_net.device_exists(v2_name): mtu = vif['network'].get_meta('mtu') linux_net._create_veth_pair(v1_name, v2_name, mtu) utils.execute('ip', 'link', 'set', br_name, 'up', run_as_root=True) utils.execute('brctl', 'addif', br_name, v1_name, run_as_root=True) if port == 'ovs': linux_net.create_ovs_vif_port(self.get_bridge_name(vif), v2_name, iface_id, vif['address'], instance.uuid, mtu) elif port == 'ivs': linux_net.create_ivs_vif_port(v2_name, iface_id, vif['address'], instance.uuid)
def attach(self, instance, vif, container_id): vif_type = vif['type'] LOG.debug( 'Attach vif_type=%(vif_type)s instance=%(instance)s ' 'vif=%(vif)s', { 'vif_type': vif_type, 'instance': instance, 'vif': vif }) if_local_name = 'veth%s' % vif['id'][:8] if_remote_name = 'ns%s' % vif['id'][:8] undo_mgr = utils.UndoManager() undo_mgr.undo_with(lambda: utils.execute( 'ip', 'link', 'delete', if_local_name, run_as_root=True)) ipv4_address = '0.0.0.0' ipv6_address = None if 'subnets' in vif['network']: subnets = vif['network']['subnets'] for subnet in subnets: ips = subnet['ips'][0] if (ips['version'] == 4): if ips['address'] is not None: ipv4_address = ips['address'] ipv4_netmask = subnet['cidr'].split('/')[1] ipv4_gateway = subnet['gateway']['address'] if (ips['version'] == 6): if ips['address'] is not None: ipv6_address = ips['address'] ipv6_netmask = subnet['cidr'].split('/')[1] ipv6_gateway = subnet['gateway']['address'] params = { 'ip_address': ipv4_address, 'vn_id': vif['network']['id'], 'display_name': instance['display_name'], 'hostname': instance['hostname'], 'host': instance['host'], 'vm_project_id': instance['project_id'], 'port_type': 'NovaVMPort', 'ip6_address': ipv6_address, } try: utils.execute('ip', 'link', 'set', if_remote_name, 'netns', container_id, run_as_root=True) result = self._vrouter_client.add_port(instance['uuid'], vif['id'], if_local_name, vif['address'], **params) if not result: # follow the exception path raise RuntimeError('add_port returned %s' % str(result)) utils.execute('ip', 'link', 'set', if_local_name, 'up', run_as_root=True) except Exception: LOG.exception("Failed to attach the network") msg = _('Failed to attach the network, rolling back') undo_mgr.rollback_and_reraise(msg=msg, instance=instance) try: utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'link', 'set', if_remote_name, 'address', vif['address'], run_as_root=True) if ipv6_address: ip = ipv6_address + "/" + ipv6_netmask gateway = ipv6_gateway utils.execute('ip', 'netns', 'exec', container_id, 'ifconfig', if_remote_name, 'inet6', 'add', ip, run_as_root=True) utils.execute('ip', 'netns', 'exec', container_id, 'ip', '-6', 'route', 'replace', 'default', 'via', gateway, 'dev', if_remote_name, run_as_root=True) if ipv4_address != '0.0.0.0': ip = ipv4_address + "/" + ipv4_netmask gateway = ipv4_gateway utils.execute('ip', 'netns', 'exec', container_id, 'ifconfig', if_remote_name, ip, run_as_root=True) utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'route', 'replace', 'default', 'via', gateway, 'dev', if_remote_name, run_as_root=True) utils.execute('ip', 'netns', 'exec', container_id, 'ip', 'link', 'set', if_remote_name, 'up', run_as_root=True) except Exception: LOG.exception(_("Failed to attach vif"), instance=instance)
def _aoe_discover(self): """Call aoe-discover (aoe-tools) AoE Discover.""" (out, err) = utils.execute('aoe-discover', run_as_root=True, check_exit_code=0) return (out, err)
def execute(*args, **kwargs): return utils.execute(*args, **kwargs)
def remove_rule(cmd): execute("sudo iptables --delete %s" % (cmd)) pass
def _path_exists(path): """Check path.""" try: return utils.execute('stat', path, run_as_root=True) except exception.ProcessExecutionError: return False
def _call_parted(self, path, start, end): utils.execute('parted', '--script', path, 'rm', '1', run_as_root=True) utils.execute('parted', '--script', path, 'mkpart', 'primary', '%ds' % start, '%ds' % end, run_as_root=True)
def _call_tune2fs_add_journal(self, path): utils.execute("tune2fs", "-j", path, run_as_root=True)
def _call_tune2fs_remove_journal(self, path): utils.execute("tune2fs", "-O ^has_journal", path, run_as_root=True)
def execute(self, *args, **kwargs): stdout_value, stderr_value = utils.execute(*args, **kwargs) if stdout_value.find('The operation completed successfully') == -1: raise vmutils.HyperVException( _('An error has occurred when ' 'calling the iscsi initiator: %s') % stdout_value)
def _generate_fingerprint(public_key_file): (out, err) = utils.execute('ssh-keygen', '-q', '-l', '-f', public_key_file) fingerprint = out.split(' ')[1] return fingerprint
def convert_image(source, dest, out_format, run_as_root=False): """Convert image to other format.""" cmd = ('qemu-img', 'convert', '-O', out_format, source, dest) utils.execute(*cmd, run_as_root=run_as_root)
def confirm_rule(cmd): execute("sudo iptables --delete %s" % (cmd)) execute("sudo iptables -I %s" % (cmd))