예제 #1
0
    def test_apply_commands(self):
        fstab_lines = "\\n".join(
            [
                "",
                "# name (originally device)",
                "device\\tnone\\tswap\\tdefaults\\t0\\t0",
            ]
        )

        expected = [
            Command(
                [
                    "mkswap",
                    "device",
                    "--label=label",
                    "--pagesize=pagesize",
                    "--uuid=uuid",
                ]
            ),
            Command(["swapon", "device"]),
            Command(
                [
                    "shell",
                    "-c",
                    "'echo -e \"{}\" >> tmp_dir/etc/fstab'".format(fstab_lines),
                ]
            ),
        ]
        self.assertListEqual(
            expected,
            list(self.specification.apply(self.context)),
        )
예제 #2
0
    def __call__(self, context: CommandContext) -> Iterator[Command]:
        file_path = context.graph.resolve_path(self.specification.name)
        if not file_path:
            raise ValueError("Failed to find file path {}".format(
                self.specification.name))
        media_file_path = context.config.media_path(file_path)

        yield mkdir(os.path.dirname(media_file_path))
        if self.specification.size:
            yield Command([
                "fallocate",
                "--length",
                self.specification.size,
                quote_argument(media_file_path),
            ])
        else:
            yield Command(["touch", quote_argument(media_file_path)])
        if self.specification.owner or self.specification.group:
            yield chown(
                self.specification.owner,
                self.specification.group,
                media_file_path,
            )
        if self.specification.mode:
            yield chmod(self.specification.mode, media_file_path)
예제 #3
0
    def test_run(self, make_mode, make_action):
        spec1 = TestSpecification("spec1", [Command(["1"]), Command(["2"])])
        spec2 = TestSpecification("spec2", [Command(["3"]), Command(["4"])])

        config = Configuration(
            shell="",
            dd_bs="",
            random_device="",
            media_dir="",
            tmp_dir="",
        )
        graph = Graph([spec1, spec2])

        mode = MagicMock()
        action = MagicMock()

        make_mode.return_value = mode
        make_action.return_value = action

        run(config, graph, "action", "mode")

        action.assert_called_once_with(mode, AnyIter([spec1, spec2]))

        make_action.assert_called_once_with("action", AnyType())
        make_mode.assert_called_once_with("mode")
예제 #4
0
    def test_apply_commands(self):
        crypttab_lines = "\\n".join([
            "",
            "# name (originally device)",
            "name\\tdevice\\t/keyfile\\topt,ions",
        ])

        expected = [
            Command([
                "cryptsetup",
                "--batch-mode",
                "--key-file=/keyfile",
                "open",
                "device",
                "name",
                "--type=type",
            ]),
            Command([
                "shell",
                "-c",
                "'echo -e \"{}\" >> tmp_dir/etc/crypttab'".format(
                    crypttab_lines),
            ]),
        ]
        self.assertListEqual(
            expected,
            list(self.specification.apply(self.context)),
        )
예제 #5
0
    def test_apply_commands(self):
        fstab_lines = "\\n".join([
            "",
            "# name (originally device)",
            "device\\tmountpoint\\ttype\\topt,ions\\t1\\t2",
        ])

        expected = [
            Command([
                "mount",
                "--types",
                "type",
                "-o",
                "opt,ions",
                "device",
                "media_dir/mountpoint",
            ]),
            Command([
                "shell",
                "-c",
                "'echo -e \"{}\" >> tmp_dir/etc/fstab'".format(fstab_lines),
            ]),
        ]
        self.assertListEqual(
            expected,
            list(self.specification.apply(self.context)),
        )
예제 #6
0
def _format_crypt(
    context: CommandContext,
    device: str,
    keyfile: str,
    type: str,
    password: Optional[str],
) -> Iterator[Command]:
    yield Command(
        _cryptsetup(
            f"--key-file={quote_argument(keyfile)}",
            "luksFormat",
            f"--type={type}",
            quote_argument(device),
        ))
    if password:
        add_key_cmd = " ".join(
            _cryptsetup(
                f"--key-file={quote_argument(keyfile)}",
                "luksAddKey",
                quote_argument(device),
            ))
        yield Command([
            quote_argument(context.config.shell),
            "-c",
            quote_subcommand(f"echo {password} | {add_key_cmd}"),
        ])
