예제 #1
0
파일: lvm.py 프로젝트: AnyBucket/scalarizr
    def lvm_snapshot(self, name=None, size=None):
        long_kwds = {
                'name': name or '%ssnap' % self.name,
                'snapshot': '%s/%s' % (self.vg, self.name)
        }
        if size:
            size=str(size)
            if '%' in size:
                long_kwds['extents'] = size
            else:
                long_kwds['size'] = size
        else:
            long_kwds['extents'] = '1%ORIGIN'

        lvol = '%s/%s' % (self.vg, long_kwds['name'])
        if lvol in lvm2.lvs():
            lvm2.lvremove(lvol)
        lvm2.lvcreate(**long_kwds)
        lv_info = lvm2.lvs(lvol).values()[0]

        return storage2.snapshot(
                        type='lvm_native',
                        name=lv_info.lv_name,
                        vg=lv_info.vg_name,
                        device=lv_info.lv_path)
예제 #2
0
    def create_snapshot(self, volume_id):
        assert volume_id in self.volumes, 'Volume "%s" not found' % volume_id
        volume = self.volumes[volume_id]

        snapshot_id = str(uuid.uuid4())[:7]
        if not os.path.isdir(snapshot_dir):
            os.makedirs(snapshot_dir)
        snap_path = self._get_snapshot_path(snapshot_id)

        lvm2.lvcreate(os.path.join('/dev', vg_name, volume['id']),
                      snapshot=True,
                      name=snapshot_id,
                      size=snap_size)
        lv_info = None
        try:
            lv_info = lvm2.lvs(lvm2.lvpath(vg_name, snapshot_id)).values()[0]
            system('dd if=%s | cp --sparse=always /dev/stdin %s' %
                   (lv_info.lv_path, snap_path),
                   shell=True)
        finally:
            if lv_info:
                lvm2.lvremove(lv_info.lv_path)
            else:
                lvm2.lvremove(os.path.join('/dev', vg_name, snapshot_id))

        snapshot = dict(id=snapshot_id, size=volume['size'])
        self.snapshots[snapshot_id] = snapshot
        return snapshot
예제 #3
0
    def create_volume(self, **params):
        size = params.get('size')
        snapshot_id = params.get('snapshot')

        assert size or snapshot_id, 'Not enough params to create volume'
        if snapshot_id:
            snapshot = self.describe_snapshot(snapshot_id)
            if size:
                if int(size) < int(snapshot['size']):
                    raise StorageError('Size you specified is smaller than snapshot')
        else:
            # Size in Gigabytes
            size = int(size)

        id = 'vol-%s' % str(uuid.uuid4())[:7]

        lvm2.lvcreate(vg_name, name=id, size='%sG' % size)
        lvinfo = lvm2.lvs(lvm2.lvpath(vg_name, id)).values()[0]
        device = os.path.realpath(lvinfo.lv_path)
        if snapshot_id:
            # Apply snapshot
            system('dd if=%s of=%s' % (self._get_snapshot_path(snapshot_id), device), shell=True)

        stat = os.stat(device)
        maj, min = (os.major(stat.st_rdev), os.minor(stat.st_rdev))

        self.volumes[id] = dict(id=id, attached_to=None, maj=maj, min=min,
                      host_path=device, size=str(size), source_snapshot=snapshot_id)
        return self.volumes[id]
예제 #4
0
    def lvm_snapshot(self, name=None, size=None):
        long_kwds = {
            'name': name or '%ssnap' % self.name,
            'snapshot': '%s/%s' % (self.vg, self.name)
        }
        if size:
            size = str(size)
            if '%' in size:
                long_kwds['extents'] = size
            else:
                long_kwds['size'] = size
        else:
            long_kwds['extents'] = '1%ORIGIN'

        lvol = '%s/%s' % (self.vg, long_kwds['name'])
        if lvol in lvm2.lvs():
            lvm2.lvremove(lvol)
        lvm2.lvcreate(**long_kwds)
        lv_info = lvm2.lvs(lvol).values()[0]

        return storage2.snapshot(type='lvm_native',
                                 name=lv_info.lv_name,
                                 vg=lv_info.vg_name,
                                 device=lv_info.lv_path)
