Example #1
0
 def test_layer_from_demo_sendstreams(self):
     # `btrfs_diff.demo_sendstream` produces a subvolume send-stream with
     # fairly thorough coverage of filesystem features.  This test grabs
     # that send-stream, receives it into an `image_layer`, and validates
     # that the send-stream of the **received** volume has the same
     # rendering as the original send-stream was supposed to have.
     #
     # In other words, besides testing `image_sendstream_layer`, this is
     # also a test of idempotence for btrfs send+receive.
     #
     # Notes:
     #  - `compiler/tests/TARGETS` explains why `mutate_ops` is not here.
     #  - Currently, `mutate_ops` also uses `--no-data`, which would
     #    break this test of idempotence.
     for original_name, subvol_name, mount_config in [
         ('create_ops', 'create_ops', None),
         ('create_ops', 'create_ops-from-dir', None),
         ('create_ops', 'create_ops-from-layer', None),
         ('create_ops', 'create_ops-alias', {
             'build_source': {
                 'type': 'layer',
                 'source': '//fs_image/compiler/tests:create_ops',
             }
         }),
     ]:
         with self.target_subvol(
                 subvol_name,
                 mount_config=mount_config,
         ) as sv:
             self.assertEqual(
                 render_demo_subvols(**{original_name: original_name}),
                 render_sendstream(sv.mark_readonly_and_get_sendstream()),
             )
Example #2
0
def _render_sendstream_path(path):
    if path.endswith('.zst'):
        data = subprocess.check_output(
            ['zstd', '--decompress', '--stdout', path]
        )
    else:
        with open(path, 'rb') as infile:
            data = infile.read()
    return render_sendstream(data)
Example #3
0
 def test_receive(self, temp_subvols):
     new_subvol_name = 'differs_from_create_ops'
     sv = temp_subvols.caller_will_create(new_subvol_name)
     with open(Path(__file__).dirname() / 'create_ops.sendstream') as f, \
             sv.receive(f):
         pass
     self.assertEqual(
         render_demo_subvols(create_ops=new_subvol_name),
         render_sendstream(sv.mark_readonly_and_get_sendstream()),
     )
Example #4
0
    def _assert_sendstream_files_equal(self, path1: str, path2: str):
        renders = []
        for path in [path1, path2]:
            if path.endswith('.zst'):
                data = subprocess.check_output(
                    ['zstd', '--decompress', '--stdout', path])
            else:
                with open(path, 'rb') as infile:
                    data = infile.read()
            renders.append(render_sendstream(data))

        self.assertEqual(*renders)
Example #5
0
 def test_check_layers(self):
     meta = {
         'meta': [
             '(Dir)', {
                 'private': [
                     '(Dir)', {
                         'opts': [
                             '(Dir)', {
                                 'artifacts_may_require_repo':
                                 ['(File d2)'],
                             }
                         ]
                     }
                 ]
             }
         ]
     }
     # The parent has a couple of directories.
     self.assertEqual(
         ['(Dir)', {
             'a': ['(Dir)', {
                 'b': ['(Dir)', {}]
             }],
             **meta
         }],
         render_sendstream(
             find_built_subvol(self._resource_path(
                 'parent')).mark_readonly_and_get_sendstream()),
     )
     # The child is near-empty because the `remove_paths` cleaned it up.
     self.assertEqual(
         ['(Dir)', {
             **meta
         }],
         render_sendstream(
             find_built_subvol(self._resource_path(
                 'child')).mark_readonly_and_get_sendstream()),
     )
Example #6
0
 def test_receive_sendstream(self):
     item = ReceiveSendstreamItem(
         from_target='t',
         source=Path(__file__).dirname() / 'create_ops.sendstream',
     )
     self.assertEqual(PhaseOrder.MAKE_SUBVOL, item.phase_order())
     with TempSubvolumes(sys.argv[0]) as temp_subvolumes:
         new_subvol_name = 'differs_from_create_ops'
         subvol = temp_subvolumes.caller_will_create(new_subvol_name)
         item.get_phase_builder([item], DUMMY_LAYER_OPTS)(subvol)
         self.assertEqual(
             render_demo_subvols(create_ops=new_subvol_name),
             render_sendstream(subvol.mark_readonly_and_get_sendstream()),
         )
Example #7
0
 def test_check_layers(self):
     # The parent has a couple of directories.
     self.assertEqual(
         [
             '(Dir)', {
                 'a': ['(Dir)', {
                     'b': ['(Dir)', {}]
                 }],
                 'meta': ['(Dir)', {}],
             }
         ],
         render_sendstream(
             find_built_subvol(self._resource_path(
                 'parent')).mark_readonly_and_get_sendstream()),
     )
     # The child is near-empty because the `remove_paths` cleaned it up.
     self.assertEqual(
         ['(Dir)', {
             'meta': ['(Dir)', {}]
         }],
         render_sendstream(
             find_built_subvol(self._resource_path(
                 'child')).mark_readonly_and_get_sendstream()),
     )
