示例#1
0
    def provision_local_vlan(self, net_uuid, network_type, physical_network,
                             segmentation_id):
        """Provisions a local VLAN.

        :param net_uuid: the uuid of the network associated with this vlan.
        :param network_type: the network type ('gre', 'vxlan', 'vlan', 'flat',
                                               'local')
        :param physical_network: the physical network for 'vlan' or 'flat'
        :param segmentation_id: the VID for 'vlan' or tunnel ID for 'tunnel'
        """

        if not self.available_local_vlans:
            LOG.error(_LE("No local VLAN available for net-id=%s"), net_uuid)
            return
        lvid = self.available_local_vlans.pop()
        LOG.info(
            _LI("Assigning %(vlan_id)s as local vlan for "
                "net-id=%(net_uuid)s"), {
                    'vlan_id': lvid,
                    'net_uuid': net_uuid
                })
        self.local_vlan_map[net_uuid] = LocalVLANMapping(
            lvid, network_type, physical_network, segmentation_id)

        if network_type in constants.TUNNEL_NETWORK_TYPES:
            if self.enable_tunneling:
                self.int_br.provision_tenant_tunnel(network_type, lvid,
                                                    segmentation_id)
            else:
                LOG.error(
                    _LE("Cannot provision %(network_type)s network for "
                        "net-id=%(net_uuid)s - tunneling disabled"), {
                            'network_type': network_type,
                            'net_uuid': net_uuid
                        })
        elif network_type in [p_const.TYPE_VLAN, p_const.TYPE_FLAT]:
            if physical_network in self.int_ofports:
                phys_port = self.int_ofports[physical_network]
                self.int_br.provision_tenant_physnet(network_type, lvid,
                                                     segmentation_id,
                                                     phys_port)
            else:
                LOG.error(
                    _LE("Cannot provision %(network_type)s network for "
                        "net-id=%(net_uuid)s - no bridge for "
                        "physical_network %(physical_network)s"), {
                            'network_type': network_type,
                            'net_uuid': net_uuid,
                            'physical_network': physical_network
                        })
        elif network_type == p_const.TYPE_LOCAL:
            # no flows needed for local networks
            pass
        else:
            LOG.error(
                _LE("Cannot provision unknown network type "
                    "%(network_type)s for net-id=%(net_uuid)s"), {
                        'network_type': network_type,
                        'net_uuid': net_uuid
                    })
    def provision_local_vlan(self, net_uuid, network_type, physical_network,
                             segmentation_id):
        """Provisions a local VLAN.

        :param net_uuid: the uuid of the network associated with this vlan.
        :param network_type: the network type ('gre', 'vxlan', 'vlan', 'flat',
                                               'local')
        :param physical_network: the physical network for 'vlan' or 'flat'
        :param segmentation_id: the VID for 'vlan' or tunnel ID for 'tunnel'
        """

        if not self.available_local_vlans:
            LOG.error(_LE("No local VLAN available for net-id=%s"), net_uuid)
            return
        lvid = self.available_local_vlans.pop()
        LOG.info(_LI("Assigning %(vlan_id)s as local vlan for "
                     "net-id=%(net_uuid)s"),
                 {'vlan_id': lvid, 'net_uuid': net_uuid})
        self.local_vlan_map[net_uuid] = LocalVLANMapping(lvid, network_type,
                                                         physical_network,
                                                         segmentation_id)

        if network_type in constants.TUNNEL_NETWORK_TYPES:
            if self.enable_tunneling:
                self.int_br.provision_tenant_tunnel(network_type, lvid,
                                                    segmentation_id)
            else:
                LOG.error(_LE("Cannot provision %(network_type)s network for "
                              "net-id=%(net_uuid)s - tunneling disabled"),
                          {'network_type': network_type,
                           'net_uuid': net_uuid})
        elif network_type in [p_const.TYPE_VLAN, p_const.TYPE_FLAT]:
            if physical_network in self.int_ofports:
                phys_port = self.int_ofports[physical_network]
                self.int_br.provision_tenant_physnet(network_type, lvid,
                                                     segmentation_id,
                                                     phys_port)
            else:
                LOG.error(_LE("Cannot provision %(network_type)s network for "
                              "net-id=%(net_uuid)s - no bridge for "
                              "physical_network %(physical_network)s"),
                          {'network_type': network_type,
                           'net_uuid': net_uuid,
                           'physical_network': physical_network})
        elif network_type == p_const.TYPE_LOCAL:
            # no flows needed for local networks
            pass
        else:
            LOG.error(_LE("Cannot provision unknown network type "
                          "%(network_type)s for net-id=%(net_uuid)s"),
                      {'network_type': network_type,
                       'net_uuid': net_uuid})
    def reclaim_local_vlan(self, net_uuid):
        """Reclaim a local VLAN.

        :param net_uuid: the network uuid associated with this vlan.
        :param lvm: a LocalVLANMapping object that tracks (vlan, lsw_id,
            vif_ids) mapping.
        """
        lvm = self.local_vlan_map.pop(net_uuid, None)
        if lvm is None:
            LOG.debug("Network %s not used on agent.", net_uuid)
            return

        LOG.info(_LI("Reclaiming vlan = %(vlan_id)s from "
                     "net-id = %(net_uuid)s"),
                 {'vlan_id': lvm.vlan,
                  'net_uuid': net_uuid})

        if lvm.network_type in constants.TUNNEL_NETWORK_TYPES:
            if self.enable_tunneling:
                self.int_br.reclaim_tenant_tunnel(lvm.network_type, lvm.vlan,
                                                  lvm.segmentation_id)
        elif lvm.network_type in [p_const.TYPE_FLAT, p_const.TYPE_VLAN]:
            phys_port = self.int_ofports[lvm.physical_network]
            self.int_br.reclaim_tenant_physnet(lvm.network_type, lvm.vlan,
                                               lvm.segmentation_id, phys_port)
        elif lvm.network_type == p_const.TYPE_LOCAL:
            # no flows needed for local networks
            pass
        else:
            LOG.error(_LE("Cannot reclaim unknown network type "
                          "%(network_type)s for net-id=%(net_uuid)s"),
                      {'network_type': lvm.network_type,
                       'net_uuid': net_uuid})

        self.available_local_vlans.add(lvm.vlan)
 def _report_state(self):
     # How many devices are likely used by a VM
     self.agent_state.get("configurations")["devices"] = self.int_br_device_count
     try:
         self.state_rpc.report_state(self.context, self.agent_state)
         self.agent_state.pop("start_flag", None)
     except Exception:
         LOG.exception(_LE("Failed reporting state!"))
