Beispiel #1
0
def create_ports_if_not_exist(task, macs):
    """Create ironic ports for the mac addresses.

    Creates ironic ports for the mac addresses returned with inspection
    or as requested by operator.

    :param task: A TaskManager instance.
    :param macs: A dictionary of port numbers to mac addresses
                 returned by node inspection.

    """
    node = task.node
    for port_num, mac in macs.items():
        # TODO(etingof): detect --pxe-enabled flag
        port_dict = {'address': mac, 'node_id': node.id}
        port = objects.Port(task.context, **port_dict)

        try:
            port.create()
            LOG.info(
                "Port %(port_num)s created for MAC address %(address)s "
                "for node %(node)s", {
                    'address': mac,
                    'node': node.uuid,
                    'port_num': port_num
                })
        except exception.MACAlreadyExists:
            LOG.warning(
                "Port %(port_num)s already exists for "
                "MAC address %(address)s for node "
                "%(node)s", {
                    'address': mac,
                    'node': node.uuid,
                    'port_num': port_num
                })
Beispiel #2
0
def _create_ports_if_not_exist(task, macs):
    """Create ironic ports for the mac addresses.

    Creates ironic ports for the mac addresses returned with inspection
    or as requested by operator.

    :param task: a TaskManager instance.
    :param macs: A dictionary of port numbers to mac addresses
                 returned by node inspection.

    """
    node = task.node
    for mac in macs.values():
        port_dict = {'address': mac, 'node_id': node.id}
        port = objects.Port(task.context, **port_dict)

        try:
            port.create()
            LOG.info(
                _LI("Port created for MAC address %(address)s for node "
                    "%(node)s"), {
                        'address': mac,
                        'node': node.uuid
                    })
        except exception.MACAlreadyExists:
            LOG.warning(
                _LW("Port already exists for MAC address %(address)s "
                    "for node %(node)s"), {
                        'address': mac,
                        'node': node.uuid
                    })
Beispiel #3
0
def create_ports_if_not_exist(task, macs, get_mac_address=lambda x: x[1]):
    """Create ironic ports from MAC addresses data dict.

    Creates ironic ports from MAC addresses data returned with inspection or
    as requested by operator. Helper argument to detect the MAC address
    ``get_mac_address`` defaults to 'value' part of MAC address dict key-value
    pair.

    :param task: A TaskManager instance.
    :param macs: A dictionary of MAC addresses returned by node inspection.
    :param get_mac_address: a function to get the MAC address from mac item.
        A mac item is the dict key-value pair of the previous ``macs``
        argument.
    """
    node = task.node
    for k_v_pair in macs.items():
        mac = get_mac_address(k_v_pair)
        port_dict = {'address': mac, 'node_id': node.id}
        port = objects.Port(task.context, **port_dict)

        try:
            port.create()
            LOG.info(
                "Port created for MAC address %(address)s for node "
                "%(node)s", {
                    'address': mac,
                    'node': node.uuid
                })
        except exception.MACAlreadyExists:
            LOG.warning(
                "Port already exists for MAC address %(address)s "
                "for node %(node)s", {
                    'address': mac,
                    'node': node.uuid
                })
Beispiel #4
0
 def test_vif_in_extra_in_internal_info(self):
     vif2 = 'another_uuid'
     port = objects.Port(self.context, **self.fake_port)
     port.internal_info['tenant_vif_port_id'] = vif2
     port._convert_to_version('1.8', False)
     # no change
     self.assertEqual(vif2, port.internal_info['tenant_vif_port_id'])