예제 #5
0
    def create_snapshot(self, volume_id):
        assert volume_id in self.volumes, 'Volume "%s" not found' % volume_id
        volume = self.volumes[volume_id]

        snapshot_id = str(uuid.uuid4())[:7]
        if not os.path.isdir(snapshot_dir):
            os.makedirs(snapshot_dir)
        snap_path = self._get_snapshot_path(snapshot_id)

        lvm2.lvcreate(os.path.join('/dev', vg_name, volume['id']), snapshot=True, name=snapshot_id, size=snap_size)
        lv_info = None
        try:
            lv_info = lvm2.lvs(lvm2.lvpath(vg_name, snapshot_id)).values()[0]
            system('dd if=%s | cp --sparse=always /dev/stdin %s' % (lv_info.lv_path, snap_path), shell=True)
        finally:
            if lv_info:
                lvm2.lvremove(lv_info.lv_path)
            else:
                lvm2.lvremove(os.path.join('/dev', vg_name, snapshot_id))

        snapshot = dict(id=snapshot_id, size=volume['size'])
        self.snapshots[snapshot_id] = snapshot
        return snapshot
예제 #6
0
    def create_volume(self, **params):
        size = params.get('size')
        snapshot_id = params.get('snapshot')

        assert size or snapshot_id, 'Not enough params to create volume'
        if snapshot_id:
            snapshot = self.describe_snapshot(snapshot_id)
            if size:
                if int(size) < int(snapshot['size']):
                    raise StorageError(
                        'Size you specified is smaller than snapshot')
        else:
            # Size in Gigabytes
            size = int(size)

        id = 'vol-%s' % str(uuid.uuid4())[:7]

        lvm2.lvcreate(vg_name, name=id, size='%sG' % size)
        lvinfo = lvm2.lvs(lvm2.lvpath(vg_name, id)).values()[0]
        device = os.path.realpath(lvinfo.lv_path)
        if snapshot_id:
            # Apply snapshot
            system('dd if=%s of=%s' %
                   (self._get_snapshot_path(snapshot_id), device),
                   shell=True)

        stat = os.stat(device)
        maj, min = (os.major(stat.st_rdev), os.minor(stat.st_rdev))

        self.volumes[id] = dict(id=id,
                                attached_to=None,
                                maj=maj,
                                min=min,
                                host_path=device,
                                size=str(size),
                                source_snapshot=snapshot_id)
        return self.volumes[id]