示例#5
0
 def _report_state(self):
     # How many devices are likely used by a VM
     self.agent_state.get('configurations')['devices'] = (
         self.int_br_device_count)
     try:
         self.state_rpc.report_state(self.context, self.agent_state)
         self.agent_state.pop('start_flag', None)
     except Exception:
         LOG.exception(_LE("Failed reporting state!"))
 def _report_state(self):
     # How many devices are likely used by a VM
     self.agent_state.get('configurations')['devices'] = (
         self.int_br_device_count)
     try:
         self.state_rpc.report_state(self.context,
                                     self.agent_state)
         self.agent_state.pop('start_flag', None)
     except Exception:
         LOG.exception(_LE("Failed reporting state!"))
 def get_datapath(self, retry_max=cfg.CONF.AGENT.get_datapath_retry_times):
     retry = 0
     while self.datapath is None:
         self.datapath = ryu_api.get_datapath(self.ryuapp, int(self.datapath_id, 16))
         retry += 1
         if retry >= retry_max:
             LOG.error(_LE("Agent terminated!: Failed to get a datapath."))
             raise SystemExit(1)
         time.sleep(1)
     self.set_dp(self.datapath)
示例#8
0
 def get_datapath(self, retry_max=cfg.CONF.AGENT.get_datapath_retry_times):
     retry = 0
     while self.datapath is None:
         self.datapath = ryu_api.get_datapath(self.ryuapp,
                                              int(self.datapath_id, 16))
         retry += 1
         if retry >= retry_max:
             LOG.error(_LE('Agent terminated!: Failed to get a datapath.'))
             raise SystemExit(1)
         time.sleep(1)
     self.set_dp(self.datapath)
