コード例 #1
0
ファイル: common.py プロジェクト: stackhpc/ironic
    def vif_detach(self, task, vif_id):
        """Detach a virtual network interface from a node

        :param task: A TaskManager instance.
        :param vif_id: A VIF ID to detach
        :raises: VifNotAttached if VIF not attached.
        :raises: NetworkError: if unbind Neutron port failed.
        """

        # NOTE(vsaienko) We picking object to attach on vif-attach side.
        # Here we should only detach VIF and shouldn't duplicate/follow
        # attach rules, just walk over all objects and detach VIF.
        for port_like_obj in task.portgroups + task.ports:
            # FIXME(sambetts) Remove this when we no longer support a nova
            # driver that uses port.extra
            vif_port_id = port_like_obj.internal_info.get(
                TENANT_VIF_KEY, port_like_obj.extra.get("vif_port_id"))
            if vif_port_id == vif_id:
                int_info = port_like_obj.internal_info
                extra = port_like_obj.extra
                int_info.pop(TENANT_VIF_KEY, None)
                extra.pop('vif_port_id', None)
                port_like_obj.extra = extra
                port_like_obj.internal_info = int_info
                port_like_obj.save()
                # NOTE(vsaienko) allow to unplug VIFs from ACTIVE instance.
                if task.node.provision_state == states.ACTIVE:
                    neutron.unbind_neutron_port(vif_port_id)
                break
        else:
            raise exception.VifNotAttached(vif=vif_id, node=task.node.uuid)
コード例 #2
0
ファイル: common.py プロジェクト: jimrollenhagen/ironic
    def _get_port_like_obj_by_vif_id(self, task, vif_id):
        """Lookup a port or portgroup by its attached VIF ID.

        :param task: A TaskManager instance.
        :param vif_id: ID of the attached VIF.
        :returns: A Port or Portgroup object to which the VIF is attached.
        :raises: VifNotAttached if the VIF is not attached.
        """
        for port_like_obj in task.portgroups + task.ports:
            vif_port_id = self._get_vif_id_by_port_like_obj(port_like_obj)
            if vif_port_id == vif_id:
                return port_like_obj
        raise exception.VifNotAttached(vif=vif_id, node=task.node.uuid)
コード例 #3
0
    def vif_detach(self, task, vif_id):
        """Detach a virtual network interface from a node

        :param task: A TaskManager instance.
        :param vif_id: A VIF ID to detach
        :raises: VifNotAttached
        """
        for port in task.ports:
            # FIXME(sambetts) Remove this when we no longer support a nova
            # driver that uses port.extra
            if (port.extra.get("vif_port_id") == vif_id or
                    port.internal_info.get(TENANT_VIF_KEY) == vif_id):
                int_info = port.internal_info
                extra = port.extra
                int_info.pop(TENANT_VIF_KEY, None)
                extra.pop('vif_port_id', None)
                port.extra = extra
                port.internal_info = int_info
                port.save()
                break
        else:
            raise exception.VifNotAttached(vif=vif_id, node=task.node.uuid)
コード例 #4
0
ファイル: common.py プロジェクト: stackhpc/ironic
def plug_port_to_tenant_network(task, port_like_obj, client=None):
    """Plug port like object to tenant network.

    :param task: A TaskManager instance.
    :param port_like_obj: port-like object to plug.
    :param client: Neutron client instance.
    :raises NetworkError: if failed to update Neutron port.
    :raises VifNotAttached if tenant VIF is not associated with port_like_obj.
    """

    node = task.node
    local_link_info = []
    client_id_opt = None

    vif_id = (port_like_obj.internal_info.get(TENANT_VIF_KEY)
              or port_like_obj.extra.get('vif_port_id'))

    if not vif_id:
        obj_name = port_like_obj.__class__.__name__.lower()
        raise exception.VifNotAttached(
            _("Tenant VIF is not associated with %(obj_name)s "
              "%(obj_id)s") % {
                  'obj_name': obj_name,
                  'obj_id': port_like_obj.uuid
              })

    LOG.debug('Mapping tenant port %(vif_id)s to node '
              '%(node_id)s', {
                  'vif_id': vif_id,
                  'node_id': node.uuid
              })

    if isinstance(port_like_obj, objects.Portgroup):
        pg_ports = [
            p for p in task.ports if p.portgroup_id == port_like_obj.id
        ]
        for port in pg_ports:
            local_link_info.append(port.local_link_connection)
    else:
        # We iterate only on ports or portgroups, no need to check
        # that it is a port
        local_link_info.append(port_like_obj.local_link_connection)
        client_id = port_like_obj.extra.get('client-id')
        if client_id:
            client_id_opt = ({'opt_name': 'client-id', 'opt_value': client_id})

    # NOTE(sambetts) Only update required binding: attributes,
    # because other port attributes may have been set by the user or
    # nova.
    body = {
        'port': {
            'binding:vnic_type': 'baremetal',
            'binding:host_id': node.uuid,
            'binding:profile': {
                'local_link_information': local_link_info,
            },
        }
    }
    if client_id_opt:
        body['port']['extra_dhcp_opts'] = [client_id_opt]

    if not client:
        client = neutron.get_client()

    try:
        client.update_port(vif_id, body)
    except neutron_exceptions.ConnectionFailed as e:
        msg = (_('Could not add public network VIF %(vif)s '
                 'to node %(node)s, possible network issue. %(exc)s') % {
                     'vif': vif_id,
                     'node': node.uuid,
                     'exc': e
                 })
        LOG.error(msg)
        raise exception.NetworkError(msg)
