def test_power_off_negative(self, mock_power_off): """Negative tests.""" # Raise the expected pypowervm exception mock_power_off.side_effect = pvm_exc.VMPowerOffFailure( reason='Something bad.', lpar_nm='TheLPAR') # We should get a valid Nova exception that the compute manager expects self.assertRaises(exception.InstancePowerOffFailure, vm.power_off, None, None, 'host_uuid', mock.Mock(state=pvm_bp.LPARState.RUNNING))
def test_power_off_negative(self, mock_wrap, mock_power_off): """Negative tests.""" instance = objects.Instance(**powervm.TEST_INSTANCE) mock_wrap.return_value = mock.Mock(state=pvm_bp.LPARState.RUNNING) # Raise the expected pypowervm exception mock_power_off.side_effect = pvm_exc.VMPowerOffFailure( reason='Something bad.', lpar_nm='TheLPAR') # We should get a valid Nova exception that the compute manager expects self.assertRaises(exception.InstancePowerOffFailure, vm.power_off, None, instance)
def test_power_off_negative(self, mock_wrap, mock_power_off): """Negative tests.""" mock_wrap.return_value = mock.Mock(state=pvm_bp.LPARState.RUNNING) # Raise the expected pypowervm exception mock_power_off.side_effect = pvm_exc.VMPowerOffFailure( reason='Something bad.', lpar_nm='TheLPAR') # We should get a valid Nova exception that the compute manager expects self.assertRaises(exception.InstancePowerOffFailure, vm.power_off, None, self.inst) # Non-pvm error raises directly mock_power_off.side_effect = ValueError() self.assertRaises(ValueError, vm.power_off, None, self.inst)
def stop(cls, part, opts=None, timeout=CONF.pypowervm_job_request_timeout, synchronous=True): """Power off a partition. :param part: LPAR/VIOS wrapper indicating the partition to power off. :param opts: An instance of power_opts.PowerOffOpts indicating the type of shutdown to perform, and any additional options. If not specified, PowerOffOpts.soft_detect is used, with no restart. :param timeout: value in seconds for specifying how long to wait for the Job to complete. :param synchronous: If True, this method will not return until the Job completes (whether success or failure) or times out. If False, this method will return as soon as the Job has started on the server (that is, achieved any state beyond NOT_ACTIVE). Note that timeout is still possible in this case. :raise VMPowerOffTimeout: If the Job timed out. :raise VMPowerOffFailure: If the Job failed for some reason other than that the partition was already powered off, and restart was not requested. :return: A PowerOp instance which can be invoked via the run method. :raise OSShutdownNoRMC: OP_PWROFF_OS was requested on a non-IBMi partition with no RMC connection. """ if opts is None: opts = popts.PowerOffOpts().soft_detect(part) if opts.is_os and not opts.can_os_shutdown(part): raise pexc.OSShutdownNoRMC(lpar_nm=part.name) try: cls._run(part, opts, timeout, synchronous=synchronous) except pexc.JobRequestTimedOut as error: LOG.exception(error) raise pexc.VMPowerOffTimeout(lpar_nm=part.name, timeout=timeout) except pexc.JobRequestFailed as error: emsg = six.text_type(error) # If already powered off and not a reboot, don't send exception if (any(err_prefix in emsg for err_prefix in _ALREADY_POWERED_OFF_ERRS) and not opts.is_restart): LOG.warning(_("Partition %s already powered off."), part.name) return LOG.exception(error) raise pexc.VMPowerOffFailure(lpar_nm=part.name, reason=emsg)
def _power_on_off(part, suffix, host_uuid, force_immediate=Force.ON_FAILURE, restart=False, timeout=CONF.pypowervm_job_request_timeout, add_parms=None, synchronous=True): """Internal function to power on or off an instance. :param part: The LPAR/VIOS wrapper of the instance to act on. :param suffix: power option - 'PowerOn' or 'PowerOff'. :param host_uuid: TEMPORARY - The host system UUID that the LPAR/VIOS resides on :param force_immediate: (For PowerOff suffix only) One of the Force enum values (defaulting to Force.ON_FAILURE), which behave as follows: - Force.TRUE: The force-immediate option is included on the first pass. - Force.NO_RETRY: The force-immediate option is not included. If the power-off fails or times out, VMPowerOffFailure is raised immediately. - Force.ON_FAILURE: The force-immediate option is not included on the first pass; but if the power-off fails (including timeout), it is retried with the force-immediate option added. :param restart: Boolean. Do a restart after power off (for PowerOff suffix only) :param timeout: Value in seconds for specifying how long to wait for the LPAR/VIOS to stop (for PowerOff suffix only) :param add_parms: dict of parameters to pass directly to the job template :param synchronous: If True (the default), this method will not return until the Job completes (whether success or failure) or times out. If False, this method will return as soon as the Job has started on the server (that is, achieved any state beyond NOT_ACTIVE). Note that timeout is still possible in this case. """ complete = False uuid = part.uuid adapter = part.adapter normal_vsp_power_off = False add_immediate = part.env != bp.LPARType.OS400 while not complete: resp = adapter.read(part.schema_type, uuid, suffix_type=c.SUFFIX_TYPE_DO, suffix_parm=suffix) job_wrapper = job.Job.wrap(resp.entry) job_parms = [] if suffix == _SUFFIX_PARM_POWER_OFF: operation = 'osshutdown' if force_immediate == Force.TRUE: operation = 'shutdown' add_immediate = True # Do normal vsp shutdown if flag on or # if RMC not active (for non-IBMi) elif (normal_vsp_power_off or (part.env != bp.LPARType.OS400 and part.rmc_state != bp.RMCState.ACTIVE)): operation = 'shutdown' add_immediate = False job_parms.append( job_wrapper.create_job_parameter('operation', operation)) if add_immediate: job_parms.append( job_wrapper.create_job_parameter('immediate', 'true')) if restart: job_parms.append( job_wrapper.create_job_parameter('restart', 'true')) # Add add_parms to the job if add_parms is not None: for kw in add_parms.keys(): # Skip any parameters already set. if kw not in ['operation', 'immediate', 'restart']: job_parms.append(job_wrapper.create_job_parameter( kw, str(add_parms[kw]))) try: job_wrapper.run_job(uuid, job_parms=job_parms, timeout=timeout, synchronous=synchronous) complete = True except pexc.JobRequestTimedOut as error: if suffix == _SUFFIX_PARM_POWER_OFF: if operation == 'osshutdown' and (force_immediate == Force.ON_FAILURE): # This has timed out, we loop again and attempt to # force immediate vsp. Unless IBMi, in which case we # will try an immediate osshutdown and then # a vsp normal before then jumping to immediate vsp. timeout = CONF.pypowervm_job_request_timeout if part.env == bp.LPARType.OS400: if not add_immediate: add_immediate = True else: normal_vsp_power_off = True else: force_immediate = Force.TRUE # normal vsp power off did not work, try hard vsp power off elif normal_vsp_power_off: timeout = CONF.pypowervm_job_request_timeout force_immediate = Force.TRUE normal_vsp_power_off = False else: LOG.exception(error) emsg = six.text_type(error) raise pexc.VMPowerOffFailure(reason=emsg, lpar_nm=part.name) else: # Power On timed out LOG.exception(error) emsg = six.text_type(error) raise pexc.VMPowerOnFailure(reason=emsg, lpar_nm=part.name) except pexc.JobRequestFailed as error: emsg = six.text_type(error) LOG.exception(_('Error: %s') % emsg) if suffix == _SUFFIX_PARM_POWER_OFF: # If already powered off and not a reboot, # don't send exception if (any(err_prefix in emsg for err_prefix in _ALREADY_POWERED_OFF_ERRS) and not restart): complete = True # If failed for other reasons, # retry with normal vsp power off except for IBM i # where we try immediate osshutdown first elif operation == 'osshutdown' and (force_immediate == Force.ON_FAILURE): timeout = CONF.pypowervm_job_request_timeout if (part.env == bp.LPARType.OS400 and not add_immediate): add_immediate = True else: force_immediate = Force.NO_RETRY normal_vsp_power_off = True # normal vsp power off did not work, try hard vsp power off elif normal_vsp_power_off: timeout = CONF.pypowervm_job_request_timeout force_immediate = Force.TRUE normal_vsp_power_off = False else: raise pexc.VMPowerOffFailure(reason=emsg, lpar_nm=part.name) else: # If already powered on, don't send exception if (any(err_prefix in emsg for err_prefix in _ALREADY_POWERED_ON_ERRS)): complete = True else: raise pexc.VMPowerOnFailure(reason=emsg, lpar_nm=part.name)
def _power_on_off(part, suffix, host_uuid, force_immediate=False, restart=False, timeout=CONF.pypowervm_job_request_timeout, add_parms=None, synchronous=True): """Internal function to power on or off an instance. :param part: The LPAR/VIOS wrapper of the instance to act on. :param suffix: power option - 'PowerOn' or 'PowerOff'. :param host_uuid: TEMPORARY - The host system UUID that the LPAR/VIOS resides on :param force_immediate: Boolean. Do immediate shutdown (for PowerOff suffix only) :param restart: Boolean. Do a restart after power off (for PowerOff suffix only) :param timeout: Value in seconds for specifying how long to wait for the LPAR/VIOS to stop (for PowerOff suffix only) :param add_parms: dict of parameters to pass directly to the job template :param synchronous: If True (the default), this method will not return until the Job completes (whether success or failure) or times out. If False, this method will return as soon as the Job has started on the server (that is, achieved any state beyond NOT_ACTIVE). Note that timeout is still possible in this case. """ complete = False uuid = part.uuid adapter = part.adapter normal_vsp_power_off = False add_immediate = part.env != bp.LPARType.OS400 try: while not complete: resp = adapter.read(part.schema_type, uuid, suffix_type=c.SUFFIX_TYPE_DO, suffix_parm=suffix) job_wrapper = job.Job.wrap(resp.entry) job_parms = [] if suffix == _SUFFIX_PARM_POWER_OFF: operation = 'osshutdown' if force_immediate: operation = 'shutdown' add_immediate = True # Do normal vsp shutdown if flag on or # if RMC not active (for non-IBMi) elif (normal_vsp_power_off or (part.env != bp.LPARType.OS400 and part.rmc_state != bp.RMCState.ACTIVE)): operation = 'shutdown' add_immediate = False job_parms.append( job_wrapper.create_job_parameter('operation', operation)) if add_immediate: job_parms.append( job_wrapper.create_job_parameter('immediate', 'true')) if restart: job_parms.append( job_wrapper.create_job_parameter('restart', 'true')) # Add add_parms to the job if add_parms is not None: for kw in add_parms.keys(): # Skip any parameters already set. if kw not in ['operation', 'immediate', 'restart']: job_parms.append( job_wrapper.create_job_parameter( kw, str(add_parms[kw]))) try: job_wrapper.run_job(uuid, job_parms=job_parms, timeout=timeout, synchronous=synchronous) complete = True except pexc.JobRequestTimedOut as error: if (suffix == _SUFFIX_PARM_POWER_OFF and operation == 'osshutdown'): # This has timed out, we loop again and attempt to # force immediate vsp now except for IBM i where we try # immediate osshutdown first timeout = CONF.pypowervm_job_request_timeout if (part.env == bp.LPARType.OS400 and not add_immediate): add_immediate = True else: force_immediate = True else: emsg = six.text_type(error) LOG.exception(_('Error: %s') % emsg) if suffix == _SUFFIX_PARM_POWER_OFF: raise pexc.VMPowerOffFailure(reason=emsg, lpar_nm=part.name) else: raise pexc.VMPowerOnFailure(reason=emsg, lpar_nm=part.name) except pexc.JobRequestFailed as error: emsg = six.text_type(error) LOG.exception(_('Error: %s') % emsg) if suffix == _SUFFIX_PARM_POWER_OFF: # If already powered off and not a reboot, # don't send exception if (any(err_prefix in emsg for err_prefix in _ALREADY_POWERED_OFF_ERRS) and not restart): complete = True # If failed for other reasons, # retry with normal vsp power off except for IBM i # where we try immediate osshutdown first elif operation == 'osshutdown': timeout = CONF.pypowervm_job_request_timeout if (part.env == bp.LPARType.OS400 and not add_immediate): add_immediate = True else: force_immediate = False normal_vsp_power_off = True # normal vsp power off did not work, try hard vsp power off elif normal_vsp_power_off: timeout = CONF.pypowervm_job_request_timeout force_immediate = True normal_vsp_power_off = False else: raise pexc.VMPowerOffFailure(reason=emsg, lpar_nm=part.name) else: # If already powered on, don't send exception if (any(err_prefix in emsg for err_prefix in _ALREADY_POWERED_ON_ERRS)): complete = True else: raise pexc.VMPowerOnFailure(reason=emsg, lpar_nm=part.name) # Invalidate the LPARentry in the adapter cache so the consumers get # the current LPAR state by forcing a subsequent read. Feeds must be # invalidated too, since the adapter will use them if an entry is not in # the cache. finally: try: adapter.invalidate_cache_elem(ms.System.schema_type, root_id=host_uuid, child_type=part.schema_type, child_id=uuid, invalidate_feeds=True) except Exception as e: LOG.exception( _('Error invalidating adapter cache for LPAR ' ' %(lpar_name) with UUID %(lpar_uuid)s: %(exc)s') % { 'lpar_name': part.name, 'lpar_uuid': uuid, 'exc': six.text_type(e) })