def test_get_client_without_auth_token(self, mock_client): utils.get_client(None) args = {'os_password': CONF.ironic.os_password, 'os_username': CONF.ironic.os_username, 'os_auth_url': CONF.ironic.os_auth_url, 'os_tenant_name': CONF.ironic.os_tenant_name, 'os_endpoint_type': CONF.ironic.os_endpoint_type, 'os_service_type': CONF.ironic.os_service_type, 'os_ironic_api_version': '1.6', 'max_retries': CONF.ironic.max_retries, 'retry_interval': CONF.ironic.retry_interval} mock_client.assert_called_once_with(1, **args)
def test_get_client_with_auth_token(self, mock_keystone_client, mock_client): fake_token = "token" fake_ironic_url = "http://127.0.0.1:6385" mock_keystone_client().service_catalog.url_for.return_value = fake_ironic_url utils.get_client(fake_token) args = { "os_auth_token": fake_token, "ironic_url": fake_ironic_url, "os_ironic_api_version": "1.6", "max_retries": CONF.ironic.max_retries, "retry_interval": CONF.ironic.retry_interval, } mock_client.assert_called_once_with(1, **args)
def test_get_client_with_auth_token(self, mock_keystone_client, mock_client): fake_token = 'token' fake_ironic_url = 'http://127.0.0.1:6385' mock_keystone_client().service_catalog.url_for.return_value = ( fake_ironic_url) utils.get_client(fake_token) args = {'os_auth_token': fake_token, 'ironic_url': fake_ironic_url, 'os_ironic_api_version': '1.6', 'max_retries': CONF.ironic.max_retries, 'retry_interval': CONF.ironic.retry_interval} mock_client.assert_called_once_with(1, **args)
def test_get_client_without_auth_token(self, mock_client): utils.get_client(None) args = { "os_password": CONF.ironic.os_password, "os_username": CONF.ironic.os_username, "os_auth_url": CONF.ironic.os_auth_url, "os_tenant_name": CONF.ironic.os_tenant_name, "os_endpoint_type": CONF.ironic.os_endpoint_type, "os_service_type": CONF.ironic.os_service_type, "os_ironic_api_version": "1.6", "max_retries": CONF.ironic.max_retries, "retry_interval": CONF.ironic.retry_interval, } mock_client.assert_called_once_with(1, **args)
def test_get_client_without_auth_token(self, mock_client): utils.get_client(None) args = { 'os_password': CONF.ironic.os_password, 'os_username': CONF.ironic.os_username, 'os_auth_url': CONF.ironic.os_auth_url, 'os_tenant_name': CONF.ironic.os_tenant_name, 'os_endpoint_type': CONF.ironic.os_endpoint_type, 'os_service_type': CONF.ironic.os_service_type, 'os_ironic_api_version': '1.6', 'max_retries': CONF.ironic.max_retries, 'retry_interval': CONF.ironic.retry_interval } mock_client.assert_called_once_with(1, **args)
def test_get_client_with_auth_token(self, mock_keystone_client, mock_client): fake_token = 'token' fake_ironic_url = 'http://127.0.0.1:6385' mock_keystone_client().service_catalog.url_for.return_value = ( fake_ironic_url) utils.get_client(fake_token) args = { 'os_auth_token': fake_token, 'ironic_url': fake_ironic_url, 'os_ironic_api_version': '1.6', 'max_retries': CONF.ironic.max_retries, 'retry_interval': CONF.ironic.retry_interval } mock_client.assert_called_once_with(1, **args)
def hook(introspection_data, **kwargs): ironic = utils.get_client() try: node = ironic.node.create(**{'driver': 'fake'}) except exceptions.HttpError as exc: raise utils.Error(_("Can not create node in ironic for unknown" "node: %s") % exc) return node_cache.add_node(node.uuid, ironic=ironic)
def update_filters(ironic=None): """Update firewall filter rules for introspection. Gives access to PXE boot port for any machine, except for those, whose MAC is registered in Ironic and is not on introspection right now. This function is called from both introspection initialization code and from periodic task. This function is supposed to be resistant to unexpected iptables state. ``init()`` function must be called once before any call to this function. This function is using ``eventlet`` semaphore to serialize access from different green threads. Does nothing, if firewall management is disabled in configuration. :param ironic: Ironic client instance, optional. """ if not CONF.firewall.manage_firewall: return assert INTERFACE is not None ironic = utils.get_client() if ironic is None else ironic with LOCK: macs_active = set(p.address for p in ironic.port.list(limit=0)) to_blacklist = macs_active - node_cache.active_macs() LOG.debug('Blacklisting active MAC\'s %s', to_blacklist) # Clean up a bit to account for possible troubles on previous run _clean_up(NEW_CHAIN) # Operate on temporary chain _iptables('-N', NEW_CHAIN) # - Blacklist active macs, so that nova can boot them for mac in to_blacklist: _iptables('-A', NEW_CHAIN, '-m', 'mac', '--mac-source', mac, '-j', 'DROP') # - Whitelist everything else _iptables('-A', NEW_CHAIN, '-j', 'ACCEPT') # Swap chains _iptables('-I', 'INPUT', '-i', INTERFACE, '-p', 'udp', '--dport', '67', '-j', NEW_CHAIN) _iptables('-D', 'INPUT', '-i', INTERFACE, '-p', 'udp', '--dport', '67', '-j', CHAIN, ignore=True) _iptables('-F', CHAIN, ignore=True) _iptables('-X', CHAIN, ignore=True) _iptables('-E', NEW_CHAIN, CHAIN)
def introspect(uuid, new_ipmi_credentials=None, token=None): """Initiate hardware properties introspection for a given node. :param uuid: node uuid :param new_ipmi_credentials: tuple (new username, new password) or None :param token: authentication token :raises: Error """ ironic = utils.get_client(token) try: node = ironic.node.get(uuid) except exceptions.NotFound: raise utils.Error(_("Cannot find node %s") % uuid, code=404) except exceptions.HttpError as exc: raise utils.Error( _("Cannot get node %(node)s: %(exc)s") % { 'node': uuid, 'exc': exc }) utils.check_provision_state(node, with_credentials=new_ipmi_credentials) if new_ipmi_credentials: new_ipmi_credentials = (_validate_ipmi_credentials( node, new_ipmi_credentials)) else: validation = ironic.node.validate(node.uuid) if not validation.power['result']: msg = _('Failed validation of power interface for node %(node)s, ' 'reason: %(reason)s') raise utils.Error(msg % { 'node': node.uuid, 'reason': validation.power['reason'] }) node_info = node_cache.add_node(node.uuid, bmc_address=utils.get_ipmi_address(node), ironic=ironic) node_info.set_option('new_ipmi_credentials', new_ipmi_credentials) def _handle_exceptions(): try: _background_introspect(ironic, node_info) except utils.Error as exc: node_info.finished(error=str(exc)) except Exception as exc: msg = _('Unexpected exception in background introspection thread') LOG.exception(msg) node_info.finished(error=msg) utils.spawn_n(_handle_exceptions)
def _process_node(node, introspection_data, node_info): # NOTE(dtantsur): repeat the check in case something changed utils.check_provision_state(node) node_info.create_ports(introspection_data.get('macs') or ()) _run_post_hooks(node_info, introspection_data) if CONF.processing.store_data == 'swift': swift_object_name = swift.store_introspection_data( introspection_data, node_info.uuid) LOG.info( _LI('Introspection data for node %(node)s was stored in ' 'Swift in object %(obj)s'), { 'node': node_info.uuid, 'obj': swift_object_name }) if CONF.processing.store_data_location: node_info.patch([{ 'op': 'add', 'path': '/extra/%s' % CONF.processing.store_data_location, 'value': swift_object_name }]) else: LOG.debug( 'Swift support is disabled, introspection data for node %s ' 'won\'t be stored', node_info.uuid) ironic = utils.get_client() firewall.update_filters(ironic) node_info.invalidate_cache() rules.apply(node_info, introspection_data) resp = {'uuid': node.uuid} if node_info.options.get('new_ipmi_credentials'): new_username, new_password = ( node_info.options.get('new_ipmi_credentials')) utils.spawn_n(_finish_set_ipmi_credentials, ironic, node, node_info, introspection_data, new_username, new_password) resp['ipmi_setup_credentials'] = True resp['ipmi_username'] = new_username resp['ipmi_password'] = new_password else: utils.spawn_n(_finish, ironic, node_info) return resp
def introspect(uuid, new_ipmi_credentials=None, token=None): """Initiate hardware properties introspection for a given node. :param uuid: node uuid :param new_ipmi_credentials: tuple (new username, new password) or None :param token: authentication token :raises: Error """ ironic = utils.get_client(token) try: node = ironic.node.get(uuid) except exceptions.NotFound: raise utils.Error(_("Cannot find node %s") % uuid, code=404) except exceptions.HttpError as exc: raise utils.Error(_("Cannot get node %(node)s: %(exc)s") % {'node': uuid, 'exc': exc}) utils.check_provision_state(node, with_credentials=new_ipmi_credentials) if new_ipmi_credentials: new_ipmi_credentials = ( _validate_ipmi_credentials(node, new_ipmi_credentials)) else: validation = ironic.node.validate(node.uuid) if not validation.power['result']: msg = _('Failed validation of power interface for node %(node)s, ' 'reason: %(reason)s') raise utils.Error(msg % {'node': node.uuid, 'reason': validation.power['reason']}) node_info = node_cache.add_node(node.uuid, bmc_address=utils.get_ipmi_address(node), ironic=ironic) node_info.set_option('new_ipmi_credentials', new_ipmi_credentials) def _handle_exceptions(): try: _background_introspect(ironic, node_info) except utils.Error as exc: node_info.finished(error=str(exc)) except Exception as exc: msg = _('Unexpected exception in background introspection thread') LOG.exception(msg) node_info.finished(error=msg) utils.spawn_n(_handle_exceptions)
def _process_node(node, introspection_data, node_info): # NOTE(dtantsur): repeat the check in case something changed utils.check_provision_state(node) node_info.create_ports(introspection_data.get('macs') or ()) _run_post_hooks(node_info, introspection_data) if CONF.processing.store_data == 'swift': swift_object_name = swift.store_introspection_data(introspection_data, node_info.uuid) LOG.info(_LI('Introspection data for node %(node)s was stored in ' 'Swift in object %(obj)s'), {'node': node_info.uuid, 'obj': swift_object_name}) if CONF.processing.store_data_location: node_info.patch([{'op': 'add', 'path': '/extra/%s' % CONF.processing.store_data_location, 'value': swift_object_name}]) else: LOG.debug('Swift support is disabled, introspection data for node %s ' 'won\'t be stored', node_info.uuid) ironic = utils.get_client() firewall.update_filters(ironic) node_info.invalidate_cache() rules.apply(node_info, introspection_data) resp = {'uuid': node.uuid} if node_info.options.get('new_ipmi_credentials'): new_username, new_password = ( node_info.options.get('new_ipmi_credentials')) utils.spawn_n(_finish_set_ipmi_credentials, ironic, node, node_info, introspection_data, new_username, new_password) resp['ipmi_setup_credentials'] = True resp['ipmi_username'] = new_username resp['ipmi_password'] = new_password else: utils.spawn_n(_finish, ironic, node_info) return resp
def sync_with_ironic(): ironic = utils.get_client() # TODO(yuikotakada): pagination ironic_nodes = ironic.node.list(limit=0) ironic_node_uuids = {node.uuid for node in ironic_nodes} node_cache.delete_nodes_not_in_list(ironic_node_uuids)
def ironic(self): """Ironic client instance.""" if self._ironic is None: self._ironic = utils.get_client() return self._ironic
def setUp(self): super(Base, self).setUp() rules.delete_all() self.cli = utils.get_client() self.cli.reset_mock() self.cli.node.get.return_value = self.node self.cli.node.update.return_value = self.node self.cli.node.list.return_value = [self.node] # https://github.com/openstack/ironic-inspector/blob/master/HTTP-API.rst # noqa self.data = { 'cpus': 4, 'cpu_arch': 'x86_64', 'memory_mb': 12288, 'local_gb': 464, 'interfaces': { 'eth1': {'mac': self.macs[0], 'ip': '1.2.1.2'}, 'eth2': {'mac': '12:12:21:12:21:12'}, 'eth3': {'mac': self.macs[1], 'ip': '1.2.1.1'}, }, 'boot_interface': '01-' + self.macs[0].replace(':', '-'), 'ipmi_address': self.bmc_address, 'inventory': { 'disks': [ {'name': '/dev/sda', 'model': 'Big Data Disk', 'size': 1000 * units.Gi}, {'name': '/dev/sdb', 'model': 'Small OS Disk', 'size': 20 * units.Gi}, ] }, 'root_disk': {'name': '/dev/sda', 'model': 'Big Data Disk', 'size': 1000 * units.Gi}, } self.data_old_ramdisk = { 'cpus': 4, 'cpu_arch': 'x86_64', 'memory_mb': 12288, 'local_gb': 464, 'interfaces': { 'eth1': {'mac': self.macs[0], 'ip': '1.2.1.2'}, 'eth2': {'mac': '12:12:21:12:21:12'}, 'eth3': {'mac': self.macs[1], 'ip': '1.2.1.1'}, }, 'boot_interface': '01-' + self.macs[0].replace(':', '-'), 'ipmi_address': self.bmc_address, } self.patch = [ {'op': 'add', 'path': '/properties/cpus', 'value': '4'}, {'path': '/properties/cpu_arch', 'value': 'x86_64', 'op': 'add'}, {'op': 'add', 'path': '/properties/memory_mb', 'value': '12288'}, {'path': '/properties/local_gb', 'value': '999', 'op': 'add'} ] self.patch_old_ramdisk = [ {'op': 'add', 'path': '/properties/cpus', 'value': '4'}, {'path': '/properties/cpu_arch', 'value': 'x86_64', 'op': 'add'}, {'op': 'add', 'path': '/properties/memory_mb', 'value': '12288'}, {'path': '/properties/local_gb', 'value': '464', 'op': 'add'} ] self.patch_root_hints = [ {'op': 'add', 'path': '/properties/cpus', 'value': '4'}, {'path': '/properties/cpu_arch', 'value': 'x86_64', 'op': 'add'}, {'op': 'add', 'path': '/properties/memory_mb', 'value': '12288'}, {'path': '/properties/local_gb', 'value': '19', 'op': 'add'} ] self.node.power_state = 'power off'