コード例 #5
0
ファイル: common.py プロジェクト: namnx228/ironic
def plug_port_to_tenant_network(task, port_like_obj, client=None):
    """Plug port like object to tenant network.

    :param task: A TaskManager instance.
    :param port_like_obj: port-like object to plug.
    :param client: Neutron client instance.
    :raises: NetworkError if failed to update Neutron port.
    :raises: VifNotAttached if tenant VIF is not associated with port_like_obj.
    """

    node = task.node
    local_link_info = []
    local_group_info = None
    client_id_opt = None

    vif_id = (port_like_obj.internal_info.get(TENANT_VIF_KEY)
              or port_like_obj.extra.get('vif_port_id'))

    if not vif_id:
        obj_name = port_like_obj.__class__.__name__.lower()
        raise exception.VifNotAttached(
            _("Tenant VIF is not associated with %(obj_name)s "
              "%(obj_id)s") % {
                  'obj_name': obj_name,
                  'obj_id': port_like_obj.uuid
              })

    LOG.debug('Mapping tenant port %(vif_id)s to node '
              '%(node_id)s', {
                  'vif_id': vif_id,
                  'node_id': node.uuid
              })

    if isinstance(port_like_obj, objects.Portgroup):
        pg_ports = [
            p for p in task.ports if p.portgroup_id == port_like_obj.id
        ]
        for port in pg_ports:
            local_link_info.append(port.local_link_connection)
        local_group_info = neutron.get_local_group_information(
            task, port_like_obj)
    else:
        # We iterate only on ports or portgroups, no need to check
        # that it is a port
        local_link_info.append(port_like_obj.local_link_connection)
        client_id = port_like_obj.extra.get('client-id')
        if client_id:
            client_id_opt = ({
                'opt_name': DHCP_CLIENT_ID,
                'opt_value': client_id
            })

    # NOTE(sambetts) Only update required binding: attributes,
    # because other port attributes may have been set by the user or
    # nova.
    port_attrs = {
        'binding:vnic_type': neutron.VNIC_BAREMETAL,
        'binding:host_id': node.uuid
    }
    # NOTE(kaifeng) Only update mac address when it's available
    if port_like_obj.address:
        port_attrs['mac_address'] = port_like_obj.address
    binding_profile = {'local_link_information': local_link_info}
    if local_group_info:
        binding_profile['local_group_information'] = local_group_info
    port_attrs['binding:profile'] = binding_profile

    if client_id_opt:
        port_attrs['extra_dhcp_opts'] = [client_id_opt]

    is_smart_nic = neutron.is_smartnic_port(port_like_obj)
    if is_smart_nic:
        link_info = local_link_info[0]
        LOG.debug(
            'Setting hostname as host_id in case of Smart NIC, '
            'port %(port_id)s, hostname %(hostname)s', {
                'port_id': vif_id,
                'hostname': link_info['hostname']
            })
        port_attrs['binding:host_id'] = link_info['hostname']
        port_attrs['binding:vnic_type'] = neutron.VNIC_SMARTNIC

    if not client:
        client = neutron.get_client(context=task.context)

    if is_smart_nic:
        neutron.wait_for_host_agent(client, port_attrs['binding:host_id'])

    try:
        neutron.update_neutron_port(task.context, vif_id, port_attrs)
        if is_smart_nic:
            neutron.wait_for_port_status(client, vif_id, 'ACTIVE')
    except openstack_exc.OpenStackCloudException as e:
        msg = (_('Could not add public network VIF %(vif)s '
                 'to node %(node)s, possible network issue. %(exc)s') % {
                     'vif': vif_id,
                     'node': node.uuid,
                     'exc': e
                 })
        LOG.error(msg)
        raise exception.NetworkError(msg)