|
28 | 28 | from kiwi.command import Command |
29 | 29 | from kiwi.volume_manager.base import VolumeManagerBase |
30 | 30 | from kiwi.mount_manager import MountManager |
| 31 | +from kiwi.chroot_manager import ChrootManager |
31 | 32 | from kiwi.storage.mapped_device import MappedDevice |
32 | 33 | from kiwi.filesystem import FileSystem |
33 | 34 | from kiwi.utils.sync import DataSync |
@@ -135,21 +136,14 @@ def setup(self, name=None): |
135 | 136 | ['btrfs', 'subvolume', 'create', root_volume] |
136 | 137 | ) |
137 | 138 | if self.custom_args['root_is_snapper_snapshot']: |
138 | | - snapshot_volume = self.mountpoint + \ |
139 | | - f'/{self.root_volume_name}/.snapshots' |
140 | | - Command.run( |
141 | | - ['btrfs', 'subvolume', 'create', snapshot_volume] |
142 | | - ) |
143 | | - os.chmod(snapshot_volume, 0o700) |
144 | | - Path.create(snapshot_volume + '/1') |
145 | | - snapshot = self.mountpoint + \ |
146 | | - f'/{self.root_volume_name}/.snapshots/1/snapshot' |
147 | | - Command.run( |
148 | | - ['btrfs', 'subvolume', 'create', snapshot] |
149 | | - ) |
150 | | - self._set_default_volume( |
151 | | - f'{self.root_volume_name}/.snapshots/1/snapshot' |
152 | | - ) |
| 139 | + with ChrootManager( |
| 140 | + self.root_dir, binds=[self.mountpoint] |
| 141 | + ) as chroot: |
| 142 | + chroot.run([ |
| 143 | + '/usr/lib/snapper/installation-helper', '--root-prefix', |
| 144 | + os.path.join(self.mountpoint, self.root_volume_name), |
| 145 | + '--step', 'filesystem' |
| 146 | + ]) |
153 | 147 | snapshot = self.mountpoint + \ |
154 | 148 | f'/{self.root_volume_name}/.snapshots/1/snapshot' |
155 | 149 | # Mount /{some-name}/.snapshots as /.snapshots inside the root |
@@ -413,19 +407,24 @@ def sync_data(self, exclude=None): |
413 | 407 | """ |
414 | 408 | if self.toplevel_mount: |
415 | 409 | sync_target = self.get_mountpoint() |
416 | | - if self.custom_args['root_is_snapper_snapshot']: |
417 | | - self._create_snapshot_info( |
418 | | - ''.join( |
419 | | - [ |
420 | | - self.mountpoint, |
421 | | - f'/{self.root_volume_name}/.snapshots/1/info.xml' |
422 | | - ] |
423 | | - ) |
424 | | - ) |
425 | 410 | data = DataSync(self.root_dir, sync_target) |
426 | 411 | data.sync_data( |
427 | 412 | options=Defaults.get_sync_options(), exclude=exclude |
428 | 413 | ) |
| 414 | + if self.custom_args['root_is_snapper_snapshot']: |
| 415 | + root_prefix = os.path.join( |
| 416 | + self.mountpoint, |
| 417 | + f'{self.root_volume_name}/.snapshots/1/snapshot' |
| 418 | + ) |
| 419 | + snapshots_prefix = os.path.join(root_prefix, '.snapshots') |
| 420 | + with ChrootManager( |
| 421 | + self.root_dir, binds=[root_prefix, snapshots_prefix] |
| 422 | + ) as chroot: |
| 423 | + chroot.run([ |
| 424 | + '/usr/lib/snapper/installation-helper', '--root-prefix', |
| 425 | + root_prefix, '--step', 'config', '--description', |
| 426 | + 'first root filesystem' |
| 427 | + ]) |
429 | 428 | if self.custom_args['quota_groups'] and \ |
430 | 429 | self.custom_args['root_is_snapper_snapshot']: |
431 | 430 | self._create_snapper_quota_configuration() |
@@ -503,76 +502,22 @@ def _set_default_volume(self, default_volume): |
503 | 502 | 'Failed to find btrfs volume: %s' % default_volume |
504 | 503 | ) |
505 | 504 |
|
506 | | - def _xml_pretty(self, toplevel_element): |
507 | | - xml_data_unformatted = ElementTree.tostring( |
508 | | - toplevel_element, 'utf-8' |
509 | | - ) |
510 | | - xml_data_domtree = minidom.parseString(xml_data_unformatted) |
511 | | - return xml_data_domtree.toprettyxml(indent=" ") |
512 | | - |
513 | 505 | def _create_snapper_quota_configuration(self): |
514 | 506 | root_path = os.sep.join( |
515 | 507 | [ |
516 | 508 | self.mountpoint, |
517 | 509 | f'{self.root_volume_name}/.snapshots/1/snapshot' |
518 | 510 | ] |
519 | 511 | ) |
520 | | - snapper_default_conf = Defaults.get_snapper_config_template_file( |
521 | | - root_path |
| 512 | + # snapper requires an extra parent qgroup to operate with quotas |
| 513 | + Command.run( |
| 514 | + ['btrfs', 'qgroup', 'create', '1/0', self.mountpoint] |
522 | 515 | ) |
523 | | - if snapper_default_conf: |
524 | | - # snapper requires an extra parent qgroup to operate with quotas |
525 | | - Command.run( |
526 | | - ['btrfs', 'qgroup', 'create', '1/0', self.mountpoint] |
527 | | - ) |
528 | | - config_file = self._set_snapper_sysconfig_file(root_path) |
529 | | - if not os.path.exists(config_file): |
530 | | - shutil.copyfile(snapper_default_conf, config_file) |
531 | | - Command.run([ |
532 | | - 'chroot', root_path, 'snapper', '--no-dbus', 'set-config', |
533 | | - 'QGROUP=1/0' |
| 516 | + with ChrootManager(root_path) as chroot: |
| 517 | + chroot.run([ |
| 518 | + 'snapper', '--no-dbus', 'set-config', 'QGROUP=1/0' |
534 | 519 | ]) |
535 | 520 |
|
536 | | - @staticmethod |
537 | | - def _set_snapper_sysconfig_file(root_path): |
538 | | - sysconf_file = SysConfig( |
539 | | - os.sep.join([root_path, 'etc/sysconfig/snapper']) |
540 | | - ) |
541 | | - if not sysconf_file.get('SNAPPER_CONFIGS') or \ |
542 | | - len(sysconf_file['SNAPPER_CONFIGS'].strip('\"')) == 0: |
543 | | - |
544 | | - sysconf_file['SNAPPER_CONFIGS'] = '"root"' |
545 | | - sysconf_file.write() |
546 | | - elif len(sysconf_file['SNAPPER_CONFIGS'].split()) > 1: |
547 | | - raise KiwiVolumeManagerSetupError( |
548 | | - 'Unsupported SNAPPER_CONFIGS value: {0}'.format( |
549 | | - sysconf_file['SNAPPER_CONFIGS'] |
550 | | - ) |
551 | | - ) |
552 | | - return os.sep.join([ |
553 | | - root_path, 'etc/snapper/configs', |
554 | | - sysconf_file['SNAPPER_CONFIGS'].strip('\"')] |
555 | | - ) |
556 | | - |
557 | | - def _create_snapshot_info(self, filename): |
558 | | - date_info = datetime.datetime.now() |
559 | | - snapshot = ElementTree.Element('snapshot') |
560 | | - |
561 | | - snapshot_type = ElementTree.SubElement(snapshot, 'type') |
562 | | - snapshot_type.text = 'single' |
563 | | - |
564 | | - snapshot_number = ElementTree.SubElement(snapshot, 'num') |
565 | | - snapshot_number.text = '1' |
566 | | - |
567 | | - snapshot_description = ElementTree.SubElement(snapshot, 'description') |
568 | | - snapshot_description.text = 'first root filesystem' |
569 | | - |
570 | | - snapshot_date = ElementTree.SubElement(snapshot, 'date') |
571 | | - snapshot_date.text = date_info.strftime("%Y-%m-%d %H:%M:%S") |
572 | | - |
573 | | - with open(filename, 'w') as snapshot_info_file: |
574 | | - snapshot_info_file.write(self._xml_pretty(snapshot)) |
575 | | - |
576 | 521 | def __exit__(self, exc_type, exc_value, traceback): |
577 | 522 | if self.toplevel_mount: |
578 | 523 | self.umount_volumes() |
0 commit comments