openstack Neuturon組件在何處創建tap口

tap口創建流程

dhcp agent先通過plugin創建dhcp port,plugin返回Port詳情,包括port ID,mac地址,IP地址等信息。

然後通過interface driver先ovs-vsctl add-port 創建一個internal的tap口,然後加入到br-int中。然後創建namespace,將tap加入namespace,在tap口上配置IP地址。

創建接口的操作是neturonn乾的,不歸dhcp_agent,dhcp_agent只不過是rpc遠程調用
在/neuturon/agent/dhcp/agent.py

class DhcpPluginApi(object):
    """Agent side of the dhcp rpc API.

    This class implements the client side of an rpc interface.  The server side
    of this interface can be found in
    neutron.api.rpc.handlers.dhcp_rpc.DhcpRpcCallback.  For more information
    about changing rpc interfaces, see doc/source/devref/rpc_api.rst.

    API version history:
        1.0 - Initial version.
        1.1 - Added get_active_networks_info, create_dhcp_port,
              and update_dhcp_port methods.
        1.5 - Added dhcp_ready_on_ports

    """

    def __init__(self, topic, host):
        self.host = host
        target = oslo_messaging.Target(
                topic=topic,
                namespace=n_const.RPC_NAMESPACE_DHCP_PLUGIN,
                version='1.0')
        self.client = n_rpc.get_client(target)

    @property
    def context(self):
        # TODO(kevinbenton): the context should really be passed in to each of
        # these methods so a call can be tracked all of the way through the
        # system but that will require a larger refactor to pass the context
        # everywhere. We just generate a new one here on each call so requests
        # can be independently tracked server side.
        return context.get_admin_context_without_session()

    def get_active_networks_info(self):
        """Make a remote process call to retrieve all network info."""
        cctxt = self.client.prepare(version='1.1')
        networks = cctxt.call(self.context, 'get_active_networks_info',
                              host=self.host)
        return [dhcp.NetModel(n) for n in networks]

    def get_network_info(self, network_id):
        """Make a remote process call to retrieve network info."""
        cctxt = self.client.prepare()
        network = cctxt.call(self.context, 'get_network_info',
                             network_id=network_id, host=self.host)
        if network:
            return dhcp.NetModel(network)

    def create_dhcp_port(self, port):
        """Make a remote process call to create the dhcp port."""
        cctxt = self.client.prepare(version='1.1')
        port = cctxt.call(self.context, 'create_dhcp_port',
                          port=port, host=self.host)
        if port:
            return dhcp.DictModel(port)

    def update_dhcp_port(self, port_id, port):
        """Make a remote process call to update the dhcp port."""
        cctxt = self.client.prepare(version='1.1')
        port = cctxt.call(self.context, 'update_dhcp_port',
                          port_id=port_id, port=port, host=self.host)
        if port:
            return dhcp.DictModel(port)

    def release_dhcp_port(self, network_id, device_id):
        """Make a remote process call to release the dhcp port."""
        cctxt = self.client.prepare()
        return cctxt.call(self.context, 'release_dhcp_port',
                          network_id=network_id, device_id=device_id,
                          host=self.host)

    def dhcp_ready_on_ports(self, port_ids):
        """Notify the server that DHCP is configured for the port."""
        cctxt = self.client.prepare(version='1.5')
        return cctxt.call(self.context, 'dhcp_ready_on_ports',
                          port_ids=port_ids)

這邊又看到一個人寫的流程很好:
neutron-dhcp-agent收到neutron server創建網絡的通知和neutron-dhcp-agent主動承載一個網絡的操作基本上是一樣的,如下
dhcp-agent.ini中dhcp_driver設置爲 dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq

  1. 檢查網絡中是否有enable dhcp的subnet, 有則會調用dhcp_driver的enable操作
  2. Dnsmasq.enable()
    2.1 如果當前存在Dnsmasq的進程,則重啓, 沒有則繼續操作
    2.2. 調用DeviceManager的setup方法,
    2.2.1. setup_dhcp_port() 如果有dhcp_port,則返回,沒有則創建, 根據port裏面的device_id選項來區分這個port是否屬於這個agent的dhcp port
    2.2.2. 判斷port的interface名字是否存在(如:tape613727f-c3 ),如果不存在則會創建這個interface, 調用driver的plug(這個方法中會創建namespace,創建設備(創建的過程需要openvswitch agent配合,在下面介紹),並將設備綁定到br-int上)
    2.2.3. fill_dhcp_udp_checksum(),在dhcp namespace中創建udp checksum規則?, 如: -A neutron-dhcp-age-POSTROUTING -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
    2.2.4. 調用driver的init_l3(),初始化dhcp namespace中的路由規則, 其中包括subnet中的默認網關以及metadata相關的路由。
    2.2.5 調用dhcp_driver的spawn_process()
    2.2.5.1 在創建Dnsmasq服務之前需要初始化它的配置文件, 包括三個文件(hosts_file, addn_hosts_file, opts_file)
    hosts_file: 記錄mac, hostname, ip的映射關係
    addn_hosts_file: 記錄ip, 長hostname,短hostname的映射關係
    opts_file: 記錄默認路由以及dns server
    2.2.5.2 創建Dnsmasq進程。

