Beispiel #1
0
def test_sudo_xattr_get_set():
    sudo = Sudo()
    name = 'tester'
    source = "abra '{' kadabra '}' abra"
    file = "/var/test-sudo-xattr-get-set"
    sudo.file_save(file, source)
    sudo.xattr_set(file, name, source)
    target = sudo.xattr_get(file, name)
    sudo.files_delete(file)
    assert source == target
Beispiel #2
0
def test_sudo_folder_transfer():
    sudo = Sudo()
    source = "/tmp/nspawn-tester-source"
    target = "/tmp/nspawn-tester-target"
    sudo.folder_ensure(source)
    sudo.files_sync_full(source, target)
    sudo.files_delete(source)
    sudo.files_delete(target)
Beispiel #3
0
class SystemdNspawn(Base):

    base = Sudo()

    def __init__(self):
        super().__init__('wrapper/systemd_nspawn')
        version = SYSTEM_CTL.property_VersionNumber()
        bucket = PartitionBucket.parse_option_list(version, self.option_list)
        if bucket.has_supported():
            supported_list = render_option_list(bucket.supported_list())
            self.with_params(self.binary, supported_list)
        if bucket.has_unsupported():
            unsupported_list = render_option_list(bucket.unsupported_list())
            self.logger.warning(
                f"Removing unsuppoted options: {unsupported_list}")

    def machine_command(self, machine: str, command: Command) -> Command:
        return ['--machine', machine] + command

    def execute_unit(self, machine: str, command: Command) -> ExecuteResult:
        return super().execute_unit(command=self.machine_command(
            machine, command), )

    def execute_flow(self, machine: str, command: Command) -> ExecuteResult:
        return super().execute_flow(command=self.machine_command(
            machine, command), )
Beispiel #4
0
class Tar(Base):

    base = Sudo()

    def __init__(self):
        super().__init__('wrapper/tar')

    def with_archive(self, path):
        self.with_option('file', path)
        return self

    def with_extract(self, path):
        self.with_option('directory', path)
        return self

    def with_compress(self, path):
        self.with_option('use-compress-program', path)
        return self

    def with_make_pack(self):
        self.with_option('create', '.')
        return self

    def with_make_unpack(self):
        self.with_option('extract')
        return self

    def with_packer(self, file):
        self.with_compress(compressor_for(file))
        return self
Beispiel #5
0
class NSEnter(Base):

    base = Sudo()

    systemctl = SystemCtl()

    def __init__(self):
        super().__init__('wrapper/nsenter')

    def execute_invoke(self, machine: str, script: str = None) -> None:
        service = f"{machine}.service"
        init_pid = self.systemctl.machine_init_pid(service)
        root_dir = f"/var/lib/machines/{machine}"
        work_dir = f"/var/lib/machines/{machine}"
        TERM = os.environ.get('TERM')
        option_list = [
            f'-t{init_pid}', f'-r{root_dir}', f'-w{work_dir}', '/usr/bin/env',
            '-i', f'TERM={TERM}', 'sh'
        ]
        if script:
            option_list.extend(['-c', script])
        command = self.full_command(option_list)
        try:
            self.logger.info(f"Invoke nsenter: {command}")
            os.execlp(command[0], *command)
        except Exception as error:
            sys.exit(f"Invoke failure: {error}")
Beispiel #6
0
class Curl(Base):

    base = Sudo()

    def __init__(self):
        super().__init__('wrapper/curl')

    def with_url(self, url):
        self.with_option('url', url)
        return self

    def with_file_get(self, path):
        self.with_option('output', path)
        return self

    def with_file_put(self, path):
        self.with_option('upload-file', path)
        return self

    def with_file_head(self, path):
        self.with_option('output', path)
        self.with_option('head')
        return self

    def with_dump_header(self, path):
        self.with_option('dump-header', path)
        return self

    def with_header(self, text):
        self.with_option('header', text)
        return self

    # needs curl 7.49
    def with_connect_to(self, source_host, source_port, target_host,
                        target_port):
        self.with_option(
            'connect-to',
            f"{source_host}:{source_port}:{target_host}:{target_port}")
        return self

    def with_auth_basic(self, username, password):
        self.with_option('user', f"{username}:{password}")
        return self

    def with_auth_token(self, token):
        self.with_header(f"Authorization: Token {token}")
        return self

    def with_content_type(self, content_type):
        self.with_header(f"Content-Type: {content_type}")
        return self

    def with_no_proxy(self, entry_list: str):
        self.with_option('noproxy', entry_list)
        return self

    def with_proxy_entry(self, proxy_entry: str):
        self.with_option('proxy', proxy_entry)
        return self
