Beispiel #1
0
def _zero_volume(path, volume_size):
    """Write zeros over the specified path

    :param path: logical volume path
    :param size: number of zeros to write
    """
    bs = units.Mi
    direct_flags = ('oflag=direct',)
    sync_flags = ()
    remaining_bytes = volume_size

    # The loop efficiently writes zeros using dd,
    # and caters for versions of dd that don't have
    # the easier to use iflag=count_bytes option.
    while remaining_bytes:
        zero_blocks = remaining_bytes / bs
        seek_blocks = (volume_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 /= units.Ki  # Limit to 3 iterations
        # Use O_DIRECT with initial block size and fdatasync otherwise
        direct_flags = ()
        sync_flags = ('conv=fdatasync',)
Beispiel #2
0
def clear_volume(path):
    """Obfuscate the logical volume.

    :param path: logical volume path
    """
    volume_clear = CONF.libvirt.volume_clear

    if volume_clear not in ('none', 'shred', 'zero'):
        LOG.error(_LE("ignoring unrecognized volume_clear='%s' value"),
                  volume_clear)
        volume_clear = 'zero'

    if volume_clear == 'none':
        return

    volume_clear_size = int(CONF.libvirt.volume_clear_size) * units.Mi
    volume_size = get_volume_size(path)

    if volume_clear_size != 0 and volume_clear_size < volume_size:
        volume_size = volume_clear_size

    if volume_clear == 'zero':
        # NOTE(p-draigbrady): we could use shred to do the zeroing
        # with -n0 -z, however only versions >= 8.22 perform as well as dd
        _zero_volume(path, volume_size)
    elif volume_clear == 'shred':
        utils.execute('shred',
                      '-n3',
                      '-s%d' % volume_size,
                      path,
                      run_as_root=True)
    else:
        raise exception.Invalid(
            _("volume_clear='%s' is not handled") % volume_clear)
Beispiel #3
0
def clear_volume(path):
    """Obfuscate the logical volume.

    :param path: logical volume path
    """
    volume_clear = CONF.libvirt.volume_clear

    if volume_clear not in ('none', 'shred', 'zero'):
        LOG.error(_LE("ignoring unrecognized volume_clear='%s' value"),
                  volume_clear)
        volume_clear = 'zero'

    if volume_clear == 'none':
        return

    volume_clear_size = int(CONF.libvirt.volume_clear_size) * units.Mi
    volume_size = get_volume_size(path)

    if volume_clear_size != 0 and volume_clear_size < volume_size:
        volume_size = volume_clear_size

    if volume_clear == 'zero':
        # NOTE(p-draigbrady): we could use shred to do the zeroing
        # with -n0 -z, however only versions >= 8.22 perform as well as dd
        _zero_volume(path, volume_size)
    elif volume_clear == 'shred':
        utils.execute('shred', '-n3', '-s%d' % volume_size, path,
                      run_as_root=True)
    else:
        raise exception.Invalid(_("volume_clear='%s' is not handled")
                                % volume_clear)
Beispiel #4
0
def clear_volume(path):
    """Obfuscate the logical volume.

    :param path: logical volume path
    """
    volume_clear = CONF.libvirt.volume_clear

    if volume_clear == 'none':
        return

    volume_clear_size = int(CONF.libvirt.volume_clear_size) * units.Mi

    try:
        volume_size = get_volume_size(path)
    except exception.VolumeBDMPathNotFound:
        LOG.warn(_LW('ignoring missing logical volume %(path)s'),
                 {'path': path})
        return

    if volume_clear_size != 0 and volume_clear_size < volume_size:
        volume_size = volume_clear_size

    if volume_clear == 'zero':
        # NOTE(p-draigbrady): we could use shred to do the zeroing
        # with -n0 -z, however only versions >= 8.22 perform as well as dd
        _zero_volume(path, volume_size)
    elif volume_clear == 'shred':
        utils.execute('shred', '-n3', '-s%d' % volume_size, path,
                      run_as_root=True)
Beispiel #5
0
def remove_volumes(paths):
    """Remove one or more logical volume."""

    errors = []
    for path in paths:
        clear_volume(path)
        lvremove = ('lvremove', '-f', path)
        try:
            utils.execute(*lvremove, attempts=3, run_as_root=True)
        except processutils.ProcessExecutionError as exp:
            errors.append(six.text_type(exp))
    if errors:
        raise exception.VolumesNotRemoved(reason=(', ').join(errors))
Beispiel #6
0
    def _deallocate_pcidevice_for_instance(self, instance):
        """
        Remove the UUID from PCI device spec.
        """
        if CONF.pci_passthrough_whitelist and instance:
           pci_devs = jsonutils.loads(utils.load_file(CONF.fsl_sriov.pci_devices))
           for dev in pci_devs:
               if instance.uuid == dev['instance_uuid']:
                  dev['instance_uuid'] = None
                  pfname = dev['pf_vf_name']
                  intbridge = CONF.neutron.ovs_bridge
		  utils.execute('ovs-vsctl', '--no-wait', 'del-port', intbridge , pfname , run_as_root=True) 
           utils.write_to_file(CONF.fsl_sriov.pci_devices, jsonutils.dumps(pci_devs))
Beispiel #7
0
def create_volume(target, device, cipher, key_size, key):
    """Sets up a dmcrypt mapping

    :param target: device mapper logical device name
    :param device: underlying block device
    :param cipher: encryption cipher string digestible by cryptsetup
    :param key_size: encryption key size
    :param key: encryption key as an array of unsigned bytes
    """
    cmd = ('cryptsetup', 'create', target, device, '--cipher=' + cipher,
           '--key-size=' + str(key_size), '--key-file=-')
    key = ''.join(map(lambda byte: "%02x" % byte, key))
    utils.execute(*cmd, process_input=key, run_as_root=True)
Beispiel #8
0
 def _is_pci_device_available(self, instance_uuid):
     pci_devs = jsonutils.loads(utils.load_file(CONF.fsl_sriov.pci_devices))
     assignable_pci_device = None
     for dev in pci_devs:
         if dev['instance_uuid'] is None:
            assignable_pci_device = dev['dev_id']
            dev['instance_uuid'] = instance_uuid
            pfname = dev['pf_vf_name']
            intbridge = CONF.neutron.ovs_bridge
            utils.execute('ovs-vsctl', '--no-wait', 'add-port', intbridge , pfname , '--', 'set', 'interface', pfname, 'type=vf_inic', run_as_root=True)
            break
     utils.write_to_file(CONF.fsl_sriov.pci_devices, jsonutils.dumps(pci_devs))    
     return assignable_pci_device      
Beispiel #9
0
def create_volume(vg, lv, size, sparse=False):
    """Create LVM image.

    Creates a LVM image with given size.

    :param vg: existing volume group which should hold this image
    :param lv: name for this image (logical volume)
    :size: size of image in bytes
    :sparse: create sparse logical volume
    """
    vg_info = get_volume_group_info(vg)
    free_space = vg_info['free']

    def check_size(vg, lv, size):
        if size > free_space:
            raise RuntimeError(
                _('Insufficient Space on Volume Group %(vg)s.'
                  ' Only %(free_space)db available,'
                  ' but %(size)db required'
                  ' by volume %(lv)s.') % {
                      'vg': vg,
                      'free_space': free_space,
                      'size': size,
                      'lv': lv
                  })

    if sparse:
        preallocated_space = 64 * units.Mi
        check_size(vg, lv, preallocated_space)
        if free_space < size:
            LOG.warn(
                _LW('Volume group %(vg)s will not be able'
                    ' to hold sparse volume %(lv)s.'
                    ' Virtual volume size is %(size)db,'
                    ' but free space on volume group is'
                    ' only %(free_space)db.'), {
                        'vg': vg,
                        'free_space': free_space,
                        'size': size,
                        'lv': lv
                    })

        cmd = ('lvcreate', '-L', '%db' % preallocated_space, '--virtualsize',
               '%db' % size, '-n', lv, vg)
    else:
        check_size(vg, lv, size)
        cmd = ('lvcreate', '-L', '%db' % size, '-n', lv, vg)
    utils.execute(*cmd, run_as_root=True, attempts=3)
Beispiel #10
0
def get_volume_group_info(vg):
    """Return free/used/total space info for a volume group in bytes

    :param vg: volume group name
    :returns: A dict containing:
             :total: How big the filesystem is (in bytes)
             :free: How much space is free (in bytes)
             :used: How much space is used (in bytes)
    """

    out, err = utils.execute('vgs',
                             '--noheadings',
                             '--nosuffix',
                             '--separator',
                             '|',
                             '--units',
                             'b',
                             '-o',
                             'vg_size,vg_free',
                             vg,
                             run_as_root=True)

    info = out.split('|')
    if len(info) != 2:
        raise RuntimeError(_("vg %s must be LVM volume group") % vg)

    return {
        'total': int(info[0]),
        'free': int(info[1]),
        'used': int(info[0]) - int(info[1])
    }
Beispiel #11
0
def volume_info(path):
    """Get logical volume info.

    :param path: logical volume path
    :returns: Return a dict object including info of given logical volume
            : Data format example
            : {'#Seg': '1', 'Move': '', 'Log': '', 'Meta%': '', 'Min': '-1',
            : ...
            : 'Free': '9983', 'LV': 'volume-aaa', 'Host': 'xyz.com',
            : 'Active': 'active', 'Path': '/dev/vg/volume-aaa', '#LV': '3',
            : 'Maj': '-1', 'VSize': '50.00g', 'VFree': '39.00g', 'Pool': '',
            : 'VG Tags': '', 'KMaj': '253', 'Convert': '', 'LProfile': '',
            : '#Ext': '12799', 'Attr': '-wi-a-----', 'VG': 'vg',
            : ...
            : 'LSize': '1.00g', '#PV': '1', '#VMdaCps': 'unmanaged'}
    """
    out, err = utils.execute('lvs', '-o', 'vg_all,lv_all',
                             '--separator', '|', path, run_as_root=True)

    info = [line.split('|') for line in out.splitlines()]

    if len(info) != 2:
        raise RuntimeError(_("Path %s must be LVM logical volume") % path)

    return dict(zip(*info))
Beispiel #12
0
def get_volume_openstack_group_info(vg):
    """Return free/used/total space info for a volume group in bytes

    :param vg: volume group name
    :returns: A dict containing:
             :total: How big the vg is (in bytes)
             :free: How much space is free (in bytes)
             :used: How much space is used (in bytes)
    """
    out, err = utils.execute('lvs',
                             '--noheadings',
                             '--nosuffix',
                             '--separator',
                             '|',
                             '--units',
                             'b',
                             '-o',
                             'lv_size,lv_name,vg_size',
                             vg,
                             run_as_root=True)
    lvlist = [line.strip() for line in out.splitlines()]
    vg_total = 0
    vg_used = 0
    for lv in lvlist:
        info = lv.split('|')
        if len(info) != 3:
            raise RuntimeError(_("vg %s must be LVM volume group") % vg)
        if vg_total == 0:
            vg_total = int(info[2])
        if info[1].startswith('volume-') and len(info[1]) == 43:
            vg_used = vg_used + int(info[0])
        else:
            vg_total = vg_total - int(info[0])

    return {'total': vg_total, 'free': vg_total - vg_used, 'used': vg_used}
Beispiel #13
0
def get_volume_openstack_group_info(vg):
    """Return free/used/total space info for a volume group in bytes

    :param vg: volume group name
    :returns: A dict containing:
             :total: How big the vg is (in bytes)
             :free: How much space is free (in bytes)
             :used: How much space is used (in bytes)
    """
    out, err = utils.execute('lvs', '--noheadings', '--nosuffix',
                       '--separator', '|',
                       '--units', 'b', '-o', 'lv_size,lv_name,vg_size', vg,
                       run_as_root=True)
    lvlist = [line.strip() for line in out.splitlines()]
    vg_total = 0
    vg_used = 0
    for lv in lvlist:
        info = lv.split('|')
        if len(info) != 3:
            raise RuntimeError(_("vg %s must be LVM volume group") % vg)
        if vg_total == 0:
            vg_total = int(info[2])
        if info[1].startswith('volume-') and len(info[1]) == 43:
            vg_used = vg_used + int(info[0])
        else:
            vg_total = vg_total - int(info[0])

    return {'total':vg_total,
            'free': vg_total - vg_used,
            'used': vg_used}
Beispiel #14
0
def get_volume_size(path):
    """Get logical volume size in bytes.

    :param path: logical volume path
    """
    out, _err = utils.execute('blockdev', '--getsize64', path,
                              run_as_root=True)

    return int(out)
Beispiel #15
0
def create_volume(target, device, cipher, key_size, key):
    """Sets up a dmcrypt mapping

    :param target: device mapper logical device name
    :param device: underlying block device
    :param cipher: encryption cipher string digestible by cryptsetup
    :param key_size: encryption key size
    :param key: encryption key as an array of unsigned bytes
    """
    cmd = ('cryptsetup',
           'create',
           target,
           device,
           '--cipher=' + cipher,
           '--key-size=' + str(key_size),
           '--key-file=-')
    key = ''.join(map(lambda byte: "%02x" % byte, key))
    utils.execute(*cmd, process_input=key, run_as_root=True)
Beispiel #16
0
def get_volume_size(path):
    """Get logical volume size in bytes.

    :param path: logical volume path
    """
    out, _err = utils.execute('blockdev', '--getsize64', path,
                              run_as_root=True)

    return int(out)
Beispiel #17
0
def create_volume(vg, lv, size, sparse=False):
    """Create LVM image.

    Creates a LVM image with given size.

    :param vg: existing volume group which should hold this image
    :param lv: name for this image (logical volume)
    :size: size of image in bytes
    :sparse: create sparse logical volume
    """
    vg_info = get_volume_group_info(vg)
    free_space = vg_info['free']

    def check_size(vg, lv, size):
        if size > free_space:
            raise RuntimeError(_('Insufficient Space on Volume Group %(vg)s.'
                                 ' Only %(free_space)db available,'
                                 ' but %(size)db required'
                                 ' by volume %(lv)s.') %
                               {'vg': vg,
                                'free_space': free_space,
                                'size': size,
                                'lv': lv})

    if sparse:
        preallocated_space = 64 * units.Mi
        check_size(vg, lv, preallocated_space)
        if free_space < size:
            LOG.warn(_LW('Volume group %(vg)s will not be able'
                         ' to hold sparse volume %(lv)s.'
                         ' Virtual volume size is %(size)db,'
                         ' but free space on volume group is'
                         ' only %(free_space)db.'),
                        {'vg': vg,
                         'free_space': free_space,
                         'size': size,
                         'lv': lv})

        cmd = ('lvcreate', '-L', '%db' % preallocated_space,
                '--virtualsize', '%db' % size, '-n', lv, vg)
    else:
        check_size(vg, lv, size)
        cmd = ('lvcreate', '-L', '%db' % size, '-n', lv, vg)
    utils.execute(*cmd, run_as_root=True, attempts=3)
Beispiel #18
0
def delete_volume(target):
    """Deletes a dmcrypt mapping

    :param target: name of the mapped logical device
    """
    try:
        utils.execute('cryptsetup', 'remove', target, run_as_root=True)
    except processutils.ProcessExecutionError as e:
        # cryptsetup returns 4 when attempting to destroy a non-existent
        # dm-crypt device. It indicates that the device is invalid, which
        # means that the device is invalid (i.e., it has already been
        # destroyed).
        if e.exit_code == 4:
            LOG.debug("Ignoring exit code 4, volume already destroyed")
        else:
            with excutils.save_and_reraise_exception():
                LOG.error(_LE("Could not disconnect encrypted volume "
                              "%(volume)s. If dm-crypt device is still active "
                              "it will have to be destroyed manually for "
                              "cleanup to succeed."), {'volume': target})
Beispiel #19
0
def list_volumes(vg):
    """List logical volumes paths for given volume group.

    :param vg: volume group name
    :returns: Return a logical volume list for given volume group
            : Data format example
            : ['volume-aaa', 'volume-bbb', 'volume-ccc']
    """
    out, err = utils.execute('lvs', '--noheadings', '-o', 'lv_name', vg,
                             run_as_root=True)

    return [line.strip() for line in out.splitlines()]
Beispiel #20
0
def delete_volume(target):
    """Deletes a dmcrypt mapping

    :param target: name of the mapped logical device
    """
    try:
        utils.execute('cryptsetup', 'remove', target, run_as_root=True)
    except processutils.ProcessExecutionError as e:
        # cryptsetup returns 4 when attempting to destroy a non-existent
        # dm-crypt device. It indicates that the device is invalid, which
        # means that the device is invalid (i.e., it has already been
        # destroyed).
        if e.exit_code == 4:
            LOG.debug("Ignoring exit code 4, volume already destroyed")
        else:
            with excutils.save_and_reraise_exception():
                LOG.error(
                    "Could not disconnect encrypted volume "
                    "%(volume)s. If dm-crypt device is still active "
                    "it will have to be destroyed manually for "
                    "cleanup to succeed.", {'volume': target})
Beispiel #21
0
def get_volume_size(path):
    """Get logical volume size in bytes.

    :param path: logical volume path
    :raises: processutils.ProcessExecutionError if getting the volume size
             fails in some unexpected way.
    :raises: exception.VolumeBDMPathNotFound if the volume path does not exist.
    """
    out, _err = utils.execute('blockdev', '--getsize64', path,
                              run_as_root=True)

    return int(out)
Beispiel #22
0
def create_volume(target, device, cipher, key_size, key):
    """Sets up a dmcrypt mapping

    :param target: device mapper logical device name
    :param device: underlying block device
    :param cipher: encryption cipher string digestible by cryptsetup
    :param key_size: encryption key size
    :param key: encoded encryption key bytestring
    """
    cmd = ('cryptsetup', 'create', target, device, '--cipher=' + cipher,
           '--key-size=' + str(key_size), '--key-file=-')
    key = binascii.hexlify(key).decode('utf-8')
    try:
        utils.execute(*cmd, process_input=key, run_as_root=True)
    except processutils.ProcessExecutionError as e:
        with excutils.save_and_reraise_exception():
            LOG.error(
                "Could not start encryption for disk %(device)s: "
                "%(exception)s", {
                    'device': device,
                    'exception': e
                })
def create_volume(target, device, cipher, key_size, key):
    """Sets up a dmcrypt mapping

    :param target: device mapper logical device name
    :param device: underlying block device
    :param cipher: encryption cipher string digestible by cryptsetup
    :param key_size: encryption key size
    :param key: encryption key as an array of unsigned bytes
    """
    cmd = ('cryptsetup', 'create', target, device, '--cipher=' + cipher,
           '--key-size=' + str(key_size), '--key-file=-')
    key = ''.join(map(lambda byte: "%02x" % byte, key))
    try:
        utils.execute(*cmd, process_input=key, run_as_root=True)
    except processutils.ProcessExecutionError as e:
        with excutils.save_and_reraise_exception():
            LOG.error(
                _LE("Could not start encryption for disk %(device)s: "
                    "%(exception)s"), {
                        'device': device,
                        'exception': e
                    })
Beispiel #24
0
def create_volume(target, device, cipher, key_size, key):
    """Sets up a dmcrypt mapping

    :param target: device mapper logical device name
    :param device: underlying block device
    :param cipher: encryption cipher string digestible by cryptsetup
    :param key_size: encryption key size
    :param key: encryption key as an array of unsigned bytes
    """
    cmd = ('cryptsetup',
           'create',
           target,
           device,
           '--cipher=' + cipher,
           '--key-size=' + str(key_size),
           '--key-file=-')
    key = ''.join(map(lambda byte: "%02x" % byte, key))
    try:
        utils.execute(*cmd, process_input=key, run_as_root=True)
    except processutils.ProcessExecutionError as e:
        with excutils.save_and_reraise_exception():
            LOG.error(_LE("Could not start encryption for disk %(device)s: "
                          "%(exception)s"), {'device': device, 'exception': e})
Beispiel #25
0
def create_volume(target, device, cipher, key_size, key):
    """Sets up a dmcrypt mapping

    :param target: device mapper logical device name
    :param device: underlying block device
    :param cipher: encryption cipher string digestible by cryptsetup
    :param key_size: encryption key size
    :param key: encoded encryption key bytestring
    """
    cmd = ('cryptsetup',
           'create',
           target,
           device,
           '--cipher=' + cipher,
           '--key-size=' + str(key_size),
           '--key-file=-')
    key = binascii.hexlify(key).decode('utf-8')
    try:
        utils.execute(*cmd, process_input=key, run_as_root=True)
    except processutils.ProcessExecutionError as e:
        with excutils.save_and_reraise_exception():
            LOG.error("Could not start encryption for disk %(device)s: "
                      "%(exception)s", {'device': device, 'exception': e})
Beispiel #26
0
def get_volume_size(path):
    """Get logical volume size in bytes.

    :param path: logical volume path
    :raises: processutils.ProcessExecutionError if getting the volume size
             fails in some unexpected way.
    :raises: exception.VolumeBDMPathNotFound if the volume path does not exist.
    """
    out, _err = utils.execute('blockdev',
                              '--getsize64',
                              path,
                              run_as_root=True)

    return int(out)
Beispiel #27
0
def get_volume_group_info(vg):
    """Return free/used/total space info for a volume group in bytes

    :param vg: volume group name
    :returns: A dict containing:
             :total: How big the filesystem is (in bytes)
             :free: How much space is free (in bytes)
             :used: How much space is used (in bytes)
    """

    out, err = utils.execute('vgs', '--noheadings', '--nosuffix',
                       '--separator', '|',
                       '--units', 'b', '-o', 'vg_size,vg_free', vg,
                       run_as_root=True)

    info = out.split('|')
    if len(info) != 2:
        raise RuntimeError(_("vg %s must be LVM volume group") % vg)

    return {'total': int(info[0]),
            'free': int(info[1]),
            'used': int(info[0]) - int(info[1])}
Beispiel #28
0
 def snapshot_delete(self):
     # NOTE (rmk): Snapshot volumes are automatically zeroed by LVM
     cmd = ('lvremove', '-f', self.snapshot_path)
     libvirt_utils.execute(*cmd, run_as_root=True, attempts=3)
Beispiel #29
0
 def snapshot_delete(self):
     # NOTE (rmk): Snapshot volumes are automatically zeroed by LVM
     cmd = ('lvremove', '-f', self.snapshot_path)
     libvirt_utils.execute(*cmd, run_as_root=True, attempts=3)
Beispiel #30
0
 def snapshot_create(self):
     size = CONF.libvirt_lvm_snapshot_size
     cmd = ('lvcreate', '-L', size, '-s', '--name', self.snapshot_name,
            self.path)
     libvirt_utils.execute(*cmd, run_as_root=True, attempts=3)
Beispiel #31
0
 def snapshot_create(self):
     size = CONF.libvirt_lvm_snapshot_size
     cmd = ("lvcreate", "-L", size, "-s", "--name", self.snapshot_name, self.path)
     libvirt_utils.execute(*cmd, run_as_root=True, attempts=3)
Beispiel #32
0
def delete_volume(target):
    """Deletes a dmcrypt mapping

    :param target: name of the mapped logical device
    """
    utils.execute('cryptsetup', 'remove', target, run_as_root=True)
Beispiel #33
0
def delete_volume(target):
    """Deletes a dmcrypt mapping

    :param target: name of the mapped logical device
    """
    utils.execute('cryptsetup', 'remove', target, run_as_root=True)
Beispiel #34
0
 def snapshot_create(self):
     size = CONF.libvirt_lvm_snapshot_size
     cmd = ('lvcreate', '-L', size, '-s', '--name', self.snapshot_name,
            self.path)
     libvirt_utils.execute(*cmd, run_as_root=True, attempts=3)