예제 #7
0
파일: raid.py 프로젝트: worldline/scalarizr
    def _ensure(self):
        self._v1_compat = self.snap and len(self.snap['disks']) and \
                                        isinstance(self.snap['disks'][0], dict) and \
                                        'snapshot' in self.snap['disks'][0]
        if self.snap:
            disks = []
            snaps = []
            try:
                # @todo: create disks concurrently
                for disk_snap in self.snap['disks']:
                    if self._v1_compat:
                        disk_snap = disk_snap['snapshot']
                    snap = storage2.snapshot(disk_snap)
                    snaps.append(snap)

                if self.disks:
                    if len(self.disks) != len(snaps):
                        raise storage2.StorageError(
                            'Volume disks count is not equal to '
                            'snapshot disks count')
                    self.disks = map(storage2.volume, self.disks)

                # Mixing snapshots to self.volumes (if exist) or empty volumes
                disks = self.disks or [
                    storage2.volume(type=s['type']) for s in snaps
                ]

                for disk, snap in zip(disks, snaps):
                    disk.snap = snap

            except:
                with util.capture_exception(logger=LOG):
                    for disk in disks:
                        disk.destroy()

            self.disks = disks

            if self._v1_compat:
                # is some old snapshots /dev/vgname occured
                self.vg = os.path.basename(self.snap['vg'])
            else:
                self.vg = self.snap['vg']
            self.level = int(self.snap['level'])
            self.pv_uuid = self.snap['pv_uuid']
            self.lvm_group_cfg = self.snap['lvm_group_cfg']

            self.snap = None

        self._check_attr('level')
        self._check_attr('vg')
        self._check_attr('disks')

        assert int(self.level) in (0, 1, 5,
                                   10), 'Unknown raid level: %s' % self.level

        # Making sure autoassembly is disabled before attaching disks
        self._disable_autoassembly()

        disks = []
        for disk in self.disks:
            disk = storage2.volume(disk)
            disk.ensure()
            disks.append(disk)
        self.disks = disks

        disks_devices = [disk.device for disk in self.disks]

        if self.lvm_group_cfg:
            time.sleep(2)  # Give a time to device manager
            try:
                raid_device = mdadm.mdfind(*disks_devices)
            except storage2.StorageError:
                raid_device = mdadm.findname()
                """
                if self.level in (1, 10):
                        for disk in disks_devices:
                                mdadm.mdadm('misc', None, disk,
                                                        zero_superblock=True, force=True)

                        try:
                                kwargs = dict(force=True, metadata='default',
                                                          level=self.level, assume_clean=True,
                                                          raid_devices=len(disks_devices))
                                mdadm.mdadm('create', raid_device, *disks_devices, **kwargs)
                        except:
                                if self.level == 10 and self._v1_compat:
                                        self._v1_repair_raid10(raid_device)
                                else:
                                        raise
                else:
                """
                mdadm.mdadm('assemble', raid_device, *disks_devices)
                mdadm.mdadm('misc',
                            None,
                            raid_device,
                            wait=True,
                            raise_exc=False)

            # Restore vg config
            vg_restore_file = tempfile.mktemp()
            with open(vg_restore_file, 'w') as f:
                f.write(base64.b64decode(self.lvm_group_cfg))

            # Ensure RAID physical volume
            try:
                lvm2.pvs(raid_device)
            except:
                lvm2.pvcreate(raid_device,
                              uuid=self.pv_uuid,
                              restorefile=vg_restore_file)
            finally:
                lvm2.vgcfgrestore(self.vg, file=vg_restore_file)
                os.remove(vg_restore_file)

            # Check that logical volume exists
            lv_infos = lvm2.lvs(self.vg)
            if not lv_infos:
                raise storage2.StorageError(
                    'No logical volumes found in %s vol. group')
            lv_name = lv_infos.popitem()[1].lv_name
            self.device = lvm2.lvpath(self.vg, lv_name)

            # Activate volume group
            lvm2.vgchange(self.vg, available='y')

            # Wait for logical volume device file
            util.wait_until(lambda: os.path.exists(self.device),
                            timeout=120,
                            logger=LOG,
                            error_text='Logical volume %s not found' %
                            self.device)

        else:
            raid_device = mdadm.findname()
            kwargs = dict(force=True,
                          level=self.level,
                          assume_clean=True,
                          raid_devices=len(disks_devices),
                          metadata='default')
            mdadm.mdadm('create', raid_device, *disks_devices, **kwargs)
            mdadm.mdadm('misc', None, raid_device, wait=True, raise_exc=False)

            lvm2.pvcreate(raid_device, force=True)
            self.pv_uuid = lvm2.pvs(raid_device)[raid_device].pv_uuid

            lvm2.vgcreate(self.vg, raid_device)

            out, err = lvm2.lvcreate(self.vg, extents='100%FREE')[:2]
            try:
                clean_out = out.strip().split('\n')[-1].strip()
                vol = re.match(self.lv_re, clean_out).group(1)
                self.device = lvm2.lvpath(self.vg, vol)
            except:
                e = 'Logical volume creation failed: %s\n%s' % (out, err)
                raise Exception(e)

            self.lvm_group_cfg = lvm2.backup_vg_config(self.vg)

        self.raid_pv = raid_device
예제 #8
0
 def _lvinfo(self):
     return lvm2.lvs(lvm2.lvpath(self.vg, self.name)).values()[0]
예제 #9
0
 def _status(self):
     try:
         lvm2.lvs(self.device)
         return self.COMPLETED
     except lvm2.NotFound:
         return self.FAILED
