def migrate(self, pool, source, target): """ Replace a device in a btrfs pool. Parameters ---------- pool : [str] Pool into which the replaced device belongs. source : [main.DeviceItem] Source device. target : [str] Path to the target device. """ pool = self._pool[pool] if 'mount' not in pool: tmp = misc.temp_mount("UUID={0}".format(pool['uuid'])) pool['mount'] = tmp dev = BtrfsDev(options=self.options).data command = ['replace', 'start'] if self.options.force: command.extend(['-f']) command.extend(['-B', source.name, target, pool['mount']]) self.run_btrfs(command) misc.send_udev_event(target, "change") self._udev_checkpoint_fs(pool['pool_name'])
def resize(self, vol, size, resize_fs=True): vol = self.data[vol] if 'mount' not in vol: tmp = misc.temp_mount("UUID={0}".format(vol['uuid'])) vol['mount'] = tmp command = ['filesystem', 'resize', str(int(size)) + "K", vol['mount']] self.run_btrfs(command)
def create(self, pool, size=None, name=None, devs=None, options=None): options = options or {} if pool in self._pool: vol = None if size or 'raid' in options: self.problem.warn("Only name, volume name and pool name " + "can be specified when creating btrfs " + "subvolume, the rest will be ignored") tmp = misc.temp_mount("UUID={0}".format(self._pool[pool]['uuid'])) self._pool[pool]['mount'] = tmp if not name: now = datetime.datetime.now() name = now.strftime("%Y-%m-%d-T%H%M%S") vol = "{0}/{1}".format(self._pool[pool]['mount'], name) elif os.path.isabs(name): vol = name else: vol = "{0}/{1}".format(self._pool[pool]['mount'], name) self._check_new_path(vol, name) self.run_btrfs(['subvolume', 'create', vol]) vol = "{0}:{1}".format(pool, name) else: if len(devs) == 0: self.problem.check(self.problem.NO_DEVICES, pool) if name: self.problem.warn("Creating new pool. Argument (--name " + "{0}) will be ignored!".format(name)) vol = self._create_filesystem(pool, pool, devs, size, options) return vol
def reduce(self, pool, device): pool = self.data[pool] if 'mount' not in pool: tmp = misc.temp_mount("UUID={0}".format(pool['uuid'])) pool['mount'] = tmp command = ['device', 'delete', device, pool['mount']] self.run_btrfs(command) self._udev_checkpoint_fs(pool['pool_name'])
def reduce(self, pool, device): pool = self.data[pool] if 'mount' not in pool: tmp = misc.temp_mount("UUID={0}".format(pool['uuid'])) pool['mount'] = tmp command = ['device', 'delete', device, pool['mount']] self.run_btrfs(command) misc.send_udev_event(device, "change")
def resize(self, vol, size, resize_fs=True): vol = self.data[vol] if 'mount' not in vol: tmp = misc.temp_mount("UUID={0}".format(vol['uuid'])) vol['mount'] = tmp if 'subvolume' in vol and vol['subvolume'] is True: self.problem.check(self.problem.NOT_SUPPORTED, 'Resizing btrfs subvolume') command = ['filesystem', 'resize', str(int(size)) + "K", vol['mount']] self.run_btrfs(command) self._udev_checkpoint_fs(vol['pool_name'])
def extend(self, pool, devices): pool = self.data[pool] if 'mount' not in pool: tmp = misc.temp_mount("UUID={0}".format(pool['uuid'])) pool['mount'] = tmp if type(devices) is not list: devices = [devices] command = ['device', 'add'] command.extend(devices) command.append(pool['mount']) self.run_btrfs(command)
def snapshot(self, vol, destination, name, snap_size=None): vol = self[vol] if 'mount' not in vol: tmp = misc.temp_mount("UUID={0}".format(vol['uuid'])) vol['mount'] = tmp if not destination and not name: now = datetime.datetime.now() destination = vol['mount'] + now.strftime("/snap-%Y-%m-%d-T%H%M%S") if name: destination = vol['mount'] + "/" + name if snap_size: self.problem.warn("Btrfs doesn't allow setting a size of " + "subvolumes") command = ['subvolume', 'snapshot', vol['mount'], destination] self.run_btrfs(command)
def remove(self, vol): volume = self._vol[vol] if 'subvolume' in volume: # If subvolume is mounted directly we can not remove it. So ask # user whether he wants to umount it. The we'll have to mount the # root subvolume and remove this subvolume. if 'direct_mount' in volume and volume['direct_mount']: if self.problem.check(self.problem.FS_MOUNTED, [vol, volume['mount']]): misc.do_umount(volume['mount']) del volume['mount'] del volume['direct_mount'] if 'mount' not in volume: mount = misc.temp_mount("UUID={0}".format(volume['uuid'])) path = "{0}/{1}".format(mount, volume['path']) else: path = volume['mount'] self.run_btrfs(['subvolume', 'delete', path]) else: self._remove_filesystem(vol)
def extend(self, pool, devices): pool = self.data[pool] if 'mount' not in pool: tmp = misc.temp_mount("UUID={0}".format(pool['uuid'])) pool['mount'] = tmp if type(devices) is not list: devices = [devices] command = ['device', 'add'] # This might seem weird, but btrfs is mostly broken when it comes to # checking existing signatures because it will for example check for # backup superblocks as well, which is wrong. Also we have check for # existing file system signatures in the ssm itself. Other things # than file system should be covered by the backend and we should # have tried to remove the device from the respective pool already. # So at this point there should not be any useful signatures to # speak of. However as I mentioned btrfs is broken, so force it. if self._can_btrfs_force(['btrfs', 'device', 'add']): command.extend(['--force']) command.extend(devices) command.append(pool['mount']) self.run_btrfs(command) misc.udev_checkpoint(devices)