예제 #7
0
def _randomize_device(
    name: str,
    device: str,
    context: CommandContext,
) -> Iterator[Command]:
    cryptname = f"randomize_{name}"

    yield Command(
        _open_crypt(
            cryptname,
            device,
            context.config.random_device,
            "plain",
        ))
    dd_cmd = " ".join(
        _dd(
            "if=/dev/zero",
            f"of={quote_argument(_crypt_device(cryptname))}",
            f"bs={context.config.dd_bs}",
        ))
    yield Command(
        [context.config.shell, "-c",
         quote_subcommand(f"{dd_cmd} || true")])
    yield Command(["sync"])
    yield Command(_close_crypt(cryptname))
예제 #8
0
 def test_apply_commands(self):
     expected = [
         Command(["mkdir", "--parents", "media_dir/name"]),
         Command(["chown", "owner:group", "media_dir/name"]),
         Command(["chmod", "mode", "media_dir/name"]),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.apply(self.context)),
     )
예제 #9
0
    def __call__(self, context: CommandContext) -> Iterator[Command]:
        yield mkdir(context.config.tmp_path("/etc"))

        tmp_fstab_path = context.config.tmp_path("/etc/fstab")
        yield Command(["truncate", "--size=0", tmp_fstab_path])
        yield chmod("0644", tmp_fstab_path)
        yield chown("root", "root", tmp_fstab_path)

        tmp_crypttab_path = context.config.tmp_path("/etc/crypttab")
        yield Command(["truncate", "--size=0", tmp_crypttab_path])
        yield chmod("0644", tmp_crypttab_path)
        yield chown("root", "root", tmp_crypttab_path)
예제 #10
0
    def __call__(self, context: CommandContext) -> Iterator[Command]:
        device_path = context.graph.resolve_device(self.specification.device)
        if not device_path:
            raise ValueError("Failed to find device path {}".format(
                self.specification.device))

        yield Command(["pvcreate", quote_argument(device_path)])
예제 #11
0
    def __call__(self, context: CommandContext) -> Iterator[Command]:
        lvm_physical_volume_paths = [
            _lvm_physical_volume_path(lvm_physical_volume, context)
            for lvm_physical_volume in self.specification.lvm_physical_volumes
        ]

        cmd = [
            "lvcreate",
            f"--name={self.specification.name}",
        ]
        if self.specification.size:
            cmd.append(f"--size={self.specification.size}")
        if self.specification.extents:
            cmd.append(f"--extents={self.specification.extents}")
        if self.specification.type:
            cmd.append(f"--type={self.specification.type}")
        if self.specification.lvm_poolmetadata_volume:
            cmd.append(
                f"--poolmetadata={self.specification.lvm_poolmetadata_volume}",
            )
        if self.specification.lvm_cachepool_volume:
            cmd.append(f"--cachepool={self.specification.lvm_cachepool_volume}")
        if self.specification.lvm_thinpool_volume:
            cmd.append(f"--thinpool={self.specification.lvm_thinpool_volume}")
        cmd += self.specification.args
        cmd.append(self.specification.lvm_volume_group)
        cmd += [quote_argument(path) for path in lvm_physical_volume_paths]

        yield Command(cmd)
예제 #12
0
 def test_apply_commands(self):
     expected = [
         Command([
             "parted",
             "--script",
             "--",
             "partition_table",
             "mkpart",
             "type",
             "start",
             "end",
             "name",
             "1",
             "label",
             "unit",
             "unit",
             "set",
             "1",
             "flags",
             "on",
         ]),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.apply(self.context)),
     )
예제 #13
0
 def test_up_commands(self):
     expected = [
         Command(["mdadm", "--assemble", "/dev/md/name", "device"]),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.up(self.context)),
     )
예제 #14
0
 def test_apply_commands(self):
     expected = [
         Command(["vgcreate", "name", "lvm_physical_volume"]),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.apply(self.context)),
     )
예제 #15
0
 def test_apply_commands(self):
     expected = [
         Command(["parted", "--script", "--", "device", "mklabel", "type"]),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.apply(self.context)),
     )
예제 #16
0
 def test_down_commands(self):
     expected = [
         Command(["umount", "media_dir/mountpoint"]),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.down(self.context)),
     )