這樣創建一個網絡,包括subnet的過程基本結束了。

原文鏈接:https://blog.csdn.net/allenson1/article/details/54602007

就是在\neutron\agent\linux\dhcp.py中class DhcpLocalProcess(DhcpBase):類裏的device_manager.setup(self.network)

    def enable(self):
        """Enables DHCP for this network by spawning a local process."""
        if self.active:
            self.restart()
        elif self._enable_dhcp():
            fileutils.ensure_tree(self.network_conf_dir, mode=0o755)
            interface_name = self.device_manager.setup(self.network)
            self.interface_name = interface_name
            self.spawn_process()
    def setup_dhcp_port(self, network):
        """Create/update DHCP port for the host if needed and return port."""

        # The ID that the DHCP port will have (or already has).
        device_id = self.get_device_id(network)

        # Get the set of DHCP-enabled local subnets on this network.
        dhcp_subnets = {subnet.id: subnet for subnet in network.subnets
                        if subnet.enable_dhcp}

        # There are 3 cases: either the DHCP port already exists (but
        # might need to be updated for a changed set of subnets); or
        # some other code has already prepared a 'reserved' DHCP port,
        # and we just need to adopt that; or we need to create a new
        # DHCP port.  Try each of those in turn until we have a DHCP
        # port.
        for setup_method in (self._setup_existing_dhcp_port,
                             self._setup_reserved_dhcp_port,
                             self._setup_new_dhcp_port):
            dhcp_port = setup_method(network, device_id, dhcp_subnets)
            if dhcp_port:
                break
        else:
            raise exceptions.Conflict()
    def _setup_new_dhcp_port(self, network, device_id, dhcp_subnets):
        """Create and set up new DHCP port for the specified network."""
        LOG.debug('DHCP port %(device_id)s on network %(network_id)s'
                  ' does not yet exist. Creating new one.',
                  {'device_id': device_id, 'network_id': network.id})

        # Make a list of the subnets that need a unique IP address for
        # this DHCP port.
        if self.driver.use_gateway_ips:
            unique_ip_subnets = []
        else:
            unique_ip_subnets = [dict(subnet_id=s) for s in dhcp_subnets]

        port_dict = dict(
            name='',
            admin_state_up=True,
            device_id=device_id,
            network_id=network.id,
            tenant_id=network.tenant_id,
            fixed_ips=unique_ip_subnets)
        return self.plugin.create_dhcp_port({'port': port_dict})

self.plugin.create_dhcp_port({‘port’: port_dict}) 爲遠程rpc調用

然後找到配置 文件的位置

  def spawn_process(self):
        """Spawn the process, if it's not spawned already."""
        # we only need to generate the lease file the first time dnsmasq starts
        # rather than on every reload since dnsmasq will keep the file current
        self._output_init_lease_file()
        self._spawn_or_reload_process(reload_with_HUP=False)

    def _spawn_or_reload_process(self, reload_with_HUP):
        """Spawns or reloads a Dnsmasq process for the network.

        When reload_with_HUP is True, dnsmasq receives a HUP signal,
        or it's reloaded if the process is not running.
        """

        self._output_config_files()

        pm = self._get_process_manager(
            cmd_callback=self._build_cmdline_callback)

        pm.enable(reload_cfg=reload_with_HUP)

        self.process_monitor.register(uuid=self.network.id,
                                      service_name=DNSMASQ_SERVICE_NAME,
                                      monitored_process=pm)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章