Esempio n. 1
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. 2
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