def _run_dog(self, command, subcommand, *params): cmd = ('env', 'LC_ALL=C', 'LANG=C', 'dog', command, subcommand, '-a', self.addr, '-p', self.port) + params try: return utils.execute(*cmd) except OSError as e: with excutils.save_and_reraise_exception(): if e.errno == errno.ENOENT: msg = _LE('Sheepdog is not installed. ' 'OSError: command is %s.') else: msg = _LE('OSError: command is %s.') LOG.error(msg, cmd) except processutils.ProcessExecutionError as e: _stderr = e.stderr if _stderr.startswith(self.DOG_RESP_CONNECTION_ERROR): reason = (_('Failed to connect to sheep daemon. ' 'addr: %(addr)s, port: %(port)s'), { 'addr': self.addr, 'port': self.port }) raise exception.SheepdogError(reason=reason) raise exception.SheepdogCmdError( cmd=e.cmd, exit_code=e.exit_code, stdout=e.stdout.replace('\n', '\\n'), stderr=e.stderr.replace('\n', '\\n'))
def backup_volume(self, context, backup, backup_service): """Create a new backup from an existing volume.""" src_volume = self.db.volume_get(context, backup.volume_id) temp_snapshot_name = 'tmp-snap-%s' % src_volume.name # NOTE(tishizaki): If previous backup_volume operation has failed, # a temporary snapshot for previous operation may exist. # So, the old snapshot must be deleted before backup_volume. # Sheepdog 0.9 or later 'delete_snapshot' operation # is done successfully, although target snapshot does not exist. # However, sheepdog 0.8 or before 'delete_snapshot' operation # is failed, and raise ProcessExecutionError when target snapshot # does not exist. try: self.client.delete_snapshot(src_volume.name, temp_snapshot_name) except (exception.SheepdogCmdError): pass try: self.client.create_snapshot(src_volume.name, temp_snapshot_name) except (exception.SheepdogCmdError, OSError): msg = (_('Failed to create a temporary snapshot for volume %s.') % src_volume.id) LOG.exception(msg) raise exception.SheepdogError(reason=msg) try: sheepdog_fd = SheepdogIOWrapper(self.addr, self.port, src_volume, temp_snapshot_name) backup_service.backup(backup, sheepdog_fd) finally: self.client.delete_snapshot(src_volume.name, temp_snapshot_name)
def delete_snapshot(self, vdiname, snapname): try: (_stdout, _stderr) = self._run_dog('vdi', 'delete', '-s', snapname, vdiname) if _stderr.rstrip().endswith(self.DOG_RESP_SNAPSHOT_NOT_FOUND): LOG.warning(_LW('Snapshot "%s" not found.'), snapname) elif _stderr.rstrip().endswith(self.DOG_RESP_VDI_NOT_FOUND): LOG.warning(_LW('Volume "%s" not found.'), vdiname) elif _stderr.startswith(self.DOG_RESP_CONNECTION_ERROR): # NOTE(tishizaki) # Dog command does not return error_code although # dog command cannot connect to sheep process. # That is a Sheepdog's bug. # To avoid a Sheepdog's bug, now we need to check stderr. # If Sheepdog has been fixed, this check logic is needed # by old Sheepdog users. reason = (_('Failed to connect to sheep daemon. ' 'addr: %(addr)s, port: %(port)s'), { 'addr': self.addr, 'port': self.port }) raise exception.SheepdogError(reason=reason) except exception.SheepdogCmdError as e: cmd = e.kwargs['cmd'] _stderr = e.kwargs['stderr'] with excutils.save_and_reraise_exception(): LOG.error(_LE('Failed to delete snapshot. (command: %s)'), cmd)
def check_cluster_status(self): try: (_stdout, _stderr) = self._run_dog('cluster', 'info') except exception.SheepdogCmdError as e: cmd = e.kwargs['cmd'] _stderr = e.kwargs['stderr'] with excutils.save_and_reraise_exception(): if _stderr.startswith(self.DOG_RESP_CONNECTION_ERROR): msg = _LE('Failed to connect to sheep daemon. ' 'addr: %(addr)s, port: %(port)s') LOG.error(msg, {'addr': self.addr, 'port': self.port}) else: LOG.error(_LE('Failed to check cluster status.' '(command: %s)'), cmd) if _stdout.startswith(self.DOG_RESP_CLUSTER_RUNNING): LOG.debug('Sheepdog cluster is running.') return reason = _('Invalid sheepdog cluster status.') if _stdout.startswith(self.DOG_RESP_CLUSTER_NOT_FORMATTED): reason = _('Cluster is not formatted. ' 'You should probably perform "dog cluster format".') elif _stdout.startswith(self.DOG_RESP_CLUSTER_WAITING): reason = _('Waiting for all nodes to join cluster. ' 'Ensure all sheep daemons are running.') raise exception.SheepdogError(reason=reason)
def _run_dog(self, command, subcommand, *params): """Execute dog command wrapper.""" addr = self.get_addr() cmd = ('env', 'LC_ALL=C', 'LANG=C', 'dog', command, subcommand, '-a', addr, '-p', self.port) + params try: (_stdout, _stderr) = utils.execute(*cmd) if _stderr.startswith(self.DOG_RESP_CONNECTION_ERROR): # NOTE(tishizaki) # Dog command does not return error_code although # dog command cannot connect to sheep process. # That is a Sheepdog's bug. # To avoid a Sheepdog's bug, now we need to check stderr. # If Sheepdog has been fixed, this check logic is needed # by old Sheepdog users. reason = (_('Failed to connect to sheep daemon. ' 'addr: %(addr)s, port: %(port)s'), { 'addr': addr, 'port': self.port }) raise exception.SheepdogError(reason=reason) return (_stdout, _stderr) except OSError as e: with excutils.save_and_reraise_exception(): if e.errno == errno.ENOENT: msg = _LE('Sheepdog is not installed. ' 'OSError: command is %s.') else: msg = _LE('OSError: command is %s.') LOG.error(msg, cmd) except processutils.ProcessExecutionError as e: _stderr = e.stderr if _stderr.startswith(self.DOG_RESP_CONNECTION_ERROR): reason = (_('Failed to connect to sheep daemon. ' 'addr: %(addr)s, port: %(port)s'), { 'addr': addr, 'port': self.port }) raise exception.SheepdogError(reason=reason) raise exception.SheepdogCmdError( cmd=e.cmd, exit_code=e.exit_code, stdout=e.stdout.replace('\n', '\\n'), stderr=e.stderr.replace('\n', '\\n'))
def check_cluster_status(self): try: (_stdout, _stderr) = self._run_dog('cluster', 'info') except exception.SheepdogCmdError as e: cmd = e.kwargs['cmd'] with excutils.save_and_reraise_exception(): LOG.error('Failed to check cluster status.' '(command: %s)', cmd) if _stdout.startswith(self.DOG_RESP_CLUSTER_RUNNING): LOG.debug('Sheepdog cluster is running.') return reason = _('Invalid sheepdog cluster status.') if _stdout.startswith(self.DOG_RESP_CLUSTER_NOT_FORMATTED): reason = _('Cluster is not formatted. ' 'You should probably perform "dog cluster format".') elif _stdout.startswith(self.DOG_RESP_CLUSTER_WAITING): reason = _('Waiting for all nodes to join cluster. ' 'Ensure all sheep daemons are running.') raise exception.SheepdogError(reason=reason)
def _run_qemu_img(self, command, *params): """Executes qemu-img command wrapper.""" addr = self.get_addr() cmd = ['env', 'LC_ALL=C', 'LANG=C', 'qemu-img', command] for param in params: if param.startswith(self.QEMU_SHEEPDOG_PREFIX): # replace 'sheepdog:vdiname[:snapshotname]' to # 'sheepdog:addr:port:vdiname[:snapshotname]' param = param.replace( self.QEMU_SHEEPDOG_PREFIX, '%(prefix)s%(addr)s:%(port)s:' % { 'prefix': self.QEMU_SHEEPDOG_PREFIX, 'addr': addr, 'port': self.port }, 1) cmd.append(param) try: return utils.execute(*cmd) except OSError as e: with excutils.save_and_reraise_exception(): if e.errno == errno.ENOENT: msg = ('Qemu-img is not installed. OSError: command is ' '%(cmd)s.') else: msg = 'OSError: command is %(cmd)s.' LOG.error(msg, {'cmd': tuple(cmd)}) except processutils.ProcessExecutionError as e: _stderr = e.stderr if self.QEMU_IMG_RESP_CONNECTION_ERROR in _stderr: reason = (_('Failed to connect to sheep daemon. ' 'addr: %(addr)s, port: %(port)s'), { 'addr': addr, 'port': self.port }) raise exception.SheepdogError(reason=reason) raise exception.SheepdogCmdError( cmd=e.cmd, exit_code=e.exit_code, stdout=e.stdout.replace('\n', '\\n'), stderr=e.stderr.replace('\n', '\\n'))