Beispiel #7
0
def test_sudo_file_save_load():
    sudo = Sudo()
    source = "abrakadabra"
    file = "/tmp/test_sudo_file_save_load"
    sudo.file_save(file, source)
    target = sudo.file_load(file)
    sudo.files_delete(file)
    assert source == target
Beispiel #8
0
def test_make_file_digest():
    print()
    sudo = Sudo()
    text = ""
    path = "/tmp/test_make_file_digest"
    sudo.file_save(path, text)
    digest = make_file_digest(path)
    sudo.files_delete(path)
    assert digest == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
Beispiel #9
0
class MachineCtl(Base):

    base = Sudo()

    def __init__(self):
        super().__init__('wrapper/machinectl')

    def status(self, machine: str):
        command = ['status', machine]
        return self.execute_unit(command)

    def start(self, machine: str):
        command = ['start', machine]
        return self.execute_unit(command)

    def stop(self, machine: str):
        command = ['stop', machine]
        return self.execute_unit(command)

    def shell(self, machine, script=['pwd']):
        script = ['shell', '--quiet', machine] + script
        return self.execute_unit(script)

    def show(self, machine: str):
        command = ['show', machine]
        return self.execute_unit(command)

    def show_property(self, machine, name):
        command = ['show', '--name', name, '--value', machine]
        return self.execute_unit(command)

    def pid_get(self, machine: str) -> str:
        result = self.show_property(machine, 'Leader')
        result.assert_return()
        return result.stdout.strip()

    def list(self) -> List[MachineDescriptor]:
        command = ['list', '--no-legend']
        result = self.execute_unit(command)
        line_list = result.stdout.splitlines()
        meta_list = list(map(descriptor_from_line, line_list))
        return meta_list

    def has_machine(self, machine: str) -> bool:
        meta_list = self.list()
        machine_list = list(map(lambda store: store.MACHINE, meta_list))
        return machine in machine_list
Beispiel #10
0
class CmdZip(Base):

    base = Sudo()

    def __init__(self):
        super().__init__('wrapper/zip')

    def with_archive(self, path):
        self.with_option('xxx', path)
        return self

    def with_extract(self, path):
        self.with_option('xxx', path)
        return self

    def with_make_pack(self):
        return self

    def with_make_unpack(self):
        raise RuntimeError("wrong operation")
Beispiel #11
0
class CmdUnZip(Base):

    base = Sudo()

    def __init__(self):
        super().__init__('wrapper/unzip')

    def with_archive(self, path):
        self.with_option('file', path)
        return self

    def with_extract(self, path):
        self.with_option('directory', path)
        return self

    def with_make_pack(self):
        raise RuntimeError("Invalid operation")

    def with_make_unpack(self):
        return self
Beispiel #12
0
class CmdUnZip(Base):

    base = Sudo()

    def __init__(self):
        super().__init__('wrapper/unzip')

    def with_archive(self, path: str):
        assert path.endswith(".zip")
        self.option_list.extend([path])
        return self

    def with_extract(self, path: str):
        self.option_list.extend(['-d', path])
        return self

    def with_make_pack(self):
        raise RuntimeError("wrong operation")

    def with_make_unpack(self):
        return self
Beispiel #13
0
def test_sudo_folder_assert():
    sudo = Sudo()
    sudo.folder_assert("/tmp")
