Esempio n. 1
0
    def _execute(self):
        self.source_remote_executor = RemoteHostExecutor(self._source.remote_host)
        self._execute_on_every_device(self._sync_disk, self._sync_partition)
        self.source_remote_executor.close()
        self.source_remote_executor = None

        return Commander.Signal.SLEEP
Esempio n. 2
0
 def __init__(self, remote_host):
     """
     
     :param remote_host: the remote host to execute on
     :type remote_host: remote_host.public.RemoteHost
     """
     self.remote_executor = RemoteHostExecutor(remote_host)
Esempio n. 3
0
 def _execute(self):
     self.source_remote_executor = RemoteHostExecutor(
         self._source.remote_host)
     self._execute_on_every_device(self._replicate_partition_table,
                                   None,
                                   include_swap=True)
     self.source_remote_executor.close()
     self.source_remote_executor = None
Esempio n. 4
0
 def _execute(self):
     root_source_mountpoint = self._find_root_source_mountpoint()
     remote_executor = RemoteHostExecutor(self._target.remote_host)
     self._create_source_environment_mountpoints(remote_executor,
                                                 root_source_mountpoint)
     self._mount_source_environment(remote_executor, root_source_mountpoint)
     self._mount_source_mountpoints(remote_executor, root_source_mountpoint)
     self._reinstall_bootloader(remote_executor, root_source_mountpoint)
Esempio n. 5
0
 def _comment_out_listen_address(self):
     """
     comments out the ListenAddress line in the sshd_config file
     """
     RemoteFileEditor(RemoteHostExecutor(self._target.remote_host)).edit(
         SourceFileLocationResolver(self._source).resolve_path(self.SSHD_CONFIG_LOCATION),
         'ListenAddress',
         '# ListenAddress'
     )
Esempio n. 6
0
 def _write_network_config(self, network_config):
     """
     wirtes a given network config to the network config file
     
     :param network_config: the network config to persist
     :type network_config: str
     """
     RemoteFileEditor(RemoteHostExecutor(self._target.remote_host)).write(
         SourceFileLocationResolver(self._source).resolve_path(self.NETWORK_CONFIG_FILE_LOCATION),
         network_config
     )
Esempio n. 7
0
    def _execute_on_every_device(self,
                                 executable_for_disks,
                                 executable_for_partitions=None,
                                 include_swap=False):
        """
        execute the given executable with all devices.
        
        :param executable_for_disks: a function which takes the parameters: remote_executor, source_device, 
        target_device
        :type executable_for_disks: (self: Any, RemoteExecutor, (str, dict), (str, dict)) -> None
        :param executable: a function which takes the parameters: remote_executor, source_device, 
        target_device, source_partition_device, target_partition_device
        :type executable_for_partitions: (self: Any, RemoteExecutor, (str, dict), (str, dict), (str, dict), (str, dict)
        ) -> None
        :param include_swap: should a swap device also be iterated over
        :type include_swap: bool
        :return: the used remote_executor, for extended use
        :rtype: RemoteHostExecutor
        """
        remote_executor = RemoteHostExecutor(self._target.remote_host)

        for source_device_id, target_device in self._target.device_mapping.items(
        ):
            source_device = self._source.remote_host.system_info[
                'block_devices'][source_device_id]

            if executable_for_disks and (include_swap or not include_swap
                                         and source_device['fs'] != 'swap'):
                executable_for_disks(
                    remote_executor,
                    (source_device_id, source_device),
                    (target_device['id'], target_device),
                )

            if executable_for_partitions:
                for source_partition_id, target_partition in target_device[
                        'children'].items():
                    source_partition = source_device['children'][
                        source_partition_id]
                    if (include_swap or not include_swap
                            and source_partition['fs'] != 'swap'):
                        executable_for_partitions(
                            remote_executor,
                            (source_device_id, source_device),
                            (target_device['id'], target_device),
                            (source_partition_id, source_partition),
                            (target_partition['id'], target_partition),
                        )

        return remote_executor
