def test_extend_volume(self, mock_rescan, mock_active_vioses): self.vol_drv._set_udid("vstor_uuid") mock_vios = mock.Mock(uuid='fake_uuid') # Test single vios mock_active_vioses.return_value = [mock_vios] self.vol_drv.extend_volume() mock_rescan.assert_called_once_with(self.vol_drv.vios_uuids[0], "vstor_uuid", self.adpt) mock_rescan.side_effect = pvm_exc.JobRequestFailed( operation_name='RescanVirtualDisk', error='fake_err') self.assertRaises(p_exc.VolumeExtendFailed, self.vol_drv.extend_volume) mock_rescan.side_effect = pvm_exc.VstorNotFound(stor_udid='stor_udid', vios_uuid='uuid') self.assertRaises(p_exc.VolumeExtendFailed, self.vol_drv.extend_volume) # Test multiple vios mock_active_vioses.return_value = [mock_vios, mock_vios] mock_rescan.reset_mock() mock_rescan.side_effect = [ pvm_exc.JobRequestFailed(operation_name='RescanVirtualDisk', error='fake_err'), None ] self.assertRaises(p_exc.VolumeExtendFailed, self.vol_drv.extend_volume) self.assertEqual(2, mock_rescan.call_count) mock_rescan.reset_mock() mock_rescan.side_effect = [ None, pvm_exc.VstorNotFound(stor_udid='stor_udid', vios_uuid='uuid') ] self.vol_drv.extend_volume() self.assertEqual(2, mock_rescan.call_count) self.vol_drv._set_udid(None) self.assertRaises(nova_exc.InvalidBDM, self.vol_drv.extend_volume)
def run_job(self, uuid, job_parms=None, timeout=CONF.pypowervm_job_request_timeout, sensitive=False, synchronous=True): """Invokes and polls a job. Adds job parameters to the job element if specified and calls the create_job method. It then monitors the job for completion and sends a JobRequestFailed exception if it did not complete successfully. :param uuid: uuid of the target :param job_parms: list of JobParamters to add :param timeout: maximum number of seconds for job to complete :param sensitive: If True, mask the Job payload in the logs. :param synchronous: If True (the default), wait for the Job to complete or time out. If False, return as soon as the Job starts. Note that this may still involve polling (if the Job is waiting in queue to start), and may still time out (if the Job hasn't started within the requested timeout.) :raise JobRequestFailed: if the job did not complete successfully. :raise JobRequestTimedOut: if the job timed out. """ if job_parms: self.add_job_parameters_to_existing(*job_parms) try: self.entry = self.adapter.create_job( self.entry.element, self._get_val_str(_JOB_GROUP_NAME), uuid, sensitive=sensitive).entry except pvmex.Error as exc: LOG.exception(exc) raise pvmex.JobRequestFailed(operation_name=self.op, error=exc) timed_out = self._monitor_job(timeout=timeout, sensitive=sensitive, synchronous=synchronous) if timed_out: try: self.cancel_job() except pvmex.JobRequestFailed as e: LOG.warn(six.text_type(e)) exc = pvmex.JobRequestTimedOut(operation_name=self.op, seconds=timeout) LOG.error(exc.args[0]) raise exc if not synchronous: # _monitor_job spawned a subthread that will delete_job when done. return self.delete_job() if self.job_status != JobStatus.COMPLETED_OK: exc = pvmex.JobRequestFailed(operation_name=self.op, error=self.get_job_message('')) LOG.error(exc.args[0]) raise exc
def test_connect_volume_job_fail(self, mock_get_vm_id, mock_discover): mock_get_vm_id.return_value = '2' mock_discover.side_effect = pvm_exc.JobRequestFailed( operation_name='ISCSIDiscovery', error='fake_err') # Run the method self.assertRaises(p_exc.VolumeAttachFailed, self.multi_vol_drv.connect_volume, self.slot_mgr)
def run(self): self.job.poll_while_status([JobStatus.RUNNING], 0, self.sensitive) self.job.delete_job() # If the Job failed, we still want to log it. if self.job.job_status != JobStatus.COMPLETED_OK: exc = pvmex.JobRequestFailed(operation_name=self.job.op, error=self.job.get_job_message()) LOG.error(exc.args[0])
def test_extend_volume(self, mock_rescan, mock_get_mgmt_partition): # FileIO driver can only have 1 uuid in vol_drv.vios_uuids mock_vios = mock.Mock(uuid='uuid1') mock_get_mgmt_partition.return_value = mock_vios self.vol_drv.extend_volume() mock_rescan.assert_called_once_with(self.vol_drv.vios_uuids[0], "fake_path", adapter=self.adpt) mock_rescan.side_effect = pvm_exc.JobRequestFailed( operation_name='RescanVirtualDisk', error='fake_err') self.assertRaises(p_exc.VolumeExtendFailed, self.vol_drv.extend_volume) mock_rescan.side_effect = pvm_exc.VstorNotFound( stor_udid='stor_udid', vios_uuid='uuid') self.assertRaises(p_exc.VolumeExtendFailed, self.vol_drv.extend_volume)
def get_job_resp_exception_msg(self, default=''): """Gets the job message string from the ResponseException. :returns: String containing the job message or default (defaults to empty string) if not found """ job_message = self._get_val_str(_JOB_MESSAGE, default) if job_message: # See if there is a stack trace to log stack_trace = self._get_val_str(_JOB_STACKTRACE, default) if stack_trace: LOG.error(pvmex.JobRequestFailed(operation_name=self.op, error=stack_trace)) return job_message
def test_force_immed_no_retry(self, mock_vios, mock_run_job): """With force_immediate=NO_RETRY, errors don't retry.""" mock_vios.adapter = self.adpt mock_vios.rmc_state = pvm_bp.RMCState.ACTIVE for exc in (pexc.JobRequestFailed(error='e', operation_name='op'), pexc.JobRequestTimedOut(operation_name='op', seconds=60)): mock_run_job.side_effect = exc self.assertRaises(pexc.VMPowerOffFailure, power.power_off, mock_vios, 'huuid', force_immediate=power.Force.NO_RETRY) self.assertEqual(1, mock_run_job.call_count) mock_run_job.reset_mock()
def test_power_on_syson_vios(self, mock_vios, mock_job_p, mock_run_job): """Validates a power on job when system is already on.""" mock_vios.adapter = self.adpt mock_vios.rmc_state = pvm_bp.RMCState.ACTIVE for err_prefix in power._ALREADY_POWERED_ON_ERRS: mock_run_job.reset_mock() mock_run_job.side_effect = pexc.JobRequestFailed( error='PowerOn', operation_name=err_prefix) # Invoke the run the job, but succeed because it is already # powered on power._power_on_off(mock_vios, 'PowerOn', '1111') # This specific error should cause a retry. self.assertEqual(1, mock_run_job.call_count)
def test_power_off_job_failure(self, mock_lpar, mock_job_p, mock_run_job): """Validates a power off job request failure.""" mock_lpar.adapter = self.adpt mock_lpar.rmc_state = pvm_bp.RMCState.ACTIVE for rmc_err_prefix in power._OSSHUTDOWN_RMC_ERRS: mock_run_job.reset_mock() mock_run_job.side_effect = pexc.JobRequestFailed( error='PowerOff', operation_name=rmc_err_prefix) # Invoke the run, should power off graceful, fail, then force off # and fail again. self.assertRaises(pexc.VMPowerOffFailure, power._power_on_off, mock_lpar, 'PowerOff', '1111') # It should have been called three times: one for the os shutdown, # one for vsp normal power off, # and another for the immediate power off self.assertEqual(3, mock_run_job.call_count)
def efail(error='error'): """Returns a JobRequestFailed exception.""" return pexc.JobRequestFailed(operation_name='foo', error=error)
def test_get_iscsi_initiators(self, mock_iscsi_init, mock_active_vioses): # Set up mocks and clear out data that may have been set by other # tests iscsi._ISCSI_INITIATORS = dict() mock_iscsi_init.return_value = 'test_initiator' vios_ids = [ '1300C76F-9814-4A4D-B1F0-5B69352A7DEA', '7DBBE705-E4C4-4458-8223-3EBE07015CA9' ] vios0 = mock.Mock(uuid=vios_ids[0]) vios1 = mock.Mock(uuid=vios_ids[1]) mock_active_vioses.return_value = [vios0, vios1] expected_output = { '1300C76F-9814-4A4D-B1F0-5B69352A7DEA': 'test_initiator', '7DBBE705-E4C4-4458-8223-3EBE07015CA9': 'test_initiator' } self.assertEqual(expected_output, iscsi.get_iscsi_initiators(self.adpt, vios_ids)) # Make sure it gets set properly in the backend self.assertEqual(expected_output, iscsi._ISCSI_INITIATORS) self.assertEqual(mock_active_vioses.call_count, 0) self.assertEqual(mock_iscsi_init.call_count, 2) # Invoke again, make sure it doesn't call down to the mgmt part again mock_iscsi_init.reset_mock() self.assertEqual(expected_output, iscsi.get_iscsi_initiators(self.adpt, vios_ids)) self.assertEqual(mock_active_vioses.call_count, 0) self.assertEqual(mock_iscsi_init.call_count, 0) # Invoke iscsi.get_iscsi_initiators with vios_id=None iscsi._ISCSI_INITIATORS = dict() mock_iscsi_init.reset_mock() self.assertEqual(expected_output, iscsi.get_iscsi_initiators(self.adpt, None)) self.assertEqual(expected_output, iscsi._ISCSI_INITIATORS) self.assertEqual(mock_active_vioses.call_count, 1) self.assertEqual(mock_iscsi_init.call_count, 2) # Invoke again with vios_id=None to ensure get_active_vioses, # discover_iscsi_initiator is not called mock_iscsi_init.reset_mock() mock_active_vioses.reset_mock() self.assertEqual(expected_output, iscsi.get_iscsi_initiators(self.adpt, None)) self.assertEqual(mock_active_vioses.call_count, 0) self.assertEqual(mock_iscsi_init.call_count, 0) # Invoke iscsi.get_iscsi_initiators with discover_iscsi_initiator() # raises ISCSIDiscoveryFailed exception iscsi._ISCSI_INITIATORS = dict() mock_iscsi_init.reset_mock() mock_iscsi_init.side_effect = pvm_exc.ISCSIDiscoveryFailed( vios_uuid='fake_vios_uid', status="fake_status") self.assertEqual(dict(), iscsi.get_iscsi_initiators(self.adpt, vios_ids)) self.assertEqual(dict(), iscsi._ISCSI_INITIATORS) # Invoke iscsi.get_iscsi_initiators with discover_iscsi_initiator() # raises JobRequestFailed exception iscsi._ISCSI_INITIATORS = dict() mock_iscsi_init.reset_mock() mock_iscsi_init.side_effect = pvm_exc.JobRequestFailed( operation_name='fake_operation_name', error="fake_error") self.assertEqual(dict(), iscsi.get_iscsi_initiators(self.adpt, vios_ids)) self.assertEqual(dict(), iscsi._ISCSI_INITIATORS)
def test_discover_iscsi(self, mock_job_res, mock_job_p, mock_run_job, mock_job_w): mock_job_w.return_value = self.mock_job mock_host_ip = '10.0.0.1:3290' mock_user = '******' mock_pass = '******' mock_iqn = 'fake_iqn' mock_uuid = 'uuid' mock_iface_name = 'iface_name' args = ['VirtualIOServer', mock_uuid] kwargs = {'suffix_type': 'do', 'suffix_parm': 'ISCSIDiscovery'} mock_job_res.return_value = {'DEV_OUTPUT': '["fake_iqn devName udid"]', 'RETURN_CODE': '0'} device_name, udid = iscsi.discover_iscsi( self.adpt, mock_host_ip, mock_user, mock_pass, mock_iqn, mock_uuid, iface_name=mock_iface_name) self.adpt.read.assert_called_once_with(*args, **kwargs) self.assertEqual('devName', device_name) self.assertEqual('udid', udid) self.assertEqual(1, mock_run_job.call_count) mock_job_p.assert_has_calls([ mock.call('hostIP', mock_host_ip), mock.call('user', mock_user), mock.call('password', mock_pass), mock.call('targetIQN', mock_iqn), mock.call('ifaceName', mock_iface_name), mock.call('multipath', str(False))], any_order=True) self.assertEqual(6, mock_job_p.call_count) # Test for lunid mock_job_p.reset_mock() mock_lunid = 2 mock_job_res.return_value = {'DEV_OUTPUT': '["fake_iqn devName udid"]', 'RETURN_CODE': '15'} device_name, udid = iscsi.discover_iscsi( self.adpt, mock_host_ip, mock_user, mock_pass, mock_iqn, mock_uuid, iface_name=mock_iface_name, lunid=mock_lunid) self.assertEqual(7, mock_job_p.call_count) mock_job_p.assert_any_call('targetLUN', str(mock_lunid)) mock_job_res.return_value = {'DEV_OUTPUT': '["fake_iqn devName udid"]', 'RETURN_CODE': '8'} self.assertRaises(pexc.ISCSIDiscoveryFailed, iscsi.discover_iscsi, self.adpt, mock_host_ip, mock_user, mock_pass, mock_iqn, mock_uuid, iface_name=mock_iface_name) # Check named args mock_job_p.reset_mock() mock_arg = mock.MagicMock() mock_job_res.return_value = {'DEV_OUTPUT': '["fake_iqn devName udid"]', 'RETURN_CODE': '0'} device_name, udid = iscsi.discover_iscsi( self.adpt, mock_host_ip, mock_user, mock_pass, mock_iqn, mock_uuid, iface_name=mock_iface_name, lunid=mock_lunid, auth=mock_arg, discovery_auth=mock_arg, discovery_username=mock_arg, discovery_password=mock_arg, multipath=True) self.assertEqual('devName', device_name) self.assertEqual('udid', udid) # Check JobRequestFailed exception mock_run_job.side_effect = pexc.JobRequestFailed( operation_name='iscsi-discover', error='error') mock_job_res.return_value = {} self.assertRaises(pexc.JobRequestFailed, iscsi.discover_iscsi, self.adpt, mock_host_ip, mock_user, mock_pass, mock_iqn, mock_uuid, iface_name=mock_iface_name)
def test_power_off_timeout_retry(self, mock_lpar, mock_job_p, mock_run_job): """Validate that when first power off times out, re-run.""" mock_lpar.adapter = self.adpt mock_lpar.rmc_state = pvm_bp.RMCState.ACTIVE mock_run_job.side_effect = pexc.JobRequestTimedOut( operation_name='PowerOff', seconds=60) # Invoke the run, should power off graceful, fail, then force off # and fail again. self.assertRaises(pexc.VMPowerOffFailure, power._power_on_off, mock_lpar, 'PowerOff', '1111') # It should have been called twice, once for the elegant power # off, and another for the immediate power off self.assertEqual(2, mock_run_job.call_count) mock_job_p.assert_has_calls([ mock.call('operation', 'osshutdown'), mock.call('immediate', 'true'), mock.call('operation', 'shutdown'), mock.call('immediate', 'true') ]) # Try a timedout only for the 2nd and 3rd job mock_run_job.reset_mock() mock_job_p.reset_mock() rmc_error = power._OSSHUTDOWN_RMC_ERRS[0] mock_run_job.side_effect = [ pexc.JobRequestFailed(error='PowerOff', operation_name=rmc_error), pexc.JobRequestTimedOut(operation_name='PowerOff', seconds=60), pexc.JobRequestTimedOut(operation_name='PowerOff', seconds=60) ] self.assertRaises(pexc.VMPowerOffFailure, power._power_on_off, mock_lpar, 'PowerOff', '1111') # It should have been called three times, # once for the immediate os shutdown, once for vsp normal, # and another time for vsp hard self.assertEqual(3, mock_run_job.call_count) mock_job_p.assert_has_calls([ mock.call('operation', 'osshutdown'), mock.call('immediate', 'true'), mock.call('operation', 'shutdown'), mock.call('operation', 'shutdown'), mock.call('immediate', 'true') ]) # Try IBMi mock_run_job.reset_mock() mock_job_p.reset_mock() mock_lpar.rmc_state = pvm_bp.RMCState.INACTIVE mock_lpar.env = pvm_bp.LPARType.OS400 mock_lpar.ref_code = '00000000' mock_run_job.side_effect = pexc.JobRequestTimedOut( operation_name='PowerOff', seconds=60) self.assertRaises(pexc.VMPowerOffFailure, power._power_on_off, mock_lpar, 'PowerOff', '1111') # It should have been called four times, # once for the normal os shutdown, # once for the immediate os shutdown, once for vsp normal, # and another time for vsp hard self.assertEqual(4, mock_run_job.call_count) mock_job_p.assert_has_calls([ mock.call('operation', 'osshutdown'), mock.call('operation', 'osshutdown'), mock.call('immediate', 'true'), mock.call('operation', 'shutdown'), mock.call('operation', 'shutdown'), mock.call('immediate', 'true') ])