示例#9
0
    def _agent_main(self, ryuapp):
        cfg.CONF.register_opts(ip_lib.OPTS)
        n_utils.log_opt_values(LOG)

        try:
            agent_config = create_agent_config_map(cfg.CONF)
        except ValueError:
            LOG.exception(_LE("Agent failed to create agent config map"))
            raise SystemExit(1)

        agent = OFANeutronAgent(ryuapp, **agent_config)
        self.arplib.set_bridge(agent.int_br)

        # Start everything.
        LOG.info(_LI("Agent initialized successfully, now running... "))
        agent.daemon_loop()
    def _agent_main(self, ryuapp):
        cfg.CONF.register_opts(ip_lib.OPTS)
        n_utils.log_opt_values(LOG)

        try:
            agent_config = create_agent_config_map(cfg.CONF)
        except ValueError:
            LOG.exception(_LE("Agent failed to create agent config map"))
            raise SystemExit(1)

        agent = OFANeutronAgent(ryuapp, **agent_config)
        self.arplib.set_bridge(agent.int_br)

        # Start everything.
        LOG.info(_LI("Agent initialized successfully, now running... "))
        agent.daemon_loop()
 def _setup_tunnel_port(self, br, port_name, tunnel_type):
     # NOTE(yamamoto): Ideally we can specify self.local_ip instead of
     # "0" here.  However, Open vSwitch v2.0.2 doesn't support the
     # specific combination of flow/non-flow parameters we want to use
     # here.  The limitation was removed for Open vSwitch>=v2.3.
     # TODO(yamamoto): Revisit when that version gets available for
     # relevant platforms.
     ofport = br.add_tunnel_port(port_name, "flow", "0", tunnel_type, self.vxlan_udp_port, self.dont_fragment)
     if ofport == ovs_lib.INVALID_OFPORT:
         LOG.error(_LE("Failed to set-up %(type)s tunnel port"), {"type": tunnel_type})
         return 0
     ofport = int(ofport)
     self.tun_ofports[tunnel_type] = ofport
     # NOTE(yamamoto): We include local_ip in the match here because
     # our tunnel port is with local_ip=0.  See the above comment.
     br.check_in_port_add_tunnel_port(tunnel_type, ofport, self.local_ip)
     return ofport
 def setup_ofp(
     self, controller_names=None, protocols="OpenFlow13", retry_max=cfg.CONF.AGENT.get_datapath_retry_times
 ):
     if not controller_names:
         host = ryu_cfg.CONF.ofp_listen_host
         if not host:
             # 127.0.0.1 is a default for agent style of controller
             host = "127.0.0.1"
         controller_names = ["tcp:%s:%d" % (host, ryu_cfg.CONF.ofp_tcp_listen_port)]
     try:
         self.set_protocols(protocols)
         self.set_controller(controller_names)
     except RuntimeError:
         LOG.exception(_LE("Agent terminated"))
         raise SystemExit(1)
     self.find_datapath_id()
     self.get_datapath(retry_max)
示例#13
0
 def _setup_tunnel_port(self, br, port_name, tunnel_type):
     # NOTE(yamamoto): Ideally we can specify self.local_ip instead of
     # "0" here.  However, Open vSwitch v2.0.2 doesn't support the
     # specific combination of flow/non-flow parameters we want to use
     # here.  The limitation was removed for Open vSwitch>=v2.3.
     # TODO(yamamoto): Revisit when that version gets available for
     # relevant platforms.
     ofport = br.add_tunnel_port(port_name, "flow", "0", tunnel_type,
                                 self.vxlan_udp_port, self.dont_fragment)
     if ofport == ovs_lib.INVALID_OFPORT:
         LOG.error(_LE("Failed to set-up %(type)s tunnel port"),
                   {'type': tunnel_type})
         return 0
     ofport = int(ofport)
     self.tun_ofports[tunnel_type] = ofport
     # NOTE(yamamoto): We include local_ip in the match here because
     # our tunnel port is with local_ip=0.  See the above comment.
     br.check_in_port_add_tunnel_port(tunnel_type, ofport, self.local_ip)
     return ofport
示例#14
0
 def setup_ofp(self,
               controller_names=None,
               protocols='OpenFlow13',
               retry_max=cfg.CONF.AGENT.get_datapath_retry_times):
     if not controller_names:
         host = ryu_cfg.CONF.ofp_listen_host
         if not host:
             # 127.0.0.1 is a default for agent style of controller
             host = '127.0.0.1'
         controller_names = [
             "tcp:%s:%d" % (host, ryu_cfg.CONF.ofp_tcp_listen_port)
         ]
     try:
         self.set_protocols(protocols)
         self.set_controller(controller_names)
     except RuntimeError:
         LOG.exception(_LE("Agent terminated"))
         raise SystemExit(1)
     self.find_datapath_id()
     self.get_datapath(retry_max)