Esempio n. 8
0
class RemoteScriptExecutor():
    """
    takes care of executing a given python script on a remote host and injecting environment variables
    """
    REMOTE_SCRIPT_BASE_TEMPLATE = ('CONTEXT = {env_string}\n{script_string}')
    PYTHON_SCRIPT_EXECUTION_COMMAND = RemoteHostCommand(
        '{SUDO_PREFIX}python -c "import base64;exec(base64.b64decode({ENCODED_SCRIPT}))"'
    )

    def __init__(self, remote_host):
        """
        
        :param remote_host: the remote host to execute on
        :type remote_host: remote_host.public.RemoteHost
        """
        self.remote_executor = RemoteHostExecutor(remote_host)

    def execute(self, script, env=None, sudo=False):
        """
        executes the given script on the remote host and injects the env dict as a CONTEXT dict into the script
        
        :param script: the script to execute
        :type script: str
        :param env: the env to inject into the script
        :type env: dict
        :param sudo: whether the script should be executed as sudo or not
        :type sudo: bool
        :return: the stdout of the script execution
        :rtype: str
        """
        return self.remote_executor.execute(
            self._render_script_execution_command(script, env, sudo))

    def _render_script_execution_command(self, script, env, sudo):
        return self.PYTHON_SCRIPT_EXECUTION_COMMAND.render(
            sudo_prefix='sudo ' if sudo else '',
            encoded_script=self._encode_script(
                self.REMOTE_SCRIPT_BASE_TEMPLATE.format(
                    env_string=self._render_env(env),
                    script_string=script,
                )),
        )

    def _render_env(self, env):
        return str(env if env else {})

    def _encode_script(self, rendered_script):
        return base64.b64encode(rendered_script.encode())
Esempio n. 9
0
class CreatePartitionsCommand(DeviceModifyingCommand):
    """
    takes care of creating the partitions on the target system
    """
    class CanNotCreatePartitionException(
            DeviceModifyingCommand.CommandExecutionException):
        """
        is called if a partition can not be created, for whatever reason
        """
        COMMAND_DOES = 'create the partitions'

    ERROR_REPORT_EXCEPTION_CLASS = CanNotCreatePartitionException

    READ_PARTITION_TABLE_COMMAND = RemoteHostCommand('sudo sfdisk -d {DEVICE}')
    WRITE_PARTITION_TABLE_COMMAND = RemoteHostCommand(
        'echo "{PARTITION_TABLE}" | sudo sfdisk {DEVICE}')

    def _execute(self):
        self.source_remote_executor = RemoteHostExecutor(
            self._source.remote_host)
        self._execute_on_every_device(self._replicate_partition_table,
                                      None,
                                      include_swap=True)
        self.source_remote_executor.close()
        self.source_remote_executor = None

    @DeviceModifyingCommand._collect_errors
    def _replicate_partition_table(self, remote_executor, source_device,
                                   target_device):
        """
        replicates the partition table of the source device and applies it to the target device

        :param remote_executor: remote executor to use for execution
        :type remote_executor: RemoteHostExecutor 
        :param source_device: the source device
        :type source_device: (str, dict)
        :param target_device: the target device
        :type target_device: (str, dict)
        """
        partition_table = self._read_partition_table(
            self.source_remote_executor, source_device[0])

        if partition_table:
            self._write_partition_table(remote_executor, target_device[0],
                                        partition_table)
        else:
            self.logger.debug(
                'no valid partition table found for {source_device}'.format(
                    source_device=source_device))

    def _write_partition_table(self, remote_executor, target_device_id,
                               partition_table):
        remote_executor.execute(
            self.WRITE_PARTITION_TABLE_COMMAND.render(
                partition_table=self._make_string_echo_safe(partition_table),
                device='/dev/{device_id}'.format(device_id=target_device_id)))

    def _read_partition_table(self, source_remote_executor, source_device_id):
        try:
            return source_remote_executor.execute(
                self.READ_PARTITION_TABLE_COMMAND.render(
                    device='/dev/{device_id}'.format(
                        device_id=source_device_id)))
        except RemoteHostExecutor.ExecutionException:
            return ''

    def _make_string_echo_safe(self, string):
        return string.replace('"', '\\"')