Example #8
0
 def test_layer_from_demo_sendstreams(self):
     # `btrfs_diff.demo_sendstream` produces a subvolume send-stream with
     # fairly thorough coverage of filesystem features.  This test grabs
     # that send-stream, receives it into an `image_layer`, and validates
     # that the send-stream of the **received** volume has the same
     # rendering as the original send-stream was supposed to have.
     #
     # In other words, besides testing `image_layer`'s `from_sendstream`,
     # this is also a test of idempotence for btrfs send+receive.
     #
     # Notes:
     #  - `compiler/tests/TARGETS` explains why `mutate_ops` is not here.
     #  - Currently, `mutate_ops` also uses `--no-data`, which would
     #    break this test of idempotence.
     for op in ['create_ops']:
         with self.target_subvol(op) as sv:
             self.assertEqual(
                 render_demo_subvols(**{op: True}),
                 render_sendstream(sv.mark_readonly_and_get_sendstream()),
             )
Example #9
0
    def test_write_to_tarball(self, temp_subvols):
        # create a subvol from a demo sendstream, tar it, untar into a new
        # subvol, then compare the two
        demo_sv_name = 'demo_sv'
        demo_sv = temp_subvols.caller_will_create(demo_sv_name)
        with open(Path(__file__).dirname() / 'create_ops.sendstream') as f, \
                demo_sv.receive(f):
            pass

        unpacked_sv = temp_subvols.create('subvol')
        with tempfile.NamedTemporaryFile() as tar_file:
            with demo_sv.write_to_tarball(tar_file):
                pass

            demo_sv.run_as_root([
                'tar',
                'xzf',
                tar_file.name,
                '--xattrs',
                '-C',
                unpacked_sv.path(),
            ])

        demo_render = render_demo_subvols(create_ops=demo_sv_name)
        # Tar does not preserve the original's cloned extents of
        # zeros
        demo_render[1]['56KB_nuls'] = ['(File d57344)']
        demo_render[1]['56KB_nuls_clone'] = ['(File d57344)']
        # Tar des not preserve unix domain sockets, as these are usable only for
        # the lifetime of the associated process and should therefore be safe to
        # ignore.
        demo_render[1].pop('unix_sock')

        self.assertEqual(
            demo_render,
            render_sendstream(unpacked_sv.mark_readonly_and_get_sendstream()),
        )
Example #10
0
    def test_build_appliance(self):
        with self.target_subvol('validates-build-appliance') as sv:
            r = render_sendstream(sv.mark_readonly_and_get_sendstream())

            ino, = _pop_path(r, 'bin/sh')  # Busybox from `rpm-test-milk`
            # NB: We changed permissions on this at some point, but after
            # the migration diffs land, the [75] can become a 5.
            self.assertRegex(ino, r'^\(File m[75]55 d[0-9]+\)$')

            ino, = _pop_path(r, 'var/log/yum.log')
            self.assertRegex(ino, r'^\(File m600 d[0-9]+\)$')

            # Ignore a bunch of yum & RPM spam
            for ignore_dir in [
                    'usr/lib/.build-id',
                    'var/cache/yum',
                    'var/lib/rpm',
                    'var/lib/yum',
            ]:
                ino, _ = _pop_path(r, ignore_dir)
                self.assertEqual('(Dir)', ino)

            self.assertEqual(
                [
                    '(Dir)',
                    {
                        'bin': ['(Dir)', {}],
                        'dev': ['(Dir)', {}],
                        'meta': [
                            '(Dir)', {
                                'private': [
                                    '(Dir)', {
                                        'opts': [
                                            '(Dir)', {
                                                'artifacts_may_require_repo':
                                                ['(File d2)'],
                                            }
                                        ]
                                    }
                                ]
                            }
                        ],
                        'usr': [
                            '(Dir)',
                            {
                                'lib': ['(Dir)', {}],
                                'share': [
                                    '(Dir)',
                                    {
                                        'rpm_test': [
                                            '(Dir)',
                                            {
                                                'milk.txt': ['(File d12)'],
                                                # From the `rpm-test-milk` post-install script
                                                'post.txt': ['(File d6)'],
                                            }
                                        ],
                                    }
                                ],
                            }
                        ],
                        'var': [
                            '(Dir)', {
                                'cache': ['(Dir)', {}],
                                'lib': ['(Dir)', {}],
                                'log': ['(Dir)', {}],
                                'tmp': ['(Dir)', {}],
                            }
                        ],
                    }
                ],
                r)
Example #11
0
def _render_subvol(subvol: 'Subvol'):
    rendered = render_sendstream(subvol.mark_readonly_and_get_sendstream())
    subvol.set_readonly(False)  # YES, all our subvolumes are read-write.
    return rendered
Example #12
0
 def _assert_sendstream_files_equal(self, path1: str, path2: str):
     renders = []
     for path in [path1, path2]:
         with open(path, 'rb') as infile:
             renders.append(render_sendstream(infile.read()))
     self.assertEqual(*renders)