def __init__(self, hostconf_uri=None, db_plugin=None): """Initialization.""" LOG.debug("Initializing ODL Port Binding Controller") if not hostconf_uri: # extract host/port from ODL URL and append hostconf_uri path hostconf_uri = self._make_hostconf_uri( cfg.CONF.ml2_odl.url, cfg.CONF.ml2_odl.odl_hostconf_uri) LOG.debug("ODLPORTBINDING hostconfigs URI: %s", hostconf_uri) # TODO(mzmalick): disable port-binding for ODL lightweight testing self.odl_rest_client = odl_client.OpenDaylightRestClient.create_client( url=hostconf_uri) # Neutron DB plugin instance self.agents_db = db_plugin self._known_agents = set() if cfg.CONF.ml2_odl.enable_websocket_pseudo_agentdb: # Update hostconfig once for the configurations already present self._get_and_update_hostconfigs() odl_url = utils.get_odl_url() self._start_websocket(odl_url) else: # Start polling ODL restconf using maintenance thread. # default: 30s (should be <= agent keep-alive poll interval) self._start_maintenance_thread( cfg.CONF.ml2_odl.restconf_poll_interval)
def __init__(self, worker): super(PseudoAgentDBBindingWebSocket, self).__init__(worker) # Update hostconfig once for the configurations already present self._get_and_update_hostconfigs() odl_url = utils.get_odl_url() self._start_websocket(odl_url)
def _pull_missed_statuses(self): LOG.debug("starting to pull pending statuses...") plugin = directory.get_plugin() filter = { "status": [n_const.PORT_STATUS_DOWN], "vif_type": ["unbound"] } ports = plugin.get_ports(context.get_admin_context(), filter) if not ports: LOG.debug("no down ports found, done") return port_fetch_url = utils.get_odl_url(self.PORT_PATH) client = odl_client.OpenDaylightRestClient.create_client( url=port_fetch_url) for port in ports: id = port["id"] response = client.get(id) if response.status_code != 200: LOG.warning("Non-200 response code %s", str(response)) continue odl_status = response.json()['port'][0]['status'] if odl_status == n_const.PORT_STATUS_ACTIVE: # for now we only support transition from DOWN->ACTIVE # See https://bugs.launchpad.net/networking-odl/+bug/1686023 provisioning_blocks.provisioning_complete( context.get_admin_context(), id, resources.PORT, provisioning_blocks.L2_AGENT_ENTITY) LOG.debug("done pulling pending statuses")
def __init__(self, worker): super(PseudoAgentDBBindingWebSocket, self).__init__(worker) # Update hostconfig once for the configurations already present self._get_and_update_hostconfigs() odl_url = utils.get_odl_url() self._start_websocket(odl_url)
def _fetch_features(): '''Fetch the list of features declared by ODL. This function should be called once during initialization ''' path = 'restconf/operational/neutron:neutron/neutron:features' features_url = utils.get_odl_url(path) client = odl_client.OpenDaylightRestClient.create_client(features_url) try: response = client.request('get') except exceptions.ConnectionError: LOG.error("Error connecting to ODL to retrieve features", exc_info=True) return None if response.status_code == 400: LOG.debug('ODL does not support feature negotiation') return set() if response.status_code == 404: LOG.debug('No features configured') return set() if response.status_code != 200: LOG.warning('error fetching features: %i', response.status_code) return None return _load_features(response.json())
def _fetch_features(): '''Fetch the list of features declared by ODL. This function should be called once during initialization ''' path = 'restconf/operational/neutron:neutron/neutron:features' features_url = utils.get_odl_url(path) client = odl_client.OpenDaylightRestClient.create_client(features_url) try: response = client.request('get') except exceptions.ConnectionError: LOG.error("Error connecting to ODL to retrieve features", exc_info=True) return None if response.status_code == 400: LOG.debug('ODL does not support feature negotiation') return copy.copy(EMPTY_FEATURES) if response.status_code == 404: LOG.debug('No features configured') return copy.copy(EMPTY_FEATURES) if response.status_code != 200: LOG.warning('error fetching features: %i', response.status_code) return None return _load_features(response.json())
def _pull_missed_statuses(self): LOG.debug("starting to pull pending statuses...") plugin = directory.get_plugin() filter = {"status": [n_const.PORT_STATUS_DOWN], "vif_type": ["unbound"]} ports = plugin.get_ports(context.get_admin_context(), filter) if not ports: LOG.debug("no down ports found, done") return port_fetch_url = utils.get_odl_url(self.PORT_PATH) client = odl_client.OpenDaylightRestClient.create_client( url=port_fetch_url) for port in ports: port_id = port["id"] response = client.get(port_id) if response.status_code != 200: LOG.warning("Non-200 response code %s", str(response)) continue odl_status = response.json()['port'][0]['status'] if odl_status == n_const.PORT_STATUS_ACTIVE: # for now we only support transition from DOWN->ACTIVE # See https://bugs.launchpad.net/networking-odl/+bug/1686023 provisioning_blocks.provisioning_complete( context.get_admin_context(), port_id, resources.PORT, provisioning_blocks.L2_AGENT_ENTITY) LOG.debug("done pulling pending statuses")
def test_get_odl_url(self): """test make uri.""" self.cfg.config(url='http://localhost:8080/controller/nb/v2/neutron', group='ml2_odl') test_path = '/restconf/neutron:neutron/hostconfigs' expected = "http://localhost:8080/restconf/neutron:neutron/hostconfigs" test_uri = utils.get_odl_url(path=test_path) self.assertEqual(expected, test_uri)
def test_get_odl_url(self): """test make uri.""" self.cfg.config(url='http://localhost:8080/controller/nb/v2/neutron', group='ml2_odl') test_path = '/restconf/neutron:neutron/hostconfigs' expected = "http://localhost:8080/restconf/neutron:neutron/hostconfigs" test_uri = utils.get_odl_url(path=test_path) self.assertEqual(expected, test_uri)
def test_get_odl_url(self): """test make uri.""" cfg.CONF.set_override( 'url', 'http://localhost:8080' '/controller/nb/v2/neutron', 'ml2_odl') test_path = '/restconf/neutron:neutron/hostconfigs' expected = "http://localhost:8080/restconf/neutron:neutron/hostconfigs" test_uri = utils.get_odl_url(path=test_path) self.assertEqual(expected, test_uri)
def __init__(self, worker): super(PseudoAgentDBBindingTaskBase, self).__init__() self._worker = worker # extract host/port from ODL URL and append hostconf_uri path hostconf_uri = utils.get_odl_url(cfg.CONF.ml2_odl.odl_hostconf_uri) LOG.debug("ODLPORTBINDING hostconfigs URI: %s", hostconf_uri) # TODO(mzmalick): disable port-binding for ODL lightweight testing self.odl_rest_client = odl_client.OpenDaylightRestClient.create_client( url=hostconf_uri)
def __init__(self, worker): super(PseudoAgentDBBindingTaskBase, self).__init__() self._worker = worker # extract host/port from ODL URL and append hostconf_uri path hostconf_uri = utils.get_odl_url(cfg.CONF.ml2_odl.odl_hostconf_uri) LOG.debug("ODLPORTBINDING hostconfigs URI: %s", hostconf_uri) # TODO(mzmalick): disable port-binding for ODL lightweight testing self.odl_rest_client = odl_client.OpenDaylightRestClient.create_client( url=hostconf_uri)
def run_websocket(self): # OpenDaylight path to recieve websocket notifications on neutron_ports_path = "/neutron:neutron/neutron:ports" self.path_uri = utils.get_odl_url() self.odl_websocket_client = ( odl_ws_client.OpenDaylightWebsocketClient.odl_create_websocket( self.path_uri, neutron_ports_path, odl_ws_client.ODL_OPERATIONAL_DATASTORE, odl_ws_client.ODL_NOTIFICATION_SCOPE_SUBTREE, self._process_websocket_recv, self._process_websocket_reconnect, True))
def run_websocket(self): # OpenDaylight path to recieve websocket notifications on neutron_ports_path = "/neutron:neutron/neutron:ports" self.path_uri = utils.get_odl_url() self.odl_websocket_client = ( odl_ws_client.OpenDaylightWebsocketClient.odl_create_websocket( self.path_uri, neutron_ports_path, odl_ws_client.ODL_OPERATIONAL_DATASTORE, odl_ws_client.ODL_NOTIFICATION_SCOPE_SUBTREE, self._process_websocket_recv, self._process_websocket_reconnect, True ))