Esempio n. 10
0
 def _init_test_data(self, **kwargs):
     self.remote_executor = RemoteHostExecutor(
         RemoteHost.objects.create(address='ubuntu16'))
     TestAsset.REMOTE_HOST_MOCKS['ubuntu16'].add_command(
         'sudo cat /etc/testfile.txt', self.TEST_FILE_CONTENT)
Esempio n. 11
0
 def _init_operator_class(self, operator_class):
     return operator_class(RemoteHostExecutor(self.remote_host))
Esempio n. 12
0
class SyncCommand(DeviceModifyingCommand):
    """
    does the actual sync and makes sure, that temp mounts are created and used, to avoid problems introduced by 
    overlapping mountpoints.
    """
    class SyncingException(DeviceModifyingCommand.CommandExecutionException):
        """
        raised if an error occurs during the sync
        """
        COMMAND_DOES = 'do the sync'

    ERROR_REPORT_EXCEPTION_CLASS = SyncingException
    ACCEPTED_EXIT_CODES = (24,)

    def _execute(self):
        self.source_remote_executor = RemoteHostExecutor(self._source.remote_host)
        self._execute_on_every_device(self._sync_disk, self._sync_partition)
        self.source_remote_executor.close()
        self.source_remote_executor = None

        return Commander.Signal.SLEEP

    def _sync_disk(self, remote_executor, source_device, target_device):
        self._sync_device(self.source_remote_executor, source_device[1]['mountpoint'], target_device[1]['mountpoint'])

    def _sync_partition(
        self, remote_executor, source_device, target_device, source_partition_device, target_partition_device
    ):
        self._sync_device(
            self.source_remote_executor,
            source_partition_device[1]['mountpoint'],
            target_partition_device[1]['mountpoint'],
        )

    @DeviceModifyingCommand._collect_errors
    def _sync_device(self, remote_executor, source_directory, target_directory):
        if source_directory:
            remote_executor.execute(
                RemoteHostCommand(self._target.blueprint['commands']['sync']).render(
                    source_dir=self._create_temp_bind_mount(remote_executor, source_directory),
                    target_dir='{user}{remote_host_address}:{target_directory}'.format(
                        user=('{username}@'.format(username=self._target.remote_host.username))
                                if self._target.remote_host.username else '',
                        remote_host_address=self._target.remote_host.address,
                        target_directory=target_directory,
                    )
                ),
                accepted_exit_codes=self.ACCEPTED_EXIT_CODES
            )

    def _create_temp_bind_mount(self, remote_executor, source_directory):
        temp_mountpoint = MountpointMapper.map_mountpoint('/tmp', source_directory)

        remote_executor.execute(
            DefaultRemoteHostCommand.MAKE_DIRECTORY.render(directory=temp_mountpoint)
        )

        try:
            remote_executor.execute(DefaultRemoteHostCommand.CHECK_MOUNTPOINT.render(directory=temp_mountpoint))
        except RemoteHostExecutor.ExecutionException:
            remote_executor.execute(
                DefaultRemoteHostCommand.BIND_MOUNT.render(
                    directory=source_directory,
                    mountpoint=temp_mountpoint
                )
            )

        return temp_mountpoint
Esempio n. 13
0
 def _execute(self):
     RemoteHostExecutor(self._target.remote_host).execute(
         'sudo shutdown -P now &', block_for_response=False)
     self._cloud_manager.stop_target(
         self._target.remote_host.cloud_metadata['id'])