示例#15
0
    def reclaim_local_vlan(self, net_uuid):
        """Reclaim a local VLAN.

        :param net_uuid: the network uuid associated with this vlan.
        :param lvm: a LocalVLANMapping object that tracks (vlan, lsw_id,
            vif_ids) mapping.
        """
        lvm = self.local_vlan_map.pop(net_uuid, None)
        if lvm is None:
            LOG.debug("Network %s not used on agent.", net_uuid)
            return

        LOG.info(
            _LI("Reclaiming vlan = %(vlan_id)s from "
                "net-id = %(net_uuid)s"), {
                    'vlan_id': lvm.vlan,
                    'net_uuid': net_uuid
                })

        if lvm.network_type in constants.TUNNEL_NETWORK_TYPES:
            if self.enable_tunneling:
                self.int_br.reclaim_tenant_tunnel(lvm.network_type, lvm.vlan,
                                                  lvm.segmentation_id)
        elif lvm.network_type in [p_const.TYPE_FLAT, p_const.TYPE_VLAN]:
            phys_port = self.int_ofports[lvm.physical_network]
            self.int_br.reclaim_tenant_physnet(lvm.network_type, lvm.vlan,
                                               lvm.segmentation_id, phys_port)
        elif lvm.network_type == p_const.TYPE_LOCAL:
            # no flows needed for local networks
            pass
        else:
            LOG.error(
                _LE("Cannot reclaim unknown network type "
                    "%(network_type)s for net-id=%(net_uuid)s"), {
                        'network_type': lvm.network_type,
                        'net_uuid': net_uuid
                    })

        self.available_local_vlans.add(lvm.vlan)
    def daemon_loop(self):
        # TODO(yamamoto):
        # It might be better to monitor port status async messages

        sync = True
        ports = set()
        tunnel_sync = True
        while True:
            start = time.time()
            port_stats = {'regular': {'added': 0, 'updated': 0, 'removed': 0}}
            LOG.debug("Agent daemon_loop - iteration:%d started",
                      self.iter_num)
            if sync:
                LOG.info(_LI("Agent out of sync with plugin!"))
                ports.clear()
                sync = False
            # Notify the plugin of tunnel IP
            if self.enable_tunneling and tunnel_sync:
                LOG.info(_LI("Agent tunnel out of sync with plugin!"))
                try:
                    tunnel_sync = self.tunnel_sync()
                except Exception:
                    LOG.exception(_LE("Error while synchronizing tunnels"))
                    tunnel_sync = True
            LOG.debug("Agent daemon_loop - iteration:%(iter_num)d - "
                      "starting polling. Elapsed:%(elapsed).3f",
                      {'iter_num': self.iter_num,
                       'elapsed': time.time() - start})
            try:
                # Save updated ports dict to perform rollback in
                # case resync would be needed, and then clear
                # self.updated_ports. As the greenthread should not yield
                # between these two statements, this will be thread-safe
                updated_ports_copy = self.updated_ports
                self.updated_ports = set()
                port_info = self.scan_ports(ports, updated_ports_copy)
                ports = port_info['current']
                # In the following calling port_info may be updated
                port_status_list = self.ryuapp.get_port_status_list()
                check_ports = self._check_port_status_list(port_status_list,
                                                           port_info)
                LOG.debug("Agent daemon_loop - iteration:%(iter_num)d - "
                          "port information retrieved. "
                          "Elapsed:%(elapsed).3f",
                          {'iter_num': self.iter_num,
                           'elapsed': time.time() - start})
                # Secure and wire/unwire VIFs and update their status
                # on Neutron server
                if (self._port_info_has_changes(port_info) or
                    self.sg_agent.firewall_refresh_needed()):
                    LOG.debug("Starting to process devices in:%s",
                              port_info)
                    # If treat devices fails - must resync with plugin
                    sync = self.process_network_ports(port_info, check_ports)
                    LOG.debug("Agent daemon_loop - "
                              "iteration:%(iter_num)d - "
                              "ports processed. Elapsed:%(elapsed).3f",
                              {'iter_num': self.iter_num,
                               'elapsed': time.time() - start})
                    port_stats['regular']['added'] = (
                        len(port_info.get('added', [])))
                    port_stats['regular']['updated'] = (
                        len(port_info.get('updated', [])))
                    port_stats['regular']['removed'] = (
                        len(port_info.get('removed', [])))
            except Exception:
                LOG.exception(_LE("Error while processing VIF ports"))
                # Put the ports back in self.updated_port
                self.updated_ports |= updated_ports_copy
                sync = True

            # sleep till end of polling interval
            elapsed = (time.time() - start)
            LOG.debug("Agent daemon_loop - iteration:%(iter_num)d "
                      "completed. Processed ports statistics:"
                      "%(port_stats)s. Elapsed:%(elapsed).3f",
                      {'iter_num': self.iter_num,
                       'port_stats': port_stats,
                       'elapsed': elapsed})
            if (elapsed < self.polling_interval):
                time.sleep(self.polling_interval - elapsed)
            else:
                LOG.debug("Loop iteration exceeded interval "
                          "(%(polling_interval)s vs. %(elapsed)s)!",
                          {'polling_interval': self.polling_interval,
                           'elapsed': elapsed})
            self.iter_num = self.iter_num + 1