예제 #17
0
    def test_up_commands(self):
        handler = MagicMock()

        UpAction(self.context)(handler, self.generators)

        handler.on_begin.assert_called_once_with(self.context)
        handler.on_generator.assert_has_calls([
            call(self.context, TestActionCommandGenerator("gen_1")),
            call(self.context, TestActionCommandGenerator("gen_2")),
        ])
        handler.on_command.assert_has_calls([
            call(self.context, Command(["up_1"])),
            call(self.context, Command(["up_2"])),
            call(self.context, Command(["up_3"])),
            call(self.context, Command(["up_4"])),
        ])
        handler.on_end.assert_called_once_with(self.context)
예제 #18
0
 def test_down_commands(self):
     expected = [
         Command(["losetup", "--detach", '"$loop_device_name"']),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.down(self.context)),
     )
예제 #19
0
 def test_apply_commands(self):
     expected = [
         Command(["mkfs", "--type", "type", "opt", "ions", "device"]),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.apply(self.context)),
     )
예제 #20
0
 def test_apply_commands(self):
     expected = [
         Command(["pvcreate", "device"]),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.apply(self.context)),
     )
예제 #21
0
 def test_down_commands(self):
     expected = [
         Command(["vgchange", "--activate", "n", "name"]),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.down(self.context)),
     )
예제 #22
0
 def test_down_commands(self):
     expected = [
         Command(["swapoff", "device"]),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.down(self.context)),
     )
예제 #23
0
 def test_down_commands(self):
     expected = [
         Command(["mdadm", "--stop", "/dev/md/name"]),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.down(self.context)),
     )
예제 #24
0
    def __call__(self, context: CommandContext) -> Iterator[Command]:
        lvm_physical_volume_paths = [
            _lvm_physical_volume_path(lvm_physical_volume, context)
            for lvm_physical_volume in self.specification.lvm_physical_volumes
        ]

        yield Command(
            ["vgcreate", self.specification.name] +
            [quote_argument(path) for path in lvm_physical_volume_paths])
예제 #25
0
    def __call__(self, context: CommandContext) -> Iterator[Command]:
        file_path = _file_path(self.specification.file, context)
        media_file_path = context.config.media_path(file_path)

        cmd = [
            context.config.shell,
            "-c",
            quote_subcommand(_find_loop_device(media_file_path)),
        ]
        yield Command(cmd, capture=self.specification.capture)
예제 #26
0
 def test_up_commands(self):
     expected = [
         Command(
             cmd=["losetup", "args", "--find", "--show", "media_dir/file"],
             capture="loop_device_name",
         ),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.up(self.context)),
     )
예제 #27
0
 def test_post_apply_commands(self):
     expected = [
         Command(["mkdir", "--parents", "media_dir/etc"]),
         Command([
             "cp",
             "tmp_dir/etc/fstab",
             "media_dir/etc/fstab",
             "--preserve=mode,ownership",
         ]),
         Command([
             "cp",
             "tmp_dir/etc/crypttab",
             "media_dir/etc/crypttab",
             "--preserve=mode,ownership",
         ]),
     ]
     self.assertListEqual(
         expected,
         list(self.specification.post_apply(self.context)),
     )
예제 #28
0
    def __call__(self, context: CommandContext) -> Iterator[Command]:
        _, media_device_path = _device_path(self.specification.device, context)
        type = (self.specification.type
                if self.specification.ephemeral_keyfile() else None)

        yield Command(
            _open_crypt(
                self.specification.name,
                media_device_path,
                self.specification.tmp_keyfile_path(context),
                type,
            ))
예제 #29
0
    def __call__(self, context: CommandContext) -> Iterator[Command]:
        file_path = _file_path(self.specification.file, context)
        media_file_path = context.config.media_path(file_path)

        cmd = [
            "losetup",
            *self.specification.args,
            "--find",
            "--show",
            quote_argument(media_file_path),
        ]

        yield Command(cmd, capture=self.specification.capture)
예제 #30
0
def _create_keyfile(
    keyfile: str,
    keysize: str,
    context: CommandContext,
) -> Iterator[Command]:
    yield mkdir(os.path.dirname(keyfile))
    yield Command(
        _dd(
            f"if={quote_argument(context.config.random_device)}",
            f"of={quote_argument(keyfile)}",
            f"bs={keysize}",
            "count=1",
        ))