def test_upload_image_retries_on_signal_exception(self, mock_add_inst, mock_time_sleep): self.flags(num_retries=2, group='glance') params = self._get_params() params.update(self._get_upload_params()) error_details = ["", "task signaled", "", ""] error = XenAPI.Failure(details=error_details) # Note(johngarbutt) XenServer 6.1 and later has this error error_details_v61 = ["", "signal: SIGTERM", "", ""] error_v61 = self.session.XenAPI.Failure(details=error_details_v61) with mock.patch.object(self.session, 'call_plugin_serialized', side_effect=[error, error_v61, None]) as mock_call_plugin: self.store.upload_image(self.context, self.session, self.instance, 'fake_image_uuid', ['fake_vdi_uuid']) time_sleep_args = [mock.call(0.5), mock.call(1)] call_plugin_args = [ mock.call('glance.py', 'upload_vhd2', **params), mock.call('glance.py', 'upload_vhd2', **params), mock.call('glance.py', 'upload_vhd2', **params) ] add_inst_args = [ mock.call(self.context, self.instance, error, (XenAPI.Failure, error, mock.ANY)), mock.call(self.context, self.instance, error_v61, (XenAPI.Failure, error_v61, mock.ANY)) ] mock_time_sleep.assert_has_calls(time_sleep_args) mock_call_plugin.assert_has_calls(call_plugin_args) mock_add_inst.assert_has_calls(add_inst_args)
def test_session_on_slave_node_exc_more_than_one_host_ref( self, mock_gethostbyname, mock_login, mock_version_and_brand, mock_create_session, mock_platform_version, mock_verify_plugin_version): sess = mock.Mock() fake_records = {'fake_PIF_ref_a': {'host': 'fake_host_ref_a'}, 'fake_PIF_ref_b': {'host': 'fake_host_ref_b'}} sess.xenapi.PIF.get_all_records_where.return_value = fake_records sess.xenapi.host.get_uuid.return_value = 'fake_host_uuid' side_effects = [XenAPI.Failure(['HOST_IS_SLAVE', 'fake_master_url']), sess, sess, sess] mock_login.side_effect = side_effects concurrent = 2 originator = 'os-xenapi-nova' timeout = 10 mock_version_and_brand.return_value = ('6.5', 'XenServer') mock_platform_version.return_value = (2, 1, 0) fake_url = 'http://someserver' fake_host_name = 'someserver' fake_ip = '0.0.0.0' mock_gethostbyname.return_value = fake_ip self.assertRaises( XenAPI.Failure, session.XenAPISession, fake_url, 'username', 'password', originator=originator, concurrent=concurrent, timeout=timeout) mock_gethostbyname.assert_called_with(fake_host_name)
def test_upload_vhd_xenapi_failure_image_not_found(self): session = mock.Mock() num_retries = 'fake_num_retries' callback = 'fake_callback' retry_cb = 'fake_retry_cb' image_id = 'fake_image_id' sr_path = 'fake_sr_path' extra_headers = 'fake_extra_headers' vdi_uuids = 'fake_vdi_uuids' properties = {} args = {'image_id': image_id, 'sr_path': sr_path, 'extra_headers': extra_headers, 'vdi_uuids': vdi_uuids, 'properties': properties} session.call_plugin_serialized_with_retry.side_effect = XenAPI.Failure( ('XENAPI_PLUGIN_FAILURE', 'upload_vhd2', 'PluginError', 'ImageNotFound') ) self.assertRaises(exception.PluginImageNotFound, host_glance.upload_vhd, session, num_retries, callback, retry_cb, image_id, sr_path, extra_headers, vdi_uuids, properties) session.call_plugin_serialized_with_retry.assert_called_with( 'glance.py', 'upload_vhd2', num_retries, callback, retry_cb, **args )
def _login_with_password(self, user, pw, session): login_exception = XenAPI.Failure( _("Unable to log in to XenAPI " "(is the Dom0 disk full?)")) with timeout.Timeout(self.timeout, login_exception): session.login_with_password(user, pw, self.PLUGIN_REQUIRED_VERSION, self.originator)
def test_upload_image_retries_then_raises_exception( self, mock_add_inst, mock_time_sleep): self.flags(num_retries=2, group='glance') params = self._get_params() params.update(self._get_upload_params()) error_details = ["", "", "RetryableError", ""] error = XenAPI.Failure(details=error_details) with mock.patch.object(self.session, 'call_plugin_serialized', side_effect=error) as mock_call_plugin: self.assertRaises(exception.CouldNotUploadImage, self.store.upload_image, self.context, self.session, self.instance, 'fake_image_uuid', ['fake_vdi_uuid']) time_sleep_args = [mock.call(0.5), mock.call(1)] call_plugin_args = [ mock.call('glance.py', 'upload_vhd2', **params), mock.call('glance.py', 'upload_vhd2', **params), mock.call('glance.py', 'upload_vhd2', **params) ] add_inst_args = [ mock.call(self.context, self.instance, error, (XenAPI.Failure, error, mock.ANY)), mock.call(self.context, self.instance, error, (XenAPI.Failure, error, mock.ANY)), mock.call(self.context, self.instance, error, (XenAPI.Failure, error, mock.ANY)) ] mock_time_sleep.assert_has_calls(time_sleep_args) mock_call_plugin.assert_has_calls(call_plugin_args) mock_add_inst.assert_has_calls(add_inst_args)
def test_session_on_slave_node_using_host_ip(self, mock_gethostbyname, mock_login, mock_version_and_brand, mock_create_session, mock_platform_version, mock_verify_plugin_version): sess = mock.Mock() fake_records = {'fake_PIF_ref': {'host': 'fake_host_ref'}} sess.xenapi.PIF.get_all_records_where.return_value = fake_records sess.xenapi.host.get_uuid.return_value = 'fake_host_uuid' side_effects = [XenAPI.Failure(['HOST_IS_SLAVE', 'fake_master_url']), sess, sess, sess] mock_login.side_effect = side_effects concurrent = 2 originator = 'os-xenapi-nova' timeout = 10 mock_version_and_brand.return_value = ('6.5', 'XenServer') mock_platform_version.return_value = (2, 1, 0) fake_url = 'http://0.0.0.0' fake_ip = '0.0.0.0' xenapi_sess = session.XenAPISession(fake_url, 'username', 'password', originator=originator, concurrent=concurrent, timeout=timeout) self.assertTrue(xenapi_sess.is_slave) mock_gethostbyname.assert_called_with(fake_ip) self.assertEqual('fake_host_ref', xenapi_sess.host_ref) self.assertEqual('fake_host_uuid', xenapi_sess.host_uuid) self.assertEqual('http://fake_master_url', xenapi_sess.master_url) self.assertEqual(fake_url, xenapi_sess.url)
def _check_session(self, params): if (self._session is None or self._session not in _db_content['session']): raise XenAPI.Failure(['HANDLE_INVALID', 'session', self._session]) if len(params) == 0 or params[0] != self._session: LOG.debug('Raising NotImplemented') raise NotImplementedError('Call to XenAPI without using .xenapi')
def PBD_plug(self, _1, pbd_ref): rec = get_record('PBD', pbd_ref) if rec['currently_attached']: raise XenAPI.Failure(['DEVICE_ALREADY_ATTACHED', rec]) rec['currently_attached'] = True sr_ref = rec['SR'] _db_content['SR'][sr_ref]['PBDs'] = [pbd_ref]
def PBD_unplug(self, _1, pbd_ref): rec = get_record('PBD', pbd_ref) if not rec['currently_attached']: raise XenAPI.Failure(['DEVICE_ALREADY_DETACHED', rec]) rec['currently_attached'] = False sr_ref = rec['SR'] _db_content['SR'][sr_ref]['PBDs'].remove(pbd_ref)
def _get_host_ref(self, host_ip): with self._get_session() as session: if self.is_slave: rec_dict = session.xenapi.PIF.get_all_records_where( 'field "IP"="%s"' % host_ip) if not rec_dict: raise XenAPI.Failure( ("ERROR, couldn't find host ref with ip \ %(slave_ip)s ") % {'slave_ip': host_ip}) if len(rec_dict) > 1: raise XenAPI.Failure( ("ERROR, find more than one host ref with ip \ %(slave_ip)s ") % {'slave_ip': host_ip}) value = list(rec_dict.values())[0] return value['host'] else: return session.xenapi.session.get_this_host(session.handle)
def test_call_agent_fails_with_other_error(self, mock_uuid): session = mock.Mock() mock_method = mock.Mock().method() mock_method.__name__ = "mock_method" self.assertRaises(exception.AgentError, self._call_agent_setup, session, mock_uuid, mock_method, exception=XenAPI.Failure(["asdf"])) self._assert_agent_called(session, mock_uuid, mock_method)
def test_call_agent_fails_with_timeout(self, mock_uuid): session = mock.Mock() mock_method = mock.Mock().method() mock_method.__name__ = "mock_method" self.assertRaises(exception.AgentTimeout, self._call_agent_setup, session, mock_uuid, mock_method, exception=XenAPI.Failure(["TIMEOUT:fake"])) self._assert_agent_called(session, mock_uuid, mock_method)
def test_call_agent_fails_with_not_implemented(self, mock_uuid): session = mock.Mock() self.assertRaises(exception.AgentNotImplemented, self._call_agent_setup, session, mock_uuid, exception=XenAPI.Failure(["NOT IMPLEMENTED:"])) self._assert_agent_called(session, mock_uuid)
def VDI_add_to_other_config(self, _1, vdi_ref, key, value): db_ref = _db_content['VDI'][vdi_ref] if 'other_config' not in db_ref: db_ref['other_config'] = {} if key in db_ref['other_config']: raise XenAPI.Failure( ['MAP_DUPLICATE_KEY', 'VDI', 'other_config', vdi_ref, key]) db_ref['other_config'][key] = value
def _verify_plugin_version(self): requested_version = self.PLUGIN_REQUIRED_VERSION current_version = self.call_plugin_serialized( 'dom0_plugin_version.py', 'get_version') if not versionutils.is_compatible(requested_version, current_version): raise XenAPI.Failure( _("Plugin version mismatch (Expected %(exp)s, got %(got)s)") % {'exp': requested_version, 'got': current_version})
def _VM_reboot(self, session, vm_ref): db_ref = _db_content['VM'][vm_ref] if db_ref['power_state'] != 'Running': raise XenAPI.Failure([ 'VM_BAD_POWER_STATE', 'fake-opaque-ref', db_ref['power_state'].lower(), 'halted' ]) db_ref['power_state'] = 'Running' db_ref['domid'] = '%d' % (random.randrange(1, 1 << 16))
def VM_start(self, _1, ref, _2, _3): vm = fake.get_record('VM', ref) if vm['power_state'] != 'Halted': raise XenAPI.Failure(['VM_BAD_POWER_STATE', ref, 'Halted', vm['power_state']]) vm['power_state'] = 'Running' vm['is_a_template'] = False vm['is_control_domain'] = False vm['domid'] = random.randrange(1, 1 << 16) return vm
def VDI_introduce(self, _1, uuid, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11): valid_vdi = False refs = fake.get_all('VDI') for ref in refs: rec = fake.get_record('VDI', ref) if rec['uuid'] == uuid: valid_vdi = True if not valid_vdi: raise XenAPI.Failure([['INVALID_VDI', 'session', self._session]])
def _getter(self, name, params): self._check_session(params) (cls, func) = name.split('.') if func == 'get_all': self._check_arg_count(params, 1) return get_all(cls) if func == 'get_all_records': self._check_arg_count(params, 1) return get_all_records(cls) if func == 'get_all_records_where': self._check_arg_count(params, 2) return get_all_records_where(cls, params[1]) if func == 'get_record': self._check_arg_count(params, 2) return get_record(cls, params[1]) if func in ('get_by_name_label', 'get_by_uuid'): self._check_arg_count(params, 2) return_singleton = (func == 'get_by_uuid') return self._get_by_field(_db_content[cls], func[len('get_by_'):], params[1], return_singleton=return_singleton) if func == 'get_VIFs': self._check_arg_count(params, 2) # FIXME(mriedem): figure out how to use _get_by_field for VIFs, # or just stop relying on this fake DB and use mock return _db_content['VIF'].keys() if func == 'get_bridge': self._check_arg_count(params, 2) # FIXME(mriedem): figure out how to use _get_by_field for bridge, # or just stop relying on this fake DB and use mock return 'fake_bridge' if len(params) == 2: field = func[len('get_'):] ref = params[1] if (ref in _db_content[cls]): if (field in _db_content[cls][ref]): return _db_content[cls][ref][field] else: raise XenAPI.Failure(['HANDLE_INVALID', cls, ref]) LOG.debug('Raising NotImplemented') raise NotImplementedError( _('xenapi.fake does not have an implementation for %s or it has ' 'been called with the wrong number of arguments') % name)
def _get_by_field(self, recs, k, v, return_singleton): result = [] for ref, rec in recs.items(): if rec.get(k) == v: result.append(ref) if return_singleton: try: return result[0] except IndexError: raise XenAPI.Failure(['UUID_INVALID', v, result, recs, k]) return result
def test_retry_on_reboot(self, mock_wait): mock_session = mock.Mock() mock_session.VM.get_domid.return_value = "fake_dom_id" agent = self._create_agent(None, mock_session) mock_method = mock.Mock().method() mock_method.side_effect = [XenAPI.Failure(["REBOOT: fake"]), {"returncode": '0', "message": "done"}] result = agent._call_agent(mock_method) self.assertEqual("done", result) self.assertTrue(mock_session.VM.get_domid.called) self.assertEqual(2, mock_method.call_count) mock_wait.assert_called_once_with(mock_session, self.vm_ref, "fake_dom_id", mock_method)
def _fake_fetch_disk_image(context, session, instance, name_label, image, image_type): if raise_failure: raise XenAPI.Failure("Test Exception raised by " "fake fetch_image_glance_disk") elif image_type == vm_utils.ImageType.KERNEL: filename = "kernel" elif image_type == vm_utils.ImageType.RAMDISK: filename = "ramdisk" else: filename = "unknown" vdi_type = vm_utils.ImageType.to_string(image_type) return {vdi_type: dict(uuid=None, file=filename)}
def _destroy(self, name, params): self._check_session(params) self._check_arg_count(params, 2) table = name.split('.')[0] ref = params[1] if ref not in _db_content[table]: raise XenAPI.Failure(['HANDLE_INVALID', table, ref]) # Call destroy function (if exists) destroy_func = _destroy_functions.get('destroy_%s' % table.lower()) if destroy_func: destroy_func(ref) else: del _db_content[table][ref]
def _create_sr(table, obj): sr_type = obj[6] # Forces fake to support iscsi only if sr_type != 'iscsi' and sr_type != 'nfs': raise XenAPI.Failure(['SR_UNKNOWN_DRIVER', sr_type]) host_ref = list(_db_content['host'])[0] sr_ref = _create_object(table, obj[2]) if sr_type == 'iscsi': vdi_ref = create_vdi('', sr_ref) pbd_ref = create_pbd(host_ref, sr_ref, True) _db_content['SR'][sr_ref]['VDIs'] = [vdi_ref] _db_content['SR'][sr_ref]['PBDs'] = [pbd_ref] _db_content['VDI'][vdi_ref]['SR'] = sr_ref _db_content['PBD'][pbd_ref]['SR'] = sr_ref return sr_ref
def _unwrap_plugin_exceptions(self, func, *args, **kwargs): """Parse exception details.""" try: return func(*args, **kwargs) except XenAPI.Failure as exc: LOG.debug("Got exception: %s", exc) if (len(exc.details) == 4 and exc.details[0] == 'XENAPI_PLUGIN_EXCEPTION' and exc.details[2] == 'Failure'): params = None try: params = ast.literal_eval(exc.details[3]) except Exception: raise exc raise XenAPI.Failure(params) else: raise except xmlrpclib.ProtocolError as exc: LOG.debug("Got exception: %s", exc) raise
def test_upload_vhd_xenapi_failure_reraise(self): session = mock.Mock() num_retries = 'fake_num_retries' callback = 'fake_callback' retry_cb = 'fake_retry_cb' image_id = 'fake_image_id' sr_path = 'fake_sr_path' extra_headers = 'fake_extra_headers' vdi_uuids = 'fake_vdi_uuids' properties = {} args = {'image_id': image_id, 'sr_path': sr_path, 'extra_headers': extra_headers, 'vdi_uuids': vdi_uuids, 'properties': properties} session.call_plugin_serialized_with_retry.side_effect = XenAPI.Failure( ('untouch') ) self.assertRaises(XenAPI.Failure, host_glance.upload_vhd, session, num_retries, callback, retry_cb, image_id, sr_path, extra_headers, vdi_uuids, properties) session.call_plugin_serialized_with_retry.assert_called_with( 'glance.py', 'upload_vhd2', num_retries, callback, retry_cb, **args )
def _plugin_console_get_console_log(self, method, args): dom_id = args["dom_id"] if dom_id == 0: raise XenAPI.Failure('Guest does not have a console') return base64.b64encode( zlib.compress(("dom_id: %s" % dom_id).encode('utf-8')))
def get_record(table, ref): if ref in _db_content[table]: return _db_content[table].get(ref) else: raise XenAPI.Failure(['HANDLE_INVALID', table, ref])
def VBD_plug(self, _1, ref): rec = get_record('VBD', ref) if rec['currently_attached']: raise XenAPI.Failure(['DEVICE_ALREADY_ATTACHED', ref]) rec['currently_attached'] = True rec['device'] = 'fakedev'
def VBD_unplug(self, _1, ref): rec = get_record('VBD', ref) if not rec['currently_attached']: raise XenAPI.Failure(['DEVICE_ALREADY_DETACHED', ref]) rec['currently_attached'] = False rec['device'] = ''