예제 #10
0
파일: raid.py 프로젝트: notbrain/scalarizr
    def _ensure(self):
        self._v1_compat = self.snap and len(self.snap['disks']) and \
                                        isinstance(self.snap['disks'][0], dict) and \
                                        'snapshot' in self.snap['disks'][0]
        if self.snap:
            disks = []
            snaps = []
            try:
                # @todo: create disks concurrently
                for disk_snap in self.snap['disks']:
                    if self._v1_compat:
                        disk_snap = disk_snap['snapshot']
                    snap = storage2.snapshot(disk_snap)
                    snaps.append(snap)

                if self.disks:
                    if len(self.disks) != len(snaps):
                        raise storage2.StorageError('Volume disks count is not equal to '
                                                                                'snapshot disks count')
                    self.disks = map(storage2.volume, self.disks)

                # Mixing snapshots to self.volumes (if exist) or empty volumes
                disks = self.disks or [storage2.volume(type=s['type']) for s in snaps]

                for disk, snap in zip(disks, snaps):
                    disk.snap = snap

            except:
                with util.capture_exception(logger=LOG):
                    for disk in disks:
                        disk.destroy()

            self.disks = disks

            if self._v1_compat:
                # is some old snapshots /dev/vgname occured
                self.vg = os.path.basename(self.snap['vg'])
            else:
                self.vg = self.snap['vg']
            self.level = int(self.snap['level'])
            self.pv_uuid = self.snap['pv_uuid']
            self.lvm_group_cfg = self.snap['lvm_group_cfg']

            self.snap = None

        self._check_attr('level')
        self._check_attr('vg')
        self._check_attr('disks')

        assert int(self.level) in (0,1,5,10), 'Unknown raid level: %s' % self.level

        disks = []
        for disk in self.disks:
            disk = storage2.volume(disk)
            disk.ensure()
            disks.append(disk)
        self.disks = disks

        disks_devices = [disk.device for disk in self.disks]

        if self.lvm_group_cfg:
            try:
                raid_device = mdadm.mdfind(*disks_devices)
            except storage2.StorageError:
                raid_device = mdadm.findname()
                """
                if self.level in (1, 10):
                        for disk in disks_devices:
                                mdadm.mdadm('misc', None, disk,
                                                        zero_superblock=True, force=True)

                        try:
                                kwargs = dict(force=True, metadata='default',
                                                          level=self.level, assume_clean=True,
                                                          raid_devices=len(disks_devices))
                                mdadm.mdadm('create', raid_device, *disks_devices, **kwargs)
                        except:
                                if self.level == 10 and self._v1_compat:
                                        self._v1_repair_raid10(raid_device)
                                else:
                                        raise
                else:
                """
                mdadm.mdadm('assemble', raid_device, *disks_devices)
                mdadm.mdadm('misc', None, raid_device, wait=True, raise_exc=False)

            # Restore vg config
            vg_restore_file = tempfile.mktemp()
            with open(vg_restore_file, 'w') as f:
                f.write(base64.b64decode(self.lvm_group_cfg))

            # Ensure RAID physical volume
            try:
                lvm2.pvs(raid_device)
            except:
                lvm2.pvcreate(raid_device, uuid=self.pv_uuid,
                                        restorefile=vg_restore_file)
            finally:
                lvm2.vgcfgrestore(self.vg, file=vg_restore_file)
                os.remove(vg_restore_file)


            # Check that logical volume exists
            lv_infos = lvm2.lvs(self.vg)
            if not lv_infos:
                raise storage2.StorageError(
                        'No logical volumes found in %s vol. group')
            lv_name = lv_infos.popitem()[1].lv_name
            self.device = lvm2.lvpath(self.vg, lv_name)

            # Activate volume group
            lvm2.vgchange(self.vg, available='y')

            # Wait for logical volume device file
            util.wait_until(lambda: os.path.exists(self.device),
                                    timeout=120, logger=LOG,
                                    error_text='Logical volume %s not found' % self.device)

        else:
            raid_device = mdadm.findname()
            kwargs = dict(force=True, level=self.level, assume_clean=True,
                                      raid_devices=len(disks_devices), metadata='default')
            mdadm.mdadm('create', raid_device, *disks_devices, **kwargs)
            mdadm.mdadm('misc', None, raid_device, wait=True, raise_exc=False)

            lvm2.pvcreate(raid_device, force=True)
            self.pv_uuid = lvm2.pvs(raid_device)[raid_device].pv_uuid

            lvm2.vgcreate(self.vg, raid_device)

            out, err = lvm2.lvcreate(self.vg, extents='100%FREE')[:2]
            try:
                clean_out = out.strip().split('\n')[-1].strip()
                vol = re.match(self.lv_re, clean_out).group(1)
                self.device = lvm2.lvpath(self.vg, vol)
            except:
                e = 'Logical volume creation failed: %s\n%s' % (out, err)
                raise Exception(e)

            self.lvm_group_cfg = lvm2.backup_vg_config(self.vg)

        self.raid_pv = raid_device
예제 #11
0
파일: lvm.py 프로젝트: golovast/scalarizr
	def _lvinfo(self):
		return lvm2.lvs(lvm2.lvpath(self.vg, self.name)).values()[0]
예제 #12
0
파일: lvm.py 프로젝트: golovast/scalarizr
	def _status(self):
		try:
			lvm2.lvs(self.device)
			return self.COMPLETED
		except lvm2.NotFound:
			return self.FAILED