示例#17
0
    def daemon_loop(self):
        # TODO(yamamoto):
        # It might be better to monitor port status async messages

        sync = True
        ports = set()
        tunnel_sync = True
        while True:
            start = time.time()
            port_stats = {'regular': {'added': 0, 'updated': 0, 'removed': 0}}
            LOG.debug("Agent daemon_loop - iteration:%d started",
                      self.iter_num)
            if sync:
                LOG.info(_LI("Agent out of sync with plugin!"))
                ports.clear()
                sync = False
            # Notify the plugin of tunnel IP
            if self.enable_tunneling and tunnel_sync:
                LOG.info(_LI("Agent tunnel out of sync with plugin!"))
                try:
                    tunnel_sync = self.tunnel_sync()
                except Exception:
                    LOG.exception(_LE("Error while synchronizing tunnels"))
                    tunnel_sync = True
            LOG.debug(
                "Agent daemon_loop - iteration:%(iter_num)d - "
                "starting polling. Elapsed:%(elapsed).3f", {
                    'iter_num': self.iter_num,
                    'elapsed': time.time() - start
                })
            try:
                # Save updated ports dict to perform rollback in
                # case resync would be needed, and then clear
                # self.updated_ports. As the greenthread should not yield
                # between these two statements, this will be thread-safe
                updated_ports_copy = self.updated_ports
                self.updated_ports = set()
                port_info = self.scan_ports(ports, updated_ports_copy)
                ports = port_info['current']
                # In the following calling port_info may be updated
                port_status_list = self.ryuapp.get_port_status_list()
                check_ports = self._check_port_status_list(
                    port_status_list, port_info)
                LOG.debug(
                    "Agent daemon_loop - iteration:%(iter_num)d - "
                    "port information retrieved. "
                    "Elapsed:%(elapsed).3f", {
                        'iter_num': self.iter_num,
                        'elapsed': time.time() - start
                    })
                # Secure and wire/unwire VIFs and update their status
                # on Neutron server
                if (self._port_info_has_changes(port_info)
                        or self.sg_agent.firewall_refresh_needed()):
                    LOG.debug("Starting to process devices in:%s", port_info)
                    # If treat devices fails - must resync with plugin
                    sync = self.process_network_ports(port_info, check_ports)
                    LOG.debug(
                        "Agent daemon_loop - "
                        "iteration:%(iter_num)d - "
                        "ports processed. Elapsed:%(elapsed).3f", {
                            'iter_num': self.iter_num,
                            'elapsed': time.time() - start
                        })
                    port_stats['regular']['added'] = (len(
                        port_info.get('added', [])))
                    port_stats['regular']['updated'] = (len(
                        port_info.get('updated', [])))
                    port_stats['regular']['removed'] = (len(
                        port_info.get('removed', [])))
            except Exception:
                LOG.exception(_LE("Error while processing VIF ports"))
                # Put the ports back in self.updated_port
                self.updated_ports |= updated_ports_copy
                sync = True

            # sleep till end of polling interval
            elapsed = (time.time() - start)
            LOG.debug(
                "Agent daemon_loop - iteration:%(iter_num)d "
                "completed. Processed ports statistics:"
                "%(port_stats)s. Elapsed:%(elapsed).3f", {
                    'iter_num': self.iter_num,
                    'port_stats': port_stats,
                    'elapsed': elapsed
                })
            if (elapsed < self.polling_interval):
                time.sleep(self.polling_interval - elapsed)
            else:
                LOG.debug(
                    "Loop iteration exceeded interval "
                    "(%(polling_interval)s vs. %(elapsed)s)!", {
                        'polling_interval': self.polling_interval,
                        'elapsed': elapsed
                    })
            self.iter_num = self.iter_num + 1