Beispiel #5
0
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        :raises: NotAcceptable, HTTPNotFound, Conflict
        """
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:port:create', cdict, cdict)

        if self.parent_node_ident or self.parent_portgroup_ident:
            raise exception.OperationNotPermitted()

        pdict = port.as_dict()
        self._check_allowed_port_fields(pdict)

        extra = pdict.get('extra')
        vif = extra.get('vif_port_id') if extra else None
        if vif:
            common_utils.warn_about_deprecated_extra_vif_port_id()
        if (pdict.get('portgroup_uuid') and (pdict.get('pxe_enabled') or vif)):
            rpc_pg = objects.Portgroup.get_by_uuid(context,
                                                   pdict['portgroup_uuid'])
            if not rpc_pg.standalone_ports_supported:
                msg = _("Port group %s doesn't support standalone ports. "
                        "This port cannot be created as a member of that "
                        "port group because either 'extra/vif_port_id' "
                        "was specified or 'pxe_enabled' was set to True.")
                raise exception.Conflict(msg % pdict['portgroup_uuid'])

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not pdict.get('uuid'):
            pdict['uuid'] = uuidutils.generate_uuid()

        rpc_port = objects.Port(context, **pdict)
        rpc_node = objects.Node.get_by_id(context, rpc_port.node_id)

        notify_extra = {
            'node_uuid': port.node_uuid,
            'portgroup_uuid': port.portgroup_uuid
        }
        notify.emit_start_notification(context, rpc_port, 'create',
                                       **notify_extra)
        with notify.handle_error_notification(context, rpc_port, 'create',
                                              **notify_extra):
            # TODO(mgoddard): In RPC API v1.41, port creation was moved to the
            # conductor service to facilitate validation of the physical
            # network field of ports in portgroups. Further consideration is
            # required determine how best to support rolling upgrades from a
            # release in which ports are created by the API service to one in
            # which they are created by the conductor service, while ensuring
            # that all required validation is performed.
            topic = pecan.request.rpcapi.get_topic_for(rpc_node)
            new_port = pecan.request.rpcapi.create_port(
                context, rpc_port, topic)
        notify.emit_end_notification(context, new_port, 'create',
                                     **notify_extra)
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
Beispiel #6
0
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        :raises: NotAcceptable, HTTPNotFound
        """
        cdict = pecan.request.context.to_dict()
        policy.authorize('baremetal:port:create', cdict, cdict)

        if self.parent_node_ident or self.parent_portgroup_ident:
            raise exception.OperationNotPermitted()

        pdict = port.as_dict()
        if (not api_utils.allow_port_advanced_net_fields()
                and set(pdict).intersection(self.advanced_net_fields)):
            raise exception.NotAcceptable()
        if (not api_utils.allow_portgroups_subcontrollers()
                and 'portgroup_uuid' in pdict):
            raise exception.NotAcceptable()

        new_port = objects.Port(pecan.request.context, **pdict)

        new_port.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
Beispiel #7
0
    def inspect_hardware(self, task):
        """Inspect hardware.

        Inspect hardware to obtain the essential hardware properties and
        mac addresses.

        :param task: a task from TaskManager.
        :raises: HardwareInspectionFailure, if hardware inspection failed.
        :returns: states.MANAGEABLE, if hardware inspection succeeded.
        """
        node = task.node
        kwargs = {}
        # Inspect additional capabilities task requires node with power on
        # status
        old_power_state = task.driver.power.get_power_state(task)
        if old_power_state == states.POWER_OFF:
            manager_utils.node_set_boot_device(task, boot_devices.BIOS, False)
            manager_utils.node_power_action(task, states.POWER_ON)

            LOG.info("The Node %(node_uuid)s being powered on for inspection",
                     {'node_uuid': task.node.uuid})

            kwargs['sleep_flag'] = True

        (props, macs) = _inspect_hardware(node, **kwargs)
        node.properties = dict(node.properties, **props)
        node.save()

        for mac in macs:
            try:
                new_port = objects.Port(task.context,
                                        address=mac,
                                        node_id=node.id)
                new_port.create()
                LOG.info(
                    "Port created for MAC address %(address)s "
                    "for node %(node_uuid)s during inspection", {
                        'address': mac,
                        'node_uuid': node.uuid
                    })
            except exception.MACAlreadyExists:
                LOG.warning(
                    "Port already existed for MAC address "
                    "%(address)s for node %(node_uuid)s "
                    "during inspection", {
                        'address': mac,
                        'node_uuid': node.uuid
                    })

        LOG.info("Node %s inspected", node.uuid)
        # restore old power state
        if old_power_state == states.POWER_OFF:
            manager_utils.node_power_action(task, states.POWER_OFF)

            LOG.info(
                "The Node %(node_uuid)s being powered off after "
                "inspection", {'node_uuid': task.node.uuid})

        return states.MANAGEABLE
Beispiel #8
0
 def test_name_unsupported_missing(self):
     # name not set, no change required.
     port = objects.Port(self.context, **self.fake_port)
     delattr(port, 'name')
     port.obj_reset_changes()
     port._convert_to_version("1.9")
     self.assertNotIn('name', port)
     self.assertNotIn('name', port.obj_get_changes())
Beispiel #9
0
 def test_name_unsupported_set_remove(self):
     # name set, should be removed.
     port = objects.Port(self.context, **self.fake_port)
     port.name = 'meow'
     port.obj_reset_changes()
     port._convert_to_version("1.9")
     self.assertNotIn('name', port)
     self.assertNotIn('name', port.obj_get_changes())
Beispiel #10
0
 def test_name_supported_set(self):
     # Physical network set, no change required.
     port = objects.Port(self.context, **self.fake_port)
     port.name = 'meow'
     port.obj_reset_changes()
     port._convert_to_version("1.10")
     self.assertEqual('meow', port.name)
     self.assertNotIn('name', port.obj_get_changes())
