Example #1
0
    def test_lvdisplay(self):
        """Test display of LVM volume information.
        """
        treadmill.subproc.check_output.return_value = (
            '  /dev/test/test-lv:test:3:1:-1:0:24576:'
            '3:-1:0:-1:253:5\n')

        lv = lvm.lvdisplay('test-lv', 'test')

        treadmill.subproc.check_output.assert_called_with([
            'lvm',
            'lvdisplay',
            '--colon',
            'test/test-lv',
        ])
        self.assertEqual(
            lv,
            {
                'block_dev': '/dev/test/test-lv',
                'dev_major': 253,
                'dev_minor': 5,
                'extent_alloc': -1,
                'extent_size': 3,
                'group': 'test',
                'name': 'test-lv',
                'open_count': 0,
            },
        )
Example #2
0
    def _destroy_volume(self, uniqueid):
        """Try destroy a volume from LVM.
        """
        # Remove it from state (if present)
        self._volumes.pop(uniqueid, None)
        try:
            lvm.lvdisplay(uniqueid, group=self._vg_name)
        except subproc.CalledProcessError:
            _LOGGER.warning('Ignoring unknow volume %r', uniqueid)
            return False

        # This should not fail.
        lvm.lvremove(uniqueid, group=self._vg_name)
        _LOGGER.info('Destroyed volume %r', uniqueid)

        return True
Example #3
0
    def _destroy_volume(self, uniqueid):
        """Try destroy a volume from LVM.
        """
        # Remove it from state (if present)
        self._volumes.pop(uniqueid, None)
        try:
            lvm.lvdisplay(uniqueid, group=self._vg_name)
        except subproc.CalledProcessError:
            _LOGGER.warning('Ignoring unknown volume %r', uniqueid)
            return False

        # This should not fail.
        while True:
            # XXX: Workaround AFSClient delayed cleanup.
            try:
                lvm.lvremove(uniqueid, group=self._vg_name)
                break
            except subproc.CalledProcessError:
                _LOGGER.critical('Ignoring volume %r deletion error', uniqueid)
                time.sleep(1)

        _LOGGER.info('Destroyed volume %r', uniqueid)

        return True
Example #4
0
    def on_create_request(self, rsrc_id, rsrc_data):
        app_unique_name = rsrc_id
        size = rsrc_data['size']
        read_bps = self._default_read_bps
        write_bps = self._default_write_bps
        read_iops = self._default_read_iops
        write_iops = self._default_write_iops

        with lc.LogContext(_LOGGER, rsrc_id,
                           adapter_cls=lc.ContainerAdapter) as log:
            log.info('Processing request')

            size_in_bytes = utils.size_to_bytes(size)
            uniqueid = _uniqueid(app_unique_name)

            # Create the logical volume
            existing_volume = uniqueid in self._volumes
            if not existing_volume:
                needed = math.ceil(size_in_bytes /
                                   self._vg_status['extent_size'])
                if needed > self._vg_status['extent_free']:
                    # If we do not have enough space, delay the creation until
                    # another volume is deleted.
                    log.info(
                        'Delaying request %r until %d extents are free.'
                        ' Current volumes: %r', rsrc_id, needed, self._volumes)
                    self._pending.append(rsrc_id)
                    return None

                lvm.lvcreate(
                    volume=uniqueid,
                    group=self._vg_name,
                    size_in_bytes=size_in_bytes,
                )
                # We just created a volume, refresh cached status from LVM
                self._vg_status = localdiskutils.refresh_vg_status(
                    self._vg_name)

            lv_info = lvm.lvdisplay(volume=uniqueid, group=self._vg_name)

            # Configure block device using cgroups (this is idempotent)
            # FIXME(boysson): The unique id <-> cgroup relation should be
            #                 captured in the cgroup module.
            cgrp = os.path.join('treadmill', 'apps', app_unique_name)
            cgutils.create('blkio', cgrp)
            major, minor = lv_info['dev_major'], lv_info['dev_minor']
            cgroups.set_value(
                'blkio', cgrp, 'blkio.throttle.write_bps_device',
                '{major}:{minor} {bps}'.format(
                    major=major,
                    minor=minor,
                    bps=utils.size_to_bytes(write_bps),
                ))
            cgroups.set_value(
                'blkio', cgrp, 'blkio.throttle.read_bps_device',
                '{major}:{minor} {bps}'.format(
                    major=major,
                    minor=minor,
                    bps=utils.size_to_bytes(read_bps),
                ))
            cgroups.set_value(
                'blkio', cgrp, 'blkio.throttle.write_iops_device',
                '{major}:{minor} {iops}'.format(major=major,
                                                minor=minor,
                                                iops=write_iops))
            cgroups.set_value(
                'blkio', cgrp, 'blkio.throttle.read_iops_device',
                '{major}:{minor} {iops}'.format(major=major,
                                                minor=minor,
                                                iops=read_iops))

            volume_data = {
                k: lv_info[k]
                for k in
                ['name', 'block_dev', 'dev_major', 'dev_minor', 'extent_size']
            }

            # Record existence of the volume.
            self._volumes[lv_info['name']] = volume_data

        return volume_data