def test_pre_live_migration_setup_compute_node_fail(self): """Confirm operation setup_compute_network() fails. It retries and raise exception when timeout exceeded. """ i_ref = self._get_dummy_instance() c = context.get_admin_context() self._setup_other_managers() dbmock = self.mox.CreateMock(db) netmock = self.mox.CreateMock(self.network_manager) volmock = self.mox.CreateMock(self.volume_manager) drivermock = self.mox.CreateMock(self.compute_driver) dbmock.instance_get(c, i_ref['id']).AndReturn(i_ref) dbmock.instance_get_fixed_addresses(c, i_ref['id']).AndReturn('dummy') for i in range(len(i_ref['volumes'])): volmock.setup_compute_volume(c, i_ref['volumes'][i]['id']) for i in range(FLAGS.live_migration_retry_count): drivermock.plug_vifs(i_ref, []).\ AndRaise(exception.ProcessExecutionError()) self.compute.db = dbmock self.compute.network_manager = netmock self.compute.volume_manager = volmock self.compute.driver = drivermock self.mox.ReplayAll() self.assertRaises(exception.ProcessExecutionError, self.compute.pre_live_migration, c, i_ref['id'], time=FakeTime())
def ssh_execute(ssh, cmd, process_input=None, addl_env=None, check_exit_code=True): LOG.debug(_('Running cmd (SSH): %s'), ' '.join(cmd)) if addl_env: raise exception.Error(_('Environment not supported over SSH')) if process_input: # This is (probably) fixable if we need it... raise exception.Error(_('process_input not supported over SSH')) stdin_stream, stdout_stream, stderr_stream = ssh.exec_command(cmd) channel = stdout_stream.channel #stdin.write('process_input would go here') #stdin.flush() # NOTE(justinsb): This seems suspicious... # ...other SSH clients have buffering issues with this approach stdout = stdout_stream.read() stderr = stderr_stream.read() stdin_stream.close() exit_status = channel.recv_exit_status() # exit_status == -1 if no exit code was returned if exit_status != -1: LOG.debug(_('Result was %s') % exit_status) if check_exit_code and exit_status != 0: raise exception.ProcessExecutionError(exit_code=exit_status, stdout=stdout, stderr=stderr, cmd=' '.join(cmd)) return (stdout, stderr)
def ssh_command_as_root(ssh_connection, cmd, check_exit_code=True): """Method to execute remote command as root. :param connection: an active paramiko.SSHClient connection. :param command: string containing the command to run. :returns: Tuple -- a tuple of (stdout, stderr) :raises: nova.exception.ProcessExecutionError """ LOG.debug(_('Running cmd (SSH-as-root): %s') % cmd) chan = ssh_connection._transport.open_session() # This command is required to be executed # in order to become root. chan.exec_command('ioscli oem_setup_env') bufsize = -1 stdin = chan.makefile('wb', bufsize) stdout = chan.makefile('rb', bufsize) stderr = chan.makefile_stderr('rb', bufsize) # We run the command and then call 'exit' to exit from # super user environment. stdin.write('%s\n%s\n' % (cmd, 'exit')) stdin.flush() exit_status = chan.recv_exit_status() # Lets handle the error just like nova.utils.ssh_execute does. if exit_status != -1: LOG.debug(_('Result was %s') % exit_status) if check_exit_code and exit_status != 0: raise nova_exception.ProcessExecutionError(exit_code=exit_status, stdout=stdout, stderr=stderr, cmd=' '.join(cmd)) return (stdout, stderr)
def _xvp_encrypt(self, password, is_pool_password=False): """Call xvp to obfuscate passwords for config file. Args: - password: the password to encode, max 8 char for vm passwords, and 16 chars for pool passwords. passwords will be trimmed to max len before encoding. - is_pool_password: True if this this is the XenServer api password False if it's a VM console password (xvp uses different keys and max lengths for pool passwords) Note that xvp's obfuscation should not be considered 'real' encryption. It simply DES encrypts the passwords with static keys plainly viewable in the xvp source code. """ maxlen = 8 flag = '-e' if is_pool_password: maxlen = 16 flag = '-x' #xvp will blow up on passwords that are too long (mdragon) password = password[:maxlen] out, err = utils.execute('xvp', flag, process_input=password) if err: raise exception.ProcessExecutionError(_("Failed to run xvp.")) return out.strip()
def execute(*cmd, **kwargs): process_input = kwargs.pop('process_input', None) addl_env = kwargs.pop('addl_env', None) check_exit_code = kwargs.pop('check_exit_code', 0) delay_on_retry = kwargs.pop('delay_on_retry', True) attempts = kwargs.pop('attempts', 1) if len(kwargs): raise exception.Error(_('Got unknown keyword args ' 'to utils.execute: %r') % kwargs) cmd = map(str, cmd) while attempts > 0: attempts -= 1 try: LOG.debug(_('Running cmd (subprocess): %s'), ' '.join(cmd)) env = os.environ.copy() if addl_env: env.update(addl_env) _PIPE = subprocess.PIPE # pylint: disable=E1101 obj = subprocess.Popen(cmd, stdin=_PIPE, stdout=_PIPE, stderr=_PIPE, env=env) result = None if process_input is not None: result = obj.communicate(process_input) else: result = obj.communicate() obj.stdin.close() # pylint: disable=E1101 _returncode = obj.returncode # pylint: disable=E1101 if _returncode: LOG.debug(_('Result was %s') % _returncode) if type(check_exit_code) == types.IntType \ and _returncode != check_exit_code: (stdout, stderr) = result raise exception.ProcessExecutionError( exit_code=_returncode, stdout=stdout, stderr=stderr, cmd=' '.join(cmd)) return result except exception.ProcessExecutionError: if not attempts: raise else: LOG.debug(_('%r failed. Retrying.'), cmd) if delay_on_retry: greenthread.sleep(random.randint(20, 200) / 100.0) finally: # NOTE(termie): this appears to be necessary to let the subprocess # call clean something up in between calls, without # it two execute calls in a row hangs the second one greenthread.sleep(0)
def test_check_for_export_with_some_volume_missing(self): """Output a warning message when some volumes are not recognied by ietd.""" volume_id_list = self._attach_volume() tid = db.volume_get_iscsi_target_num(self.context, volume_id_list[0]) self.mox.StubOutWithMock(self.volume.driver.tgtadm, 'show_target') self.volume.driver.tgtadm.show_target(tid).AndRaise( exception.ProcessExecutionError()) self.mox.ReplayAll() self.assertRaises(exception.ProcessExecutionError, self.volume.check_for_export, self.context, self.instance_id) self.mox.UnsetStubs() self._detach_volume(volume_id_list)
def test_check_for_export_with_some_volume_missing(self): """Output a warning message when some volumes are not recognied by ietd.""" volume_id_list = self._attach_volume() # the first vblade process isn't running tid = db.volume_get_iscsi_target_num(self.context, volume_id_list[0]) self.mox.StubOutWithMock(self.volume.driver, '_execute') self.volume.driver._execute("sudo", "ietadm", "--op", "show", "--tid=%(tid)d" % locals()).AndRaise( exception.ProcessExecutionError()) self.mox.ReplayAll() self.assertRaises(exception.ProcessExecutionError, self.volume.check_for_export, self.context, self.instance_id) msg = _("Cannot confirm exported volume id:%s.") % volume_id_list[0] self.assertTrue(0 <= self.stream.getvalue().find(msg)) self.mox.UnsetStubs() self._detach_volume(volume_id_list)
def check_for_export(self, context, volume_id): """Make sure volume is exported.""" (shelf_id, blade_id) = self.db.volume_get_shelf_and_blade(context, volume_id) cmd = ('vblade-persist', 'ls', '--no-header') out, _err = self._execute(*cmd, run_as_root=True) exported = False for line in out.split('\n'): param = line.split(' ') if len(param) == 6 and param[0] == str(shelf_id) \ and param[1] == str(blade_id) and param[-1] == "run": exported = True break if not exported: # Instance will be terminated in this case. desc = _("Cannot confirm exported volume id:%(volume_id)s. " "vblade process for e%(shelf_id)s.%(blade_id)s " "isn't running.") % locals() raise exception.ProcessExecutionError(out, _err, cmd=cmd, description=desc)
def execute(*cmd, **kwargs): """ Helper method to execute command with optional retry. :cmd Passed to subprocess.Popen. :process_input Send to opened process. :check_exit_code Single bool, int, or list of allowed exit codes. Defaults to [0]. Raise exception.ProcessExecutionError unless program exits with one of these code. :delay_on_retry True | False. Defaults to True. If set to True, wait a short amount of time before retrying. :attempts How many times to retry cmd. :run_as_root True | False. Defaults to False. If set to True, the command is prefixed by the command specified in the root_helper FLAG. :raises exception.Error on receiving unknown arguments :raises exception.ProcessExecutionError :returns a tuple, (stdout, stderr) from the spawned process, or None if the command fails. """ process_input = kwargs.pop('process_input', None) check_exit_code = kwargs.pop('check_exit_code', [0]) ignore_exit_code = False if isinstance(check_exit_code, bool): ignore_exit_code = not check_exit_code check_exit_code = [0] elif isinstance(check_exit_code, int): check_exit_code = [check_exit_code] delay_on_retry = kwargs.pop('delay_on_retry', True) attempts = kwargs.pop('attempts', 1) run_as_root = kwargs.pop('run_as_root', False) shell = kwargs.pop('shell', False) if len(kwargs): raise exception.Error( _('Got unknown keyword args ' 'to utils.execute: %r') % kwargs) if run_as_root: cmd = shlex.split(FLAGS.root_helper) + list(cmd) cmd = map(str, cmd) while attempts > 0: attempts -= 1 try: LOG.debug(_('Running cmd (subprocess): %s'), ' '.join(cmd)) _PIPE = subprocess.PIPE # pylint: disable=E1101 obj = subprocess.Popen(cmd, stdin=_PIPE, stdout=_PIPE, stderr=_PIPE, close_fds=True, shell=shell) result = None if process_input is not None: result = obj.communicate(process_input) else: result = obj.communicate() obj.stdin.close() # pylint: disable=E1101 _returncode = obj.returncode # pylint: disable=E1101 if _returncode: LOG.debug(_('Result was %s') % _returncode) if not ignore_exit_code \ and _returncode not in check_exit_code: (stdout, stderr) = result raise exception.ProcessExecutionError( exit_code=_returncode, stdout=stdout, stderr=stderr, cmd=' '.join(cmd)) return result except exception.ProcessExecutionError: if not attempts: raise else: LOG.debug(_('%r failed. Retrying.'), cmd) if delay_on_retry: greenthread.sleep(random.randint(20, 200) / 100.0) finally: # NOTE(termie): this appears to be necessary to let the subprocess # call clean something up in between calls, without # it two execute calls in a row hangs the second one greenthread.sleep(0)
def execute(*cmd, **kwargs): """Helper method to execute command with optional retry. If you add a run_as_root=True command, don't forget to add the corresponding filter to etc/nova/rootwrap.d ! :param cmd: Passed to subprocess.Popen. :param process_input: Send to opened process. :param check_exit_code: Single bool, int, or list of allowed exit codes. Defaults to [0]. Raise exception.ProcessExecutionError unless program exits with one of these code. :param delay_on_retry: True | False. Defaults to True. If set to True, wait a short amount of time before retrying. :param attempts: How many times to retry cmd. :param run_as_root: True | False. Defaults to False. If set to True, the command is run with rootwrap. :raises exception.NovaException: on receiving unknown arguments :raises exception.ProcessExecutionError: :returns: a tuple, (stdout, stderr) from the spawned process, or None if the command fails. """ process_input = kwargs.pop('process_input', None) check_exit_code = kwargs.pop('check_exit_code', [0]) ignore_exit_code = False if isinstance(check_exit_code, bool): ignore_exit_code = not check_exit_code check_exit_code = [0] elif isinstance(check_exit_code, int): check_exit_code = [check_exit_code] delay_on_retry = kwargs.pop('delay_on_retry', True) attempts = kwargs.pop('attempts', 1) run_as_root = kwargs.pop('run_as_root', False) shell = kwargs.pop('shell', False) if len(kwargs): raise exception.NovaException( _('Got unknown keyword args ' 'to utils.execute: %r') % kwargs) if run_as_root and os.geteuid() != 0: cmd = ['sudo', 'nova-rootwrap', CONF.rootwrap_config] + list(cmd) cmd = map(str, cmd) while attempts > 0: attempts -= 1 try: LOG.debug(_('Running cmd (subprocess): %s'), ' '.join(cmd)) _PIPE = subprocess.PIPE # pylint: disable=E1101 if os.name == 'nt': preexec_fn = None close_fds = False else: preexec_fn = _subprocess_setup close_fds = True obj = subprocess.Popen(cmd, stdin=_PIPE, stdout=_PIPE, stderr=_PIPE, close_fds=close_fds, preexec_fn=preexec_fn, shell=shell) result = None if process_input is not None: result = obj.communicate(process_input) else: result = obj.communicate() obj.stdin.close() # pylint: disable=E1101 _returncode = obj.returncode # pylint: disable=E1101 LOG.debug(_('Result was %s') % _returncode) if not ignore_exit_code and _returncode not in check_exit_code: (stdout, stderr) = result raise exception.ProcessExecutionError(exit_code=_returncode, stdout=stdout, stderr=stderr, cmd=' '.join(cmd)) return result except exception.ProcessExecutionError: if not attempts: raise else: LOG.debug(_('%r failed. Retrying.'), cmd) if delay_on_retry: greenthread.sleep(random.randint(20, 200) / 100.0) finally: # NOTE(termie): this appears to be necessary to let the subprocess # call clean something up in between calls, without # it two execute calls in a row hangs the second one greenthread.sleep(0)
def fake_exc(*args): raise exception.ProcessExecutionError()