Beispiel #11
0
 def test_physnet_unsupported_set_no_remove_non_default(self):
     # Physical network set, should be set to default.
     port = objects.Port(self.context, **self.fake_port)
     port.physical_network = 'physnet1'
     port.obj_reset_changes()
     port._convert_to_version("1.6", False)
     self.assertIsNone(port.physical_network)
     self.assertEqual({'physical_network': None}, port.obj_get_changes())
Beispiel #12
0
 def test_physnet_supported_set(self):
     # Physical network set, no change required.
     port = objects.Port(self.context, **self.fake_port)
     port.physical_network = 'physnet1'
     port.obj_reset_changes()
     port._convert_to_version("1.7")
     self.assertEqual('physnet1', port.physical_network)
     self.assertEqual({}, port.obj_get_changes())
Beispiel #13
0
 def test_is_smartnic_unsupported_missing(self):
     # is_smartnic is not set, no change required.
     port = objects.Port(self.context, **self.fake_port)
     delattr(port, 'is_smartnic')
     port.obj_reset_changes()
     port._convert_to_version("1.8")
     self.assertNotIn('is_smartnic', port)
     self.assertNotIn('is_smartnic', port.obj_get_changes())
Beispiel #14
0
 def test_is_smartnic_unsupported_set_remove(self):
     # is_smartnic is set, should be removed.
     port = objects.Port(self.context, **self.fake_port)
     port.is_smartnic = False
     port.obj_reset_changes()
     port._convert_to_version("1.8")
     self.assertNotIn('is_smartnic', port)
     self.assertNotIn('is_smartnic', port.obj_get_changes())
Beispiel #15
0
 def test_name_unsupported_set_no_remove_default(self):
     # name set, no change required.
     port = objects.Port(self.context, **self.fake_port)
     port.name = None
     port.obj_reset_changes()
     port._convert_to_version("1.9", False)
     self.assertIsNone(port.name)
     self.assertNotIn('name', port.obj_get_changes())
Beispiel #16
0
 def test_is_smartnic_supported_set(self):
     # is_smartnic is set, no change required.
     port = objects.Port(self.context, **self.fake_port)
     port.is_smartnic = True
     port.obj_reset_changes()
     port._convert_to_version("1.9")
     self.assertTrue(port.is_smartnic)
     self.assertNotIn('is_smartnic', port.obj_get_changes())
Beispiel #17
0
 def test_physnet_unsupported_set_no_remove_default(self):
     # Physical network set, no change required.
     port = objects.Port(self.context, **self.fake_port)
     port.physical_network = None
     port.obj_reset_changes()
     port._convert_to_version("1.6", False)
     self.assertIsNone(port.physical_network)
     self.assertEqual({}, port.obj_get_changes())
Beispiel #18
0
 def test_is_smartnic_unsupported_set_no_remove_default(self):
     # is_smartnic is set, no change required.
     port = objects.Port(self.context, **self.fake_port)
     port.is_smartnic = False
     port.obj_reset_changes()
     port._convert_to_version("1.8", False)
     self.assertFalse(port.is_smartnic)
     self.assertNotIn('is_smartnic', port.obj_get_changes())
Beispiel #19
0
 def test_physnet_unsupported_set_remove(self):
     # Physical network set, should be removed.
     port = objects.Port(self.context, **self.fake_port)
     port.physical_network = 'physnet1'
     port.obj_reset_changes()
     port._convert_to_version("1.6")
     self.assertNotIn('physical_network', port)
     self.assertEqual({}, port.obj_get_changes())
Beispiel #20
0
 def test_physnet_unsupported_missing(self):
     # Physical network not set, no change required.
     port = objects.Port(self.context, **self.fake_port)
     delattr(port, 'physical_network')
     port.obj_reset_changes()
     port._convert_to_version("1.6")
     self.assertNotIn('physical_network', port)
     self.assertEqual({}, port.obj_get_changes())
Beispiel #21
0
 def test_physnet_supported_missing(self):
     # Physical network not set, should be set to default.
     port = objects.Port(self.context, **self.fake_port)
     delattr(port, 'physical_network')
     port.obj_reset_changes()
     port._convert_to_version("1.7")
     self.assertIsNone(port.physical_network)
     self.assertEqual({'physical_network': None}, port.obj_get_changes())
Beispiel #22
0
 def test_name_supported_missing(self):
     # name not set, should be set to default.
     port = objects.Port(self.context, **self.fake_port)
     delattr(port, 'name')
     port.obj_reset_changes()
     port._convert_to_version("1.10")
     self.assertIsNone(port.name)
     self.assertIn('name', port.obj_get_changes())
     self.assertIsNone(port.obj_get_changes()['name'])