Beispiel #14
0
class SystemCtl(Base):

    base = Sudo()

    def __init__(self):
        super().__init__('wrapper/systemctl')

    def status(self, service: str) -> ExecuteResult:
        command = ['status', service]
        return self.execute_unit(command)

    def start(self, service: str) -> ExecuteResult:
        command = ['start', service]
        return self.execute_unit(command)

    def stop(self, service: str) -> ExecuteResult:
        command = ['stop', service]
        return self.execute_unit(command)

    def enable(self, service: str) -> ExecuteResult:
        command = ['enable', service]
        return self.execute_unit(command)

    def disable(self, service: str) -> ExecuteResult:
        command = ['disable', service]
        return self.execute_unit(command)

    def daemon_reload(self) -> ExecuteResult:
        command = ['daemon-reload']
        return self.execute_unit(command)

    def list_unit_files(self, pattern) -> ExecuteResult:
        command = ['list-unit-files', '--no-legend', pattern]
        return self.execute_unit(command)

    def has_unit(self, service: str) -> bool:
        result = self.list_unit_files(service)
        #         result.assert_return()
        has_stdout = result.stdout not in ('', '\n')
        return has_stdout

    def has_active(self, service: str) -> bool:
        command = ['is-active', service]
        return self.has_success(command)

    def has_failed(self, service: str) -> bool:
        command = ['is-failed', service]
        return self.has_success(command)

    def has_enabled(self, service: str) -> bool:
        command = ['is-enabled', service]
        return self.has_success(command)

    def has_machine(self, service: str) -> bool:
        prop_start = 'ExecStart'
        if self.has_property(prop_start, service):
            from nspawn.wrapper.systemd_nspawn import SYSTEMD_NSPAWN
            supervisor = SYSTEMD_NSPAWN.binary
            exec_info = self.show_exec_info(prop_start, service)
            return supervisor == exec_info.path
        else:
            return False

    def has_property(self, name: str, service: str) -> bool:
        value = self.show_property(name, service)
        return value != ''

    def show_property(self, name: str, service: str = None) -> str:
        command = ['show', '--property', name]
        if service:
            command.append(service)
        result = self.execute_unit(command)
        #         result.assert_return()
        entry = result.stdout.strip()
        value = entry.replace(f"{name}=", "")
        return value

    def show_exec_info(self, name: str, service: str) -> ExecInfo:
        value = self.show_property(name, service)
        exec_info = parse_ExecInfo(value)
        return exec_info

    def property_Version(self) -> str:
        return self.show_property('Version')

    def property_VersionNumber(self) -> int:
        version = self.property_Version()
        pattern = re.compile("^([0-9]+).*$")
        matcher = pattern.search(version)
        return int(matcher.group(1))

    def property_ExecMainPID(self, service: str) -> str:
        return self.show_property('ExecMainPID', service)

    def property_ControlGroup(self, service: str) -> str:
        return self.show_property('ControlGroup', service)

    def machine_init_pid(self, service: str) -> str:
        """
        Discover systemd-nspawn init process pid
        """
        # pid of systemd-nspawn
        main_pid = self.property_ExecMainPID(service)
        # service pid hierarchy
        group = self.property_ControlGroup(service)
        # machine group
        group_path = f"/sys/fs/cgroup/systemd/{group}"
        # since systemd v 239
        payload_path = f"{group_path}/payload"

        def process_pid(proc_list: List[str]) -> str:
            assert proc_list
            assert main_pid not in proc_list
            return proc_list[0]

        def process_list(path: str) -> List[str]:
            try:
                with open(path, 'r') as file:
                    return file.read().splitlines()
            except:
                return []

        # native, i.e. systemd inside systemd-nspawn
        native_init_procs = f"{payload_path}/init.scope/cgroup.procs"
        proc_list = process_list(native_init_procs)
        if proc_list:
            return process_pid(proc_list)
        # foreing, i.e. non-systemd inside systemd-nspawn
        foreing_init_procs = f"{payload_path}/cgroup.procs"
        proc_list = process_list(foreing_init_procs)
        if proc_list:
            return process_pid(proc_list)
        # combined parent + child process list
        legacy_init_procs = f"{group_path}/cgroup.procs"
        proc_list = process_list(legacy_init_procs)
        proc_list.remove(main_pid)
        if proc_list:
            return process_pid(proc_list)
        # unsupported case
        raise RuntimeError(f"Missing init proc for '{service}'")
Beispiel #15
0
def test_sudo():
    sudo = Sudo()
    result = sudo.execute_unit(['ls', '-las'])
Beispiel #16
0
def test_sudo_folder_check():
    sudo = Sudo()
    assert sudo.folder_check("/tmp") is True
Beispiel #17
0
def test_sudo_xattr_load_save():
    sudo = Sudo()
    assert sudo.xattr_space() == 'user.nspawn.'
    assert sudo.xattr_regex() == '^user[.]nspawn[.]'
    source = dict(
        num1='1',
        num2='2.0',
        one="one ':' one ':' one",
        two="two '{'} two [']' two",
        any="hello '{'} (###) [']' kitty",
    )
    file = "/var/test-sudo-xattr-load-save"
    sudo.file_save(file, "")
    sudo.xattr_save(file, source)
    target = sudo.xattr_load(file)
    sudo.files_delete(file)
    assert source == target