def test_additional_fields(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'foo': self.ipmi_ipv4}) self.assertEqual((None, None, None), ir_utils.get_ipmi_address(node)) self.cfg.config(ipmi_address_fields=['foo', 'bar', 'baz']) self.assertEqual((self.ipmi_ipv4, self.ipmi_ipv4, None), ir_utils.get_ipmi_address(node))
def test_additional_fields(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'foo': '192.168.1.1'}) self.assertIsNone(ir_utils.get_ipmi_address(node)) CONF.set_override('ipmi_address_fields', ['foo', 'bar', 'baz']) ip = ir_utils.get_ipmi_address(node) self.assertEqual(ip, '192.168.1.1')
def test_additional_fields(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'foo': '192.168.1.1'}) self.assertIsNone(ir_utils.get_ipmi_address(node)) self.cfg.config(ipmi_address_fields=['foo', 'bar', 'baz']) ip = ir_utils.get_ipmi_address(node) self.assertEqual('192.168.1.1', ip)
def test_additional_fields(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'foo': '192.168.1.1'}) self.assertIsNone(ir_utils.get_ipmi_address(node)) CONF.set_override('ipmi_address_fields', ['foo', 'bar', 'baz']) ip = ir_utils.get_ipmi_address(node) self.assertEqual(ip, '192.168.1.1')
def test_additional_fields(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'foo': '192.168.1.1'}) self.assertIsNone(ir_utils.get_ipmi_address(node)) self.cfg.config(ipmi_address_fields=['foo', 'bar', 'baz']) ip = ir_utils.get_ipmi_address(node) self.assertEqual('192.168.1.1', ip)
def test_additional_fields(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'foo': self.ipmi_ipv4}) self.assertEqual((None, None, None), ir_utils.get_ipmi_address(node)) self.cfg.config(ipmi_address_fields=['foo', 'bar', 'baz']) self.assertEqual((self.ipmi_ipv4, self.ipmi_ipv4, None), ir_utils.get_ipmi_address(node))
def _check_existing_nodes(introspection_data, node_driver_info, ironic): macs = utils.get_valid_macs(introspection_data) if macs: # verify existing ports for mac in macs: ports = ironic.port.list(address=mac) if not ports: continue raise utils.Error( _('Port %(mac)s already exists, uuid: %(uuid)s') % {'mac': mac, 'uuid': ports[0].uuid}, data=introspection_data) else: LOG.warning('No suitable interfaces found for discovered node. ' 'Check that validate_interfaces hook is listed in ' '[processing]default_processing_hooks config option') # verify existing node with discovered ipmi address ipmi_address = node_driver_info.get('ipmi_address') if ipmi_address: # FIXME(aarefiev): it's not effective to fetch all nodes, and may # impact on performance on big clusters nodes = ironic.node.list(fields=('uuid', 'driver_info'), limit=0) for node in nodes: bmc_address, bmc_ipv4, bmc_ipv6 = ir_utils.get_ipmi_address(node) if ipmi_address in (bmc_ipv4, bmc_ipv6): raise utils.Error( _('Node %(uuid)s already has BMC address ' '%(ipmi_address)s, not enrolling') % {'ipmi_address': ipmi_address, 'uuid': node.uuid}, data=introspection_data)
def _finish_set_ipmi_credentials(ironic, node, node_info, introspection_data, new_username, new_password): patch = [{'op': 'add', 'path': '/driver_info/ipmi_username', 'value': new_username}, {'op': 'add', 'path': '/driver_info/ipmi_password', 'value': new_password}] if (not ir_utils.get_ipmi_address(node) and introspection_data.get('ipmi_address')): patch.append({'op': 'add', 'path': '/driver_info/ipmi_address', 'value': introspection_data['ipmi_address']}) node_info.patch(patch) for attempt in range(_CREDENTIALS_WAIT_RETRIES): try: # We use this call because it requires valid credentials. # We don't care about boot device, obviously. ironic.node.get_boot_device(node_info.uuid) except Exception as exc: LOG.info(_LI('Waiting for credentials update, attempt %(attempt)d ' 'current error is %(exc)s') % {'attempt': attempt, 'exc': exc}, node_info=node_info, data=introspection_data) eventlet.greenthread.sleep(_CREDENTIALS_WAIT_PERIOD) else: _finish(ironic, node_info, introspection_data) return msg = (_('Failed to validate updated IPMI credentials for node ' '%s, node might require maintenance') % node_info.uuid) node_info.finished(error=msg) raise utils.Error(msg, node_info=node_info, data=introspection_data)
def test_good_hostname_resolves(self, mock_socket): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': 'www.example.com'}) mock_socket.return_value = '192.168.1.1' ip = ir_utils.get_ipmi_address(node) mock_socket.assert_called_once_with('www.example.com') self.assertEqual(ip, '192.168.1.1')
def introspect(node_id, manage_boot=True, token=None): """Initiate hardware properties introspection for a given node. :param node_id: node UUID or name :param manage_boot: whether to manage boot for this node :param token: authentication token :raises: Error """ ironic = ir_utils.get_client(token) node = ir_utils.get_node(node_id, ironic=ironic) ir_utils.check_provision_state(node) if manage_boot: validation = ironic.node.validate(node.uuid) if not validation.power['result']: msg = _('Failed validation of power interface, reason: %s') raise utils.Error(msg % validation.power['reason'], node_info=node) bmc_address, bmc_ipv4, bmc_ipv6 = ir_utils.get_ipmi_address(node) lookup_attrs = list(filter(None, [bmc_ipv4, bmc_ipv6])) node_info = node_cache.start_introspection(node.uuid, bmc_address=lookup_attrs, manage_boot=manage_boot, ironic=ironic) utils.executor().submit(_background_introspect, node_info, ironic)
def _finish_set_ipmi_credentials(node_info, ironic, node, introspection_data, new_username, new_password): patch = [{'op': 'add', 'path': '/driver_info/ipmi_username', 'value': new_username}, {'op': 'add', 'path': '/driver_info/ipmi_password', 'value': new_password}] new_ipmi_address = utils.get_ipmi_address_from_data(introspection_data) if not ir_utils.get_ipmi_address(node) and new_ipmi_address: patch.append({'op': 'add', 'path': '/driver_info/ipmi_address', 'value': new_ipmi_address}) node_info.patch(patch) for attempt in range(_CREDENTIALS_WAIT_RETRIES): try: # We use this call because it requires valid credentials. # We don't care about boot device, obviously. ironic.node.get_boot_device(node_info.uuid) except Exception as exc: LOG.info(_LI('Waiting for credentials update, attempt %(attempt)d ' 'current error is %(exc)s'), {'attempt': attempt, 'exc': exc}, node_info=node_info, data=introspection_data) eventlet.greenthread.sleep(_CREDENTIALS_WAIT_PERIOD) else: _finish_common(node_info, ironic, introspection_data) return msg = (_('Failed to validate updated IPMI credentials for node ' '%s, node might require maintenance') % node_info.uuid) node_info.finished(error=msg) raise utils.Error(msg, node_info=node_info, data=introspection_data)
def introspect(node_id, manage_boot=True, token=None): """Initiate hardware properties introspection for a given node. :param node_id: node UUID or name :param manage_boot: whether to manage boot for this node :param token: authentication token :raises: Error """ ironic = ir_utils.get_client(token) node = ir_utils.get_node(node_id, ironic=ironic) ir_utils.check_provision_state(node) if manage_boot: validation = ironic.node.validate(node.uuid) if not validation.power['result']: msg = _('Failed validation of power interface, reason: %s') raise utils.Error(msg % validation.power['reason'], node_info=node) bmc_address = ir_utils.get_ipmi_address(node) node_info = node_cache.start_introspection(node.uuid, bmc_address=bmc_address, manage_boot=manage_boot, ironic=ironic) utils.executor().submit(_background_introspect, node_info, ironic)
def introspect(node_id, manage_boot=True, token=None): """Initiate hardware properties introspection for a given node. :param node_id: node UUID or name :param manage_boot: whether to manage boot for this node :param token: authentication token :raises: Error """ ironic = ir_utils.get_client(token) node = ir_utils.get_node(node_id, ironic=ironic) ir_utils.check_provision_state(node) if manage_boot: try: ironic.validate_node(node.id, required='power') except os_exc.ValidationException as exc: msg = _('Failed validation of power interface: %s') raise utils.Error(msg % exc, node_info=node) bmc_address, bmc_ipv4, bmc_ipv6 = ir_utils.get_ipmi_address(node) lookup_attrs = list(filter(None, [bmc_ipv4, bmc_ipv6])) node_info = node_cache.start_introspection(node.id, bmc_address=lookup_attrs, manage_boot=manage_boot, ironic=ironic) if manage_boot: try: utils.executor().submit(_do_introspect, node_info, ironic) except Exception as exc: msg = _('Failed to submit introspection job: %s') raise utils.Error(msg % exc, node_info=node) else: _do_introspect(node_info, ironic)
def introspect(node_id, token=None): """Initiate hardware properties introspection for a given node. :param node_id: node UUID or name :param token: authentication token :raises: Error """ ironic = ir_utils.get_client(token) node = ir_utils.get_node(node_id, ironic=ironic) ir_utils.check_provision_state(node) validation = ironic.node.validate(node.uuid) if not validation.power['result']: msg = _('Failed validation of power interface, reason: %s') raise utils.Error(msg % validation.power['reason'], node_info=node) bmc_address = ir_utils.get_ipmi_address(node) node_info = node_cache.start_introspection(node.uuid, bmc_address=bmc_address, ironic=ironic) def _handle_exceptions(fut): try: fut.result() except utils.Error as exc: # Logging has already happened in Error.__init__ node_info.finished(error=str(exc)) except Exception as exc: msg = _('Unexpected exception in background introspection thread') LOG.exception(msg, node_info=node_info) node_info.finished(error=msg) future = utils.executor().submit(_background_introspect, ironic, node_info) future.add_done_callback(_handle_exceptions)
def _check_existing_nodes(introspection_data, node_driver_info, ironic): macs = utils.get_valid_macs(introspection_data) if macs: # verify existing ports for mac in macs: ports = ironic.port.list(address=mac) if not ports: continue raise utils.Error( _('Port %(mac)s already exists, uuid: %(uuid)s') % { 'mac': mac, 'uuid': ports[0].uuid }, data=introspection_data) else: LOG.warning('No suitable interfaces found for discovered node. ' 'Check that validate_interfaces hook is listed in ' '[processing]default_processing_hooks config option') # verify existing node with discovered ipmi address ipmi_address = node_driver_info.get('ipmi_address') if ipmi_address: # FIXME(aarefiev): it's not effective to fetch all nodes, and may # impact on performance on big clusters nodes = ironic.node.list(fields=('uuid', 'driver_info'), limit=0) for node in nodes: bmc_address, bmc_ipv4, bmc_ipv6 = ir_utils.get_ipmi_address(node) if ipmi_address in (bmc_ipv4, bmc_ipv6): raise utils.Error(_('Node %(uuid)s already has BMC address ' '%(ipmi_address)s, not enrolling') % { 'ipmi_address': ipmi_address, 'uuid': node.uuid }, data=introspection_data)
def test_ipmi_bridging_enabled(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={ 'ipmi_address': 'www.example.com', 'ipmi_bridging': 'single' }) self.assertIsNone(ir_utils.get_ipmi_address(node))
def test_good_hostname_resolves(self, mock_socket): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': 'www.example.com'}) mock_socket.return_value = '192.168.1.1' ip = ir_utils.get_ipmi_address(node) mock_socket.assert_called_once_with('www.example.com') self.assertEqual(ip, '192.168.1.1')
def test_good_hostname_resolves(self, mock_socket): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': self.ipmi_address}) mock_socket.return_value = [ (socket.AF_INET, None, None, None, (self.ipmi_ipv4,)), (socket.AF_INET6, None, None, None, (self.ipmi_ipv6,))] self.assertEqual((self.ipmi_address, self.ipmi_ipv4, self.ipmi_ipv6), ir_utils.get_ipmi_address(node)) mock_socket.assert_called_once_with(self.ipmi_address, None, 0, 0, socket.SOL_TCP)
def test_redfish_bmc_address_ipv6(self, mock_socket): self.cfg.config(ipmi_address_fields=['redfish_address']) url = 'https://[{}]::443/path'.format(self.ipmi_ipv6) node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'redfish_address': url}) mock_socket.return_value = [(socket.AF_INET6, None, None, None, (self.ipmi_ipv6, ))] self.assertEqual((self.ipmi_ipv6, None, self.ipmi_ipv6), ir_utils.get_ipmi_address(node)) mock_socket.assert_called_once_with(self.ipmi_ipv6, None, 0, 0, 6)
def test_good_hostname_resolves(self, mock_socket): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': self.ipmi_address}) mock_socket.return_value = [ (socket.AF_INET, None, None, None, (self.ipmi_ipv4,)), (socket.AF_INET6, None, None, None, (self.ipmi_ipv6,))] self.assertEqual((self.ipmi_address, self.ipmi_ipv4, self.ipmi_ipv6), ir_utils.get_ipmi_address(node)) mock_socket.assert_called_once_with(self.ipmi_address, None, 0, 0, socket.SOL_TCP)
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 = ir_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 }) ir_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, reason: %s') raise utils.Error(msg % validation.power['reason'], node_info=node) bmc_address = ir_utils.get_ipmi_address(node) node_info = node_cache.add_node(node.uuid, bmc_address=bmc_address, ironic=ironic) node_info.set_option('new_ipmi_credentials', new_ipmi_credentials) def _handle_exceptions(fut): try: fut.result() except utils.Error as exc: # Logging has already happened in Error.__init__ node_info.finished(error=str(exc)) except Exception as exc: msg = _('Unexpected exception in background introspection thread') LOG.exception(msg, node_info=node_info) node_info.finished(error=msg) future = utils.executor().submit(_background_introspect, ironic, node_info) future.add_done_callback(_handle_exceptions)
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 = ir_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}) ir_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, reason: %s') raise utils.Error(msg % validation.power['reason'], node_info=node) bmc_address = ir_utils.get_ipmi_address(node) node_info = node_cache.add_node(node.uuid, bmc_address=bmc_address, ironic=ironic) node_info.set_option('new_ipmi_credentials', new_ipmi_credentials) def _handle_exceptions(fut): try: fut.result() except utils.Error as exc: # Logging has already happened in Error.__init__ node_info.finished(error=str(exc)) except Exception as exc: msg = _('Unexpected exception in background introspection thread') LOG.exception(msg, node_info=node_info) node_info.finished(error=msg) future = utils.executor().submit(_background_introspect, ironic, node_info) future.add_done_callback(_handle_exceptions)
def test_ipv4_in_resolves(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': self.ipmi_ipv4}) self.assertEqual((self.ipmi_ipv4, self.ipmi_ipv4, None), ir_utils.get_ipmi_address(node))
def test_loopback_address(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': '127.0.0.2'}) self.assertEqual((None, None, None), ir_utils.get_ipmi_address(node))
def test_ipmi_bridging_enabled(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': 'www.example.com', 'ipmi_bridging': 'single'}) self.assertEqual((None, None, None), ir_utils.get_ipmi_address(node))
def test_ipv4_in_resolves(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': '192.168.1.1'}) ip = ir_utils.get_ipmi_address(node) self.assertEqual(ip, '192.168.1.1')
def test_loopback_address(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': '127.0.0.2'}) ip = ir_utils.get_ipmi_address(node) self.assertIsNone(ip)
def test_loopback_address(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': '127.0.0.2'}) self.assertEqual((None, None, None), ir_utils.get_ipmi_address(node))
def test_ipv4_in_resolves(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': '192.168.1.1'}) ip = ir_utils.get_ipmi_address(node) self.assertEqual(ip, '192.168.1.1')
def test_ipv6_in_resolves(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': self.ipmi_ipv6}) self.assertEqual((self.ipmi_ipv6, None, self.ipmi_ipv6), ir_utils.get_ipmi_address(node))
def test_loopback_address(self): node = mock.Mock(spec=['driver_info', 'uuid'], driver_info={'ipmi_address': '127.0.0.2'}) ip = ir_utils.get_ipmi_address(node) self.assertIsNone(ip)