Beispiel #23
0
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        :raises: NotAcceptable, HTTPNotFound, Conflict
        """
        context = pecan.request.context
        cdict = context.to_policy_values()
        policy.authorize('baremetal:port:create', cdict, cdict)

        if self.parent_node_ident or self.parent_portgroup_ident:
            raise exception.OperationNotPermitted()

        pdict = port.as_dict()
        if (not api_utils.allow_port_advanced_net_fields()
                and set(pdict).intersection(self.advanced_net_fields)):
            raise exception.NotAcceptable()
        if (not api_utils.allow_portgroups_subcontrollers()
                and 'portgroup_uuid' in pdict):
            raise exception.NotAcceptable()

        extra = pdict.get('extra')
        vif = extra.get('vif_port_id') if extra else None
        if vif:
            common_utils.warn_about_deprecated_extra_vif_port_id()
        if (pdict.get('portgroup_uuid') and (pdict.get('pxe_enabled') or vif)):
            rpc_pg = objects.Portgroup.get_by_uuid(context,
                                                   pdict['portgroup_uuid'])
            if not rpc_pg.standalone_ports_supported:
                msg = _("Port group %s doesn't support standalone ports. "
                        "This port cannot be created as a member of that "
                        "port group because either 'extra/vif_port_id' "
                        "was specified or 'pxe_enabled' was set to True.")
                raise exception.Conflict(msg % pdict['portgroup_uuid'])

        # NOTE(yuriyz): UUID is mandatory for notifications payload
        if not pdict.get('uuid'):
            pdict['uuid'] = uuidutils.generate_uuid()

        new_port = objects.Port(context, **pdict)

        notify.emit_start_notification(context,
                                       new_port,
                                       'create',
                                       node_uuid=port.node_uuid)
        with notify.handle_error_notification(context,
                                              new_port,
                                              'create',
                                              node_uuid=port.node_uuid):
            new_port.create()
        notify.emit_end_notification(context,
                                     new_port,
                                     'create',
                                     node_uuid=port.node_uuid)
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
Beispiel #24
0
 def test_is_smartnic_unsupported_set_no_remove_non_default(self):
     # is_smartnic is set, should be set to default.
     port = objects.Port(self.context, **self.fake_port)
     port.is_smartnic = True
     port.obj_reset_changes()
     port._convert_to_version("1.8", False)
     self.assertFalse(port.is_smartnic)
     self.assertIn('is_smartnic', port.obj_get_changes())
     self.assertFalse(port.obj_get_changes()['is_smartnic'])
Beispiel #25
0
 def test_is_smartnic_supported_missing(self):
     # is_smartnic is not set, should be set to default.
     port = objects.Port(self.context, **self.fake_port)
     delattr(port, 'is_smartnic')
     port.obj_reset_changes()
     port._convert_to_version("1.9")
     self.assertFalse(port.is_smartnic)
     self.assertIn('is_smartnic', port.obj_get_changes())
     self.assertFalse(port.obj_get_changes()['is_smartnic'])
Beispiel #26
0
 def test_name_unsupported_set_no_remove_non_default(self):
     # name set, should be set to default.
     port = objects.Port(self.context, **self.fake_port)
     port.name = 'meow'
     port.obj_reset_changes()
     port._convert_to_version("1.9", False)
     self.assertIsNone(port.name)
     self.assertIn('name', port.obj_get_changes())
     self.assertIsNone(port.obj_get_changes()['name'])
Beispiel #27
0
    def test_create(self):
        port = objects.Port(self.context, **self.fake_port)
        with mock.patch.object(self.dbapi, 'create_port',
                               autospec=True) as mock_create_port:
            mock_create_port.return_value = db_utils.get_test_port()

            port.create()

            args, _kwargs = mock_create_port.call_args
            self.assertEqual(objects.Port.VERSION, args[0]['version'])
Beispiel #28
0
def get_test_port(ctxt, **kw):
    """Return a Port object with appropriate attributes.

    NOTE: The object leaves the attributes marked as changed, such
    that a create() could be used to commit it to the DB.
    """
    db_port = db_utils.get_test_port(**kw)
    port = objects.Port(ctxt)
    for key in db_port:
        setattr(port, key, db_port[key])
    return port
Beispiel #29
0
    def post(self, port):
        """Create a new port.

        :param port: a port within the request body.
        """
        if self.from_nodes:
            raise exception.OperationNotPermitted

        new_port = objects.Port(pecan.request.context, **port.as_dict())
        new_port.create()
        # Set the HTTP Location Header
        pecan.response.location = link.build_url('ports', new_port.uuid)
        return Port.convert_with_links(new_port)
Beispiel #30
0
def get_test_port(ctxt, **kw):
    """Return a Port object with appropriate attributes.

    NOTE: The object leaves the attributes marked as changed, such
    that a create() could be used to commit it to the DB.
    """
    db_port = db_utils.get_test_port(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if 'id' not in kw:
        del db_port['id']
    port = objects.Port(ctxt)
    for key in db_port:
        setattr(port, key, db_port[key])
    return port