def _get_reply(self, operation_id, ovsdb_identifier): count = 0 while count <= n_const.MAX_RETRIES: response = self._recv_data(ovsdb_identifier) LOG.debug("Response from OVSDB server = %s", str(response)) if response: try: json_m = jsonutils.loads(response) self.responses.append(json_m) method_type = json_m.get('method', None) if method_type == "echo" and self.enable_manager: self.ovsdb_dicts.get(ovsdb_identifier).send( jsonutils.dumps( {"result": json_m.get("params", None), "error": None, "id": json_m['id']})) else: if self._process_response(operation_id): return True except Exception as ex: with excutils.save_and_reraise_exception(): LOG.exception(_LE("Exception while receiving the " "response for the write request:" " [%s]"), ex) count += 1 with excutils.save_and_reraise_exception(): LOG.error(_LE("Could not obtain response from the OVSDB server " "for the request"))
def _get_reply(self, operation_id, ovsdb_identifier): count = 0 while count <= n_const.MAX_RETRIES: response = self._recv_data(ovsdb_identifier) LOG.debug("Response from OVSDB server = %s", str(response)) if response: try: json_m = jsonutils.loads(response) self.responses.append(json_m) method_type = json_m.get('method', None) if method_type == "echo" and self.enable_manager: self.ovsdb_dicts.get(ovsdb_identifier).send( jsonutils.dumps({ "result": json_m.get("params", None), "error": None, "id": json_m['id'] })) else: if self._process_response(operation_id): return True except Exception as ex: with excutils.save_and_reraise_exception(): LOG.exception( _LE("Exception while receiving the " "response for the write request:" " [%s]"), ex) count += 1 with excutils.save_and_reraise_exception(): LOG.error( _LE("Could not obtain response from the OVSDB server " "for the request"))
def _process_ovsdb_host(self, host): try: host_splits = str(host).split(':') ovsdb_identifier = str(host_splits[0]).strip() ovsdb_conf = {n_const.OVSDB_IDENTIFIER: ovsdb_identifier, 'ovsdb_ip': str(host_splits[1]).strip(), 'ovsdb_port': str(host_splits[2]).strip()} priv_key_path = self.conf.ovsdb.l2_gw_agent_priv_key_base_path cert_path = self.conf.ovsdb.l2_gw_agent_cert_base_path ca_cert_path = self.conf.ovsdb.l2_gw_agent_ca_cert_base_path use_ssl = priv_key_path and cert_path and ca_cert_path if use_ssl: ssl_ovsdb = {'use_ssl': True, 'private_key': "/".join([str(priv_key_path), '.'.join([str(host_splits[0]). strip(), 'key'])]), 'certificate': "/".join([str(cert_path), '.'.join([str(host_splits[0]). strip(), 'cert'])]), 'ca_cert': "/".join([str(ca_cert_path), '.'.join([str(host_splits[0]). strip(), 'ca_cert'])]) } ovsdb_conf.update(ssl_ovsdb) LOG.debug("ovsdb_conf = %s", str(ovsdb_conf)) gateway = l2gateway_config.L2GatewayConfig(ovsdb_conf) self.gateways[ovsdb_identifier] = gateway except Exception as ex: LOG.exception(_LE("Exception %(ex)s occurred while processing " "host %(host)s"), {'ex': ex, 'host': host})
def _connect_to_ovsdb_server(self): """Initializes the connection to the OVSDB servers.""" ovsdb_states = {} if self.gateways and self.l2gw_agent_type == n_const.MONITOR: for key in self.gateways.keys(): gateway = self.gateways.get(key) ovsdb_fd = gateway.ovsdb_fd if not (ovsdb_fd and ovsdb_fd.connected): LOG.debug("OVSDB server %s is disconnected", str(gateway.ovsdb_ip)) try: ovsdb_fd = ovsdb_monitor.OVSDBMonitor( self.conf.ovsdb, gateway, self.agent_to_plugin_rpc) except Exception: ovsdb_states[key] = 'disconnected' # Log a warning and continue so that it can be # retried in the next iteration. LOG.error(_LE("OVSDB server %s is not " "reachable"), gateway.ovsdb_ip) # Continue processing the next element in the list. continue gateway.ovsdb_fd = ovsdb_fd try: eventlet.greenthread.spawn_n( ovsdb_fd.set_monitor_response_handler) except Exception: raise SystemExit(Exception.message) if ovsdb_fd and ovsdb_fd.connected: ovsdb_states[key] = 'connected' LOG.debug("Calling notify_ovsdb_states") self.plugin_rpc.notify_ovsdb_states(ctx.get_admin_context(), ovsdb_states)
def create_l2_gateway_connection(self, context, l2_gateway_connection): """Create an L2Gateway Connection Bind a Neutron VXLAN Network to Physical Network Segment. """ self.validate_l2_gateway_connection_for_create( context, l2_gateway_connection) self.driver.create_l2_gateway_connection(context, l2_gateway_connection) with context.session.begin(subtransactions=True): l2_gateway_conn_instance = super( L2GatewayPlugin, self).create_l2_gateway_connection( context, l2_gateway_connection) self.driver.create_l2_gateway_connection_precommit( context, l2_gateway_conn_instance) try: self.driver.create_l2_gateway_connection_postcommit( context, l2_gateway_conn_instance) except exc.L2GatewayServiceDriverError: with excutils.save_and_reraise_exception(): LOG.error(_LE("L2GatewayPlugin." "create_l2_gateway_connection_postcommit " "failed, deleting connection '%s'"), l2_gateway_conn_instance['id']) self.delete_l2_gateway_connection( context, l2_gateway_conn_instance['id']) return l2_gateway_conn_instance
def set_monitor_response_handler(self, addr=None): """Monitor OVSDB tables to receive events for any changes in OVSDB.""" if self.connected: op_id = str(random.getrandbits(128)) props = {'select': {'initial': True, 'insert': True, 'delete': True, 'modify': True}} monitor_message = {'id': op_id, 'method': 'monitor', 'params': [n_const.OVSDB_SCHEMA_NAME, None, {'Logical_Switch': [props], 'Physical_Switch': [props], 'Physical_Port': [props], 'Ucast_Macs_Local': [props], 'Ucast_Macs_Remote': [props], 'Physical_Locator': [props], 'Mcast_Macs_Local': [props], 'Physical_Locator_Set': [props]} ]} self._set_handler("update", self._update_event_handler) if not self.send(monitor_message, addr=addr): # Return so that this will retried in the next iteration return try: response_result = self._process_response(op_id) except exceptions.OVSDBError: with excutils.save_and_reraise_exception(): if self.enable_manager: self.check_monitor_table_thread = False LOG.exception(_LE("Exception while receiving the " "response for the monitor message")) self._process_monitor_msg(response_result, addr)
def _connect_to_ovsdb_server(self): """Initializes the connection to the OVSDB servers.""" ovsdb_states = {} if self.gateways and self.l2gw_agent_type == n_const.MONITOR: for key in self.gateways.keys(): gateway = self.gateways.get(key) ovsdb_fd = gateway.ovsdb_fd if not (ovsdb_fd and ovsdb_fd.connected): LOG.debug("OVSDB server %s is disconnected", str(gateway.ovsdb_ip)) try: ovsdb_fd = ovsdb_monitor.OVSDBMonitor( self.conf.ovsdb, gateway, self.agent_to_plugin_rpc) except Exception: ovsdb_states[key] = 'disconnected' # Log a warning and continue so that it can be # retried in the next iteration. LOG.error(_LE("OVSDB server %s is not " "reachable"), gateway.ovsdb_ip) # Continue processing the next element in the list. continue gateway.ovsdb_fd = ovsdb_fd try: eventlet.greenthread.spawn_n( ovsdb_fd.set_monitor_response_handler) except Exception: raise SystemExit(Exception.message) if ovsdb_fd and ovsdb_fd.connected: ovsdb_states[key] = 'connected' LOG.debug("Calling notify_ovsdb_states") self.plugin_rpc.notify_ovsdb_states(ctx.get_admin_context(), ovsdb_states)
def notify_ovsdb_states(self, context, ovsdb_states): """RPC to notify the OVSDB servers connection state.""" for ovsdb_identifier, state in ovsdb_states.items(): if state == 'connected': pending_recs = db.get_all_pending_remote_macs_in_asc_order( context, ovsdb_identifier) if pending_recs: for pending_mac in pending_recs: logical_switch_uuid = pending_mac['logical_switch_uuid' ] mac = pending_mac['mac'] operation = pending_mac['operation'] try: if operation == 'insert' or operation == 'update': l_switch = ovsdb_schema.LogicalSwitch( logical_switch_uuid, None, None, None) locator_uuid = pending_mac.get( 'locator_uuid', None) dst_ip = pending_mac.get( 'dst_ip', None) locator = ovsdb_schema.PhysicalLocator( locator_uuid, dst_ip) mac_remote = ovsdb_schema.UcastMacsRemote( pending_mac.get('uuid', None), mac, logical_switch_uuid, locator_uuid, pending_mac['vm_ip']) if operation == 'insert': self.agent_rpc.add_vif_to_gateway( context, ovsdb_identifier, l_switch.__dict__, locator.__dict__, mac_remote.__dict__) else: # update operation self.agent_rpc.update_vif_to_gateway( context, ovsdb_identifier, locator.__dict__, mac_remote.__dict__) else: self.agent_rpc.delete_vif_from_gateway( context, ovsdb_identifier, logical_switch_uuid, [mac]) # As the pending operation is over, delete the # record from the pending_ucast_mac_remote table db.delete_pending_ucast_mac_remote( context, operation, ovsdb_identifier, logical_switch_uuid, mac) except Exception as ex: LOG.exception(_LE("Exception occurred = %s"), str(ex))
def _process_monitor_msg(self, message, addr=None): """Process initial set of records in the OVSDB at startup.""" result_dict = message.get('result') data_dict = self._initialize_data_dict() try: self._process_tables(result_dict, data_dict) self.rpc_callback(self._form_ovsdb_data(data_dict, addr)) except Exception as e: LOG.exception(_LE("_process_monitor_msg:ERROR %s "), e)
def _process_monitor_msg(self, message, addr=None): """Process initial set of records in the OVSDB at startup.""" result_dict = message.get('result') data_dict = self._initialize_data_dict() try: self._process_tables(result_dict, data_dict) self.rpc_callback(self._form_ovsdb_data(data_dict, addr)) except Exception as e: LOG.exception(_LE("_process_monitor_msg:ERROR %s "), e)
def _report_state(self): try: ctx = context.get_admin_context_without_session() self.state_rpc.report_state(ctx, self.agent_state, True) self.agent_state['start_flag'] = False except Exception: LOG.exception(_LE("Failed reporting state!")) self.handle_report_state_failure()
def _on_remote_message(self, message, addr=None): """Processes the message received on the socket.""" try: json_m = jsonutils.loads(message) handler_method = json_m.get('method', None) if handler_method: self.handlers.get(handler_method)(json_m, addr) else: self.responses.append(json_m) except Exception as e: LOG.exception(_LE("Exception [%s] while handling " "message"), e)
def _on_remote_message(self, message, addr=None): """Processes the message received on the socket.""" try: json_m = jsonutils.loads(message) handler_method = json_m.get('method', None) if handler_method: self.handlers.get(handler_method)(json_m, addr) else: self.responses.append(json_m) except Exception as e: LOG.exception(_LE("Exception [%s] while handling " "message"), e)
def initialize_thread(self): """Initialization of L2gateway agent scheduler thread.""" try: monitor_thread = loopingcall.FixedIntervalLoopingCall( self.monitor_agent_state) monitor_thread.start( interval=self.monitor_interval, initial_delay=random.randint(self.monitor_interval, self.monitor_interval * 2)) LOG.debug("Successfully initialized L2gateway agent scheduler" " thread with loop interval %s", self.monitor_interval) except Exception: LOG.error(_LE("Cannot initialize agent scheduler thread"))
def _rcv_thread(self): chunks = [] lc = rc = 0 prev_char = None while self.read_on: try: response = self.socket.recv(n_const.BUFFER_SIZE) eventlet.greenthread.sleep(0) if response: response = response.decode('utf8') message_mark = 0 for i, c in enumerate(response): if c == '{' and not (prev_char and prev_char == '\\'): lc += 1 elif c == '}' and not (prev_char and prev_char == '\\'): rc += 1 if rc > lc: raise Exception(_LE("json string not valid")) elif lc == rc and lc is not 0: chunks.append(response[message_mark:i + 1]) message = "".join(chunks) eventlet.greenthread.spawn_n( self._on_remote_message, message) lc = rc = 0 message_mark = i + 1 chunks = [] prev_char = c chunks.append(response[message_mark:]) else: self.read_on = False self.disconnect() except Exception as ex: self.read_on = False self.disconnect() LOG.exception(_LE("Exception [%s] occurred while receiving" "message from the OVSDB server"), ex)
def _rcv_thread(self): chunks = [] lc = rc = 0 prev_char = None while self.read_on: try: response = self.socket.recv(n_const.BUFFER_SIZE) eventlet.greenthread.sleep(0) if response: response = response.decode('utf8') message_mark = 0 for i, c in enumerate(response): if c == '{' and not (prev_char and prev_char == '\\'): lc += 1 elif c == '}' and not (prev_char and prev_char == '\\'): rc += 1 if rc > lc: raise Exception(_LE("json string not valid")) elif lc == rc and lc is not 0: chunks.append(response[message_mark:i + 1]) message = "".join(chunks) eventlet.greenthread.spawn_n( self._on_remote_message, message) lc = rc = 0 message_mark = i + 1 chunks = [] prev_char = c chunks.append(response[message_mark:]) else: self.read_on = False self.disconnect() except Exception as ex: self.read_on = False self.disconnect() LOG.exception( _LE("Exception [%s] occurred while receiving" "message from the OVSDB server"), ex)
def initialize_thread(self): """Initialization of L2gateway agent scheduler thread.""" try: monitor_thread = loopingcall.FixedIntervalLoopingCall( self.monitor_agent_state) monitor_thread.start(interval=self.monitor_interval, initial_delay=random.randint( self.monitor_interval, self.monitor_interval * 2)) LOG.debug( "Successfully initialized L2gateway agent scheduler" " thread with loop interval %s", self.monitor_interval) except Exception: LOG.error(_LE("Cannot initialize agent scheduler thread"))
def delete_l2_gateway(self, context, l2_gateway_id): """Delete the L2Gateway.""" self.validate_l2_gateway_for_delete(context, l2_gateway_id) self.driver.delete_l2_gateway(context, l2_gateway_id) with context.session.begin(subtransactions=True): super(L2GatewayPlugin, self).delete_l2_gateway(context, l2_gateway_id) self.driver.delete_l2_gateway_precommit(context, l2_gateway_id) try: self.driver.delete_l2_gateway_postcommit(context, l2_gateway_id) except exc.L2GatewayServiceDriverError: with excutils.save_and_reraise_exception(): LOG.error(_LE("L2GatewayPlugin.delete_l2_gateway_postcommit" " failed for l2gateway %s"), l2_gateway_id)
def __init__(self, conf, gw_config, mgr=None): self.responses = [] self.connected = False self.mgr = mgr self.enable_manager = cfg.CONF.ovsdb.enable_manager if self.enable_manager: self.manager_table_listening_port = ( cfg.CONF.ovsdb.manager_table_listening_port) self.s = None self.check_c_sock = None self.check_sock_rcv = False self.ovsdb_dicts = {} self.ovsdb_fd_states = {} self.ovsdb_conn_list = [] eventlet.greenthread.spawn(self._rcv_socket) else: self.gw_config = gw_config self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if gw_config.use_ssl: ssl_sock = ssl.wrap_socket( self.socket, server_side=False, keyfile=gw_config.private_key, certfile=gw_config.certificate, cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_TLSv1, ca_certs=gw_config.ca_cert) self.socket = ssl_sock retryCount = 0 while True: try: self.socket.connect((str(gw_config.ovsdb_ip), int(gw_config.ovsdb_port))) break except (socket.error, socket.timeout): LOG.warning(OVSDB_UNREACHABLE_MSG, gw_config.ovsdb_ip) if retryCount == conf.max_connection_retries: # Retried for max_connection_retries times. # Give up and return so that it can be tried in # the next periodic interval. with excutils.save_and_reraise_exception(reraise=True): LOG.exception(_LE("Socket error in connecting to " "the OVSDB server")) else: time.sleep(1) retryCount += 1 # Successfully connected to the socket LOG.debug(OVSDB_CONNECTED_MSG, gw_config.ovsdb_ip) self.connected = True
def notify_ovsdb_states(self, context, ovsdb_states): """RPC to notify the OVSDB servers connection state.""" for ovsdb_identifier, state in ovsdb_states.items(): if state == 'connected': pending_recs = db.get_all_pending_remote_macs_in_asc_order( context, ovsdb_identifier) if pending_recs: for pending_mac in pending_recs: logical_switch_uuid = pending_mac[ 'logical_switch_uuid'] mac = pending_mac['mac'] operation = pending_mac['operation'] try: if operation == 'insert' or operation == 'update': l_switch = ovsdb_schema.LogicalSwitch( logical_switch_uuid, None, None, None) locator_uuid = pending_mac.get( 'locator_uuid', None) dst_ip = pending_mac.get('dst_ip', None) locator = ovsdb_schema.PhysicalLocator( locator_uuid, dst_ip) mac_remote = ovsdb_schema.UcastMacsRemote( pending_mac.get('uuid', None), mac, logical_switch_uuid, locator_uuid, pending_mac['vm_ip']) if operation == 'insert': self.agent_rpc.add_vif_to_gateway( context, ovsdb_identifier, l_switch.__dict__, locator.__dict__, mac_remote.__dict__) else: # update operation self.agent_rpc.update_vif_to_gateway( context, ovsdb_identifier, locator.__dict__, mac_remote.__dict__) else: self.agent_rpc.delete_vif_from_gateway( context, ovsdb_identifier, logical_switch_uuid, [mac]) # As the pending operation is over, delete the # record from the pending_ucast_mac_remote table db.delete_pending_ucast_mac_remote( context, operation, ovsdb_identifier, logical_switch_uuid, mac) except Exception as ex: LOG.exception(_LE("Exception occurred = %s"), str(ex))
def __init__(self, conf, gw_config): self.responses = [] self.connected = False self.enable_manager = cfg.CONF.ovsdb.enable_manager if self.enable_manager: self.s = None self.check_c_sock = None self.check_sock_rcv = False eventlet.greenthread.spawn(self._rcv_socket) self.ovsdb_dicts = {} self.ovsdb_fd_states = {} else: self.gw_config = gw_config self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if gw_config.use_ssl: ssl_sock = ssl.wrap_socket(self.socket, server_side=False, keyfile=gw_config.private_key, certfile=gw_config.certificate, cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_TLSv1, ca_certs=gw_config.ca_cert) self.socket = ssl_sock retryCount = 0 while True: try: self.socket.connect( (str(gw_config.ovsdb_ip), int(gw_config.ovsdb_port))) break except (socket.error, socket.timeout): LOG.warning(OVSDB_UNREACHABLE_MSG, gw_config.ovsdb_ip) if retryCount == conf.max_connection_retries: # Retried for max_connection_retries times. # Give up and return so that it can be tried in # the next periodic interval. with excutils.save_and_reraise_exception(reraise=True): LOG.exception( _LE("Socket error in connecting to " "the OVSDB server")) else: time.sleep(1) retryCount += 1 # Successfully connected to the socket LOG.debug(OVSDB_CONNECTED_MSG, gw_config.ovsdb_ip) self.connected = True
def _process_ovsdb_host(self, host): try: host_splits = str(host).split(':') ovsdb_identifier = str(host_splits[0]).strip() ovsdb_conf = { n_const.OVSDB_IDENTIFIER: ovsdb_identifier, 'ovsdb_ip': str(host_splits[1]).strip(), 'ovsdb_port': str(host_splits[2]).strip() } priv_key_path = self.conf.ovsdb.l2_gw_agent_priv_key_base_path cert_path = self.conf.ovsdb.l2_gw_agent_cert_base_path ca_cert_path = self.conf.ovsdb.l2_gw_agent_ca_cert_base_path use_ssl = priv_key_path and cert_path and ca_cert_path if use_ssl: ssl_ovsdb = { 'use_ssl': True, 'private_key': "/".join([ str(priv_key_path), '.'.join([str(host_splits[0]).strip(), 'key']) ]), 'certificate': "/".join([ str(cert_path), '.'.join([str(host_splits[0]).strip(), 'cert']) ]), 'ca_cert': "/".join([ str(ca_cert_path), '.'.join([str(host_splits[0]).strip(), 'ca_cert']) ]) } ovsdb_conf.update(ssl_ovsdb) LOG.debug("ovsdb_conf = %s", str(ovsdb_conf)) gateway = l2gateway_config.L2GatewayConfig(ovsdb_conf) self.gateways[ovsdb_identifier] = gateway except Exception as ex: LOG.exception( _LE("Exception %(ex)s occurred while processing " "host %(host)s"), { 'ex': ex, 'host': host })
def set_monitor_response_handler(self, addr=None): """Monitor OVSDB tables to receive events for any changes in OVSDB.""" if self.connected: op_id = str(random.getrandbits(128)) props = { 'select': { 'initial': True, 'insert': True, 'delete': True, 'modify': True } } monitor_message = { 'id': op_id, 'method': 'monitor', 'params': [ n_const.OVSDB_SCHEMA_NAME, None, { 'Logical_Switch': [props], 'Physical_Switch': [props], 'Physical_Port': [props], 'Ucast_Macs_Local': [props], 'Ucast_Macs_Remote': [props], 'Physical_Locator': [props], 'Mcast_Macs_Local': [props], 'Physical_Locator_Set': [props] } ] } self._set_handler("update", self._update_event_handler) if not self.send(monitor_message, addr=addr): # Return so that this will retried in the next iteration return try: response_result = self._process_response(op_id) except exceptions.OVSDBError: with excutils.save_and_reraise_exception(): if self.enable_manager: self.check_monitor_table_thread = False LOG.exception( _LE("Exception while receiving the " "response for the monitor message")) self._process_monitor_msg(response_result, addr)
def update_l2_gateway(self, context, l2_gateway_id, l2_gateway): """Update the L2Gateway.""" self.validate_l2_gateway_for_update(context, l2_gateway_id, l2_gateway) self.driver.update_l2_gateway(context, l2_gateway_id, l2_gateway) with context.session.begin(subtransactions=True): l2_gateway_instance = super(L2GatewayPlugin, self).update_l2_gateway(context, l2_gateway_id, l2_gateway) self.driver.update_l2_gateway_precommit(context, l2_gateway_instance) try: self.driver.update_l2_gateway_postcommit( context, l2_gateway_instance) except exc.L2GatewayServiceDriverError: with excutils.save_and_reraise_exception(): LOG.error(_LE("L2GatewayPlugin.update_l2_gateway_postcommit" " failed for l2gateway %s"), l2_gateway_id) return l2_gateway_instance
def _common_sock_rcv_thread(self, addr): chunks = [] lc = rc = 0 prev_char = None self.read_on = True check_monitor_msg = True self._echo_response(addr) if self.enable_manager and (addr in self.ovsdb_conn_list): while self.read_on: response = self.ovsdb_dicts.get(addr).recv(n_const.BUFFER_SIZE) self.ovsdb_fd_states[addr] = 'connected' self.check_sock_rcv = True eventlet.greenthread.sleep(0) if check_monitor_msg: self._send_monitor_msg_to_ovsdb_connection(addr) check_monitor_msg = False if response: response = response.decode('utf8') message_mark = 0 for i, c in enumerate(response): if c == '{' and not (prev_char and prev_char == '\\'): lc += 1 elif c == '}' and not (prev_char and prev_char == '\\'): rc += 1 if rc > lc: raise Exception(_LE("json string not valid")) elif lc == rc and lc is not 0: chunks.append(response[message_mark:i + 1]) message = "".join(chunks) eventlet.greenthread.spawn_n( self._on_remote_message, message, addr) eventlet.greenthread.sleep(0) lc = rc = 0 message_mark = i + 1 chunks = [] prev_char = c chunks.append(response[message_mark:]) else: self.read_on = False self.disconnect(addr)
def create_l2_gateway(self, context, l2_gateway): """Create the L2Gateway.""" self.validate_l2_gateway_for_create(context, l2_gateway) self.driver.create_l2_gateway(context, l2_gateway) with context.session.begin(subtransactions=True): l2_gateway_instance = super(L2GatewayPlugin, self).create_l2_gateway(context, l2_gateway) self.driver.create_l2_gateway_precommit(context, l2_gateway_instance) try: self.driver.create_l2_gateway_postcommit( context, l2_gateway_instance) except exc.L2GatewayServiceDriverError: with excutils.save_and_reraise_exception(): LOG.error(_LE("L2GatewayPlugin.create_l2_gateway_postcommit " "failed, deleting l2gateway '%s'"), l2_gateway_instance['id']) self.delete_l2_gateway(context, l2_gateway_instance['id']) return l2_gateway_instance
def delete_l2_gateway_connection(self, context, l2_gateway_connection_id): """Delete an L2Gateway Connection Unbind a Neutron VXLAN Network from Physical Network Segment. """ self.validate_l2_gateway_connection_for_delete( context, l2_gateway_connection_id) self.driver.delete_l2_gateway_connection( context, l2_gateway_connection_id) with context.session.begin(subtransactions=True): super(L2GatewayPlugin, self).delete_l2_gateway_connection( context, l2_gateway_connection_id) self.driver.delete_l2_gateway_connection_precommit( context, l2_gateway_connection_id) try: self.driver.delete_l2_gateway_connection_postcommit( context, l2_gateway_connection_id) except exc.L2GatewayServiceDriverError: with excutils.save_and_reraise_exception(): LOG.error(_LE( "L2GatewayPlugin.delete_l2_gateway_connection_postcommit" " failed for connection %s"), l2_gateway_connection_id)
def _common_sock_rcv_thread(self, addr): chunks = [] lc = rc = 0 prev_char = None self._echo_response(addr) if self.enable_manager and self.check_c_sock: while self.read_on: response = self.ovsdb_dicts.get(addr).recv(n_const.BUFFER_SIZE) self.ovsdb_fd_states[addr] = 'connected' eventlet.greenthread.sleep(0) self.check_sock_rcv = True if response: response = response.decode('utf8') message_mark = 0 for i, c in enumerate(response): if c == '{' and not (prev_char and prev_char == '\\'): lc += 1 elif c == '}' and not (prev_char and prev_char == '\\'): rc += 1 if rc > lc: raise Exception(_LE("json string not valid")) elif lc == rc and lc is not 0: chunks.append(response[message_mark:i + 1]) message = "".join(chunks) eventlet.greenthread.spawn_n( self._on_remote_message, message, addr) eventlet.greenthread.sleep(0) lc = rc = 0 message_mark = i + 1 chunks = [] prev_char = c chunks.append(response[message_mark:]) else: self.read_on = False self.disconnect(addr) self.ovsdb_fd_states[addr] = 'disconnected'
def send(self, message, callback=None, addr=None): """Sends a message to the OVSDB server.""" if callback: self.callbacks[message['id']] = callback retry_count = 0 bytes_sent = 0 while retry_count <= n_const.MAX_RETRIES: try: if self.enable_manager: bytes_sent = self.ovsdb_dicts.get(addr).send( jsonutils.dumps(message)) else: bytes_sent = self.socket.send(jsonutils.dumps(message)) if bytes_sent: return True except Exception as ex: LOG.exception(_LE("Exception [%s] occurred while sending " "message to the OVSDB server"), ex) retry_count += 1 LOG.warning(_LW("Could not send message to the " "OVSDB server.")) self.disconnect(addr) return False
def send(self, message, callback=None, addr=None): """Sends a message to the OVSDB server.""" if callback: self.callbacks[message['id']] = callback retry_count = 0 bytes_sent = 0 while retry_count <= n_const.MAX_RETRIES: try: if self.enable_manager: bytes_sent = self.ovsdb_dicts.get(addr).send( jsonutils.dumps(message)) else: bytes_sent = self.socket.send(jsonutils.dumps(message)) if bytes_sent: return True except Exception as ex: LOG.exception( _LE("Exception [%s] occurred while sending " "message to the OVSDB server"), ex) retry_count += 1 LOG.warning(_LW("Could not send message to the " "OVSDB server.")) self.disconnect(addr) return False
def monitor_agent_state(self): """Represents L2gateway agent scheduler thread. Maintains list of active and inactive agents based on the heartbeat recorded. """ context = neutron_context.get_admin_context() try: all_agents = self.plugin.get_agents( context, filters={'agent_type': [srv_const.AGENT_TYPE_L2GATEWAY]}) except Exception: LOG.exception(_LE("Unable to get the agent list. Continuing...")) return # Reset the agents that will be processed for selecting the # Monitor agent agents_to_process = [] for agent in all_agents: if not self.is_agent_down(agent['heartbeat_timestamp']): agents_to_process.append(agent) if agents_to_process: self._select_agent_type(context, agents_to_process) return
def monitor_agent_state(self): """Represents L2gateway agent scheduler thread. Maintains list of active and inactive agents based on the heartbeat recorded. """ context = neutron_context.get_admin_context() try: all_agents = self.plugin.get_agents( context, filters={'agent_type': [srv_const.AGENT_TYPE_L2GATEWAY]}) except Exception: LOG.exception(_LE("Unable to get the agent list. Continuing...")) return # Reset the agents that will be processed for selecting the # Monitor agent agents_to_process = [] for agent in all_agents: if not self.is_agent_down(agent['heartbeat_timestamp']): agents_to_process.append(agent) if agents_to_process: self._select_agent_type(context, agents_to_process) return
def delete_port_mac(self, context, port): """Process the deleted port and trigger the RPC to delete from the gateway. When the ML2 plugin invokes this call, the argument port is a single port dict, whereas the L2gateway service plugin sends it as a list of port dicts. """ ls_dict = {} mac_list = [] logical_switches = [] ovsdb_identifier = None if isinstance(port, list): from_l2gw_plugin = True network_id = port[0].get('network_id') ovsdb_identifier = port[0].get('ovsdb_identifier') lg_dict = { 'logical_switch_name': network_id, 'ovsdb_identifier': ovsdb_identifier } logical_switch = db.get_logical_switch_by_name(context, lg_dict) logical_switches.append(logical_switch) port_list = port else: from_l2gw_plugin = False network_id = port.get('network_id') logical_switches = (db.get_all_logical_switches_by_name( context, network_id)) l2gateway_connections = ( self.service_plugin.get_l2_gateway_connections( context, filters={'network_id': [network_id]})) if not l2gateway_connections: return port_list = [port] for port_dict in port_list: if port_dict['device_owner']: if logical_switches: for logical_switch in logical_switches: logical_switch_uuid = logical_switch.get('uuid') mac = port_dict.get("mac_address") if port_dict.get('ovsdb_identifier', None): ovsdb_identifier = port_dict.get( 'ovsdb_identifier') else: ovsdb_identifier = logical_switch.get( 'ovsdb_identifier') record_dict = { 'mac': mac, 'logical_switch_uuid': logical_switch_uuid, 'ovsdb_identifier': ovsdb_identifier } rec_dict = { 'logical_switch_id': logical_switch_uuid, 'ovsdb_identifier': ovsdb_identifier } if len( db.get_all_vlan_bindings_by_logical_switch( context, rec_dict)) > 1: if from_l2gw_plugin: ls = logical_switch.get('name') l2gateway_connections = ( self.service_plugin. get_l2_gateway_connections( context, filters={'network_id': [ls]})) if len(l2gateway_connections) > 1: continue ucast_mac_remote = ( db.get_ucast_mac_remote_by_mac_and_ls( context, record_dict)) del_count = 0 if not ucast_mac_remote: LOG.debug( "delete_port_mac: MAC %s does" " not exist", mac) # It is possible that this MAC is present # in the pending_ucast_mac_remote table. # Delete this MAC as it was not inserted # into the OVSDB server earlier. del_count = db.delete_pending_ucast_mac_remote( context, 'insert', ovsdb_identifier, logical_switch_uuid, mac) if not del_count: mac_list = ls_dict.get(logical_switch_uuid, []) mac_list.append(mac) ls_dict[logical_switch_uuid] = mac_list else: LOG.debug( "delete_port_mac:Logical Switch %s " "does not exist ", port_dict.get('network_id')) return for logical_switch_uuid, mac_list in ls_dict.items(): try: if mac_list: self.agent_rpc.delete_vif_from_gateway( context, ovsdb_identifier, logical_switch_uuid, mac_list) except messaging.MessagingTimeout: # If RPC is timed out, then the RabbitMQ # will retry the operation. LOG.exception( _LE("Communication error with " "the L2 gateway agent")) except Exception as ex: # The remote OVSDB server may be down. # We need to retry this operation later. LOG.debug("Exception occurred %s", str(ex)) db.add_pending_ucast_mac_remote(context, 'delete', ovsdb_identifier, logical_switch_uuid, None, mac_list)
def add_port_mac(self, context, port_dict): """Process the created port and trigger the RPC to add to the gateway. """ port_id = port_dict.get("id") port = self.service_plugin._core_plugin.get_port(context, port_id) if port['device_owner']: network_id = port.get("network_id") dst_ip, ip_address = self._get_ip_details(context, port) network = self._get_network_details(context, network_id) l2gateway_connections = ( self.service_plugin.get_l2_gateway_connections( context, filters={'network_id': [network_id]})) if not l2gateway_connections: return logical_switches = db.get_all_logical_switches_by_name( context, network_id) if not logical_switches: return for logical_switch in logical_switches: logical_switch['description'] = network.get('name') ovsdb_identifier = logical_switch.get('ovsdb_identifier') locator_dict = { 'dst_ip': dst_ip, 'ovsdb_identifier': ovsdb_identifier } physical_locator = self._form_physical_locator_schema( context, locator_dict) locator_uuid = physical_locator.get('uuid') logical_switch_uuid = logical_switch.get('uuid') mac_remote = self._get_dict( ovsdb_schema.UcastMacsRemote( uuid=None, mac=port['mac_address'], logical_switch_id=logical_switch_uuid, physical_locator_id=locator_uuid, ip_address=ip_address)) mac_dict = mac_remote mac_dict['ovsdb_identifier'] = ovsdb_identifier mac_dict['logical_switch_uuid'] = logical_switch_uuid ucast_mac_remote = db.get_ucast_mac_remote_by_mac_and_ls( context, mac_dict) if ucast_mac_remote: # check whether locator got changed in vm migration if ucast_mac_remote[ 'physical_locator_id'] != physical_locator['uuid']: mac_remote['uuid'] = ucast_mac_remote['uuid'] try: self.agent_rpc.update_vif_to_gateway( context, ovsdb_identifier, physical_locator, mac_remote) LOG.debug( "VM migrated from %s to %s. Update" "locator in Ucast_Macs_Remote", ucast_mac_remote['physical_locator_id'], physical_locator['uuid']) except messaging.MessagingTimeout: # If RPC is timed out, then the RabbitMQ # will retry the operation. LOG.exception( _LE("Communication error with " "the L2 gateway agent")) except Exception: # The remote OVSDB server may be down. # We need to retry this operation later. db.add_pending_ucast_mac_remote( context, 'update', ovsdb_identifier, logical_switch_uuid, physical_locator, [mac_remote]) else: LOG.debug("add_port_mac: MAC %s exists " "in Gateway", mac_dict['mac']) ovsdb_data_handler = ( self.ovsdb_callback.get_ovsdbdata_object( ovsdb_identifier)) ovsdb_data_handler._handle_l2pop( context, [ucast_mac_remote]) continue # else it is a new port created try: self.agent_rpc.add_vif_to_gateway(context, ovsdb_identifier, logical_switch, physical_locator, mac_remote) except messaging.MessagingTimeout: # If RPC is timed out, then the RabbitMQ # will retry the operation. LOG.exception( _LE("Communication error with " "the L2 gateway agent")) except Exception: # The remote OVSDB server may be down. # We need to retry this operation later. LOG.debug("The remote OVSDB server may be down") db.add_pending_ucast_mac_remote(context, 'insert', ovsdb_identifier, logical_switch_uuid, physical_locator, [mac_remote])
def _get_driver_for_provider(self, provider): if provider in self.drivers: return self.drivers[provider] # raise if not associated (should never be reached) raise n_exc.Invalid(_LE("Error retrieving driver for provider %s") % provider)
def add_port_mac(self, context, port_dict): """Process the created port and trigger the RPC to add to the gateway. """ port_id = port_dict.get("id") port = self.service_plugin._core_plugin.get_port(context, port_id) if port['device_owner']: network_id = port.get("network_id") dst_ip, ip_address = self._get_ip_details(context, port) network = self._get_network_details(context, network_id) l2gateway_connections = ( self.service_plugin.get_l2_gateway_connections( context, filters={'network_id': [network_id]})) if not l2gateway_connections: return logical_switches = db.get_all_logical_switches_by_name(context, network_id) if not logical_switches: return for logical_switch in logical_switches: logical_switch['description'] = network.get('name') ovsdb_identifier = logical_switch.get('ovsdb_identifier') locator_dict = {'dst_ip': dst_ip, 'ovsdb_identifier': ovsdb_identifier} physical_locator = self._form_physical_locator_schema( context, locator_dict) locator_uuid = physical_locator.get('uuid') logical_switch_uuid = logical_switch.get('uuid') mac_remote = self._get_dict(ovsdb_schema.UcastMacsRemote( uuid=None, mac=port['mac_address'], logical_switch_id=logical_switch_uuid, physical_locator_id=locator_uuid, ip_address=ip_address)) mac_dict = mac_remote mac_dict['ovsdb_identifier'] = ovsdb_identifier mac_dict['logical_switch_uuid'] = logical_switch_uuid ucast_mac_remote = db.get_ucast_mac_remote_by_mac_and_ls( context, mac_dict) if ucast_mac_remote: # check whether locator got changed in vm migration if ucast_mac_remote['physical_locator_id' ] != physical_locator['uuid']: mac_remote['uuid'] = ucast_mac_remote['uuid'] try: self.agent_rpc.update_vif_to_gateway( context, ovsdb_identifier, physical_locator, mac_remote) LOG.debug( "VM migrated from %s to %s. Update" "locator in Ucast_Macs_Remote", ucast_mac_remote['physical_locator_id'], physical_locator['uuid']) except messaging.MessagingTimeout: # If RPC is timed out, then the RabbitMQ # will retry the operation. LOG.exception(_LE("Communication error with " "the L2 gateway agent")) except Exception: # The remote OVSDB server may be down. # We need to retry this operation later. db.add_pending_ucast_mac_remote( context, 'update', ovsdb_identifier, logical_switch_uuid, physical_locator, [mac_remote]) else: LOG.debug("add_port_mac: MAC %s exists " "in Gateway", mac_dict['mac']) ovsdb_data_handler = ( self.ovsdb_callback.get_ovsdbdata_object( ovsdb_identifier)) ovsdb_data_handler._handle_l2pop( context, [ucast_mac_remote]) continue # else it is a new port created try: self.agent_rpc.add_vif_to_gateway( context, ovsdb_identifier, logical_switch, physical_locator, mac_remote) except messaging.MessagingTimeout: # If RPC is timed out, then the RabbitMQ # will retry the operation. LOG.exception(_LE("Communication error with " "the L2 gateway agent")) except Exception: # The remote OVSDB server may be down. # We need to retry this operation later. LOG.debug("The remote OVSDB server may be down") db.add_pending_ucast_mac_remote( context, 'insert', ovsdb_identifier, logical_switch_uuid, physical_locator, [mac_remote])
def delete_port_mac(self, context, port): """Process the deleted port and trigger the RPC to delete from the gateway. When the ML2 plugin invokes this call, the argument port is a single port dict, whereas the L2gateway service plugin sends it as a list of port dicts. """ ls_dict = {} mac_list = [] logical_switches = [] ovsdb_identifier = None if isinstance(port, list): from_l2gw_plugin = True network_id = port[0].get('network_id') ovsdb_identifier = port[0].get('ovsdb_identifier') lg_dict = {'logical_switch_name': network_id, 'ovsdb_identifier': ovsdb_identifier} logical_switch = db.get_logical_switch_by_name( context, lg_dict) logical_switches.append(logical_switch) port_list = port else: from_l2gw_plugin = False network_id = port.get('network_id') logical_switches = ( db.get_all_logical_switches_by_name( context, network_id)) l2gateway_connections = ( self.service_plugin.get_l2_gateway_connections( context, filters={'network_id': [network_id]})) if not l2gateway_connections: return port_list = [port] for port_dict in port_list: if port_dict['device_owner']: if logical_switches: for logical_switch in logical_switches: logical_switch_uuid = logical_switch.get('uuid') mac = port_dict.get("mac_address") if port_dict.get('ovsdb_identifier', None): ovsdb_identifier = port_dict.get( 'ovsdb_identifier') else: ovsdb_identifier = logical_switch.get( 'ovsdb_identifier') record_dict = {'mac': mac, 'logical_switch_uuid': logical_switch_uuid, 'ovsdb_identifier': ovsdb_identifier} rec_dict = {'logical_switch_id': logical_switch_uuid, 'ovsdb_identifier': ovsdb_identifier} if len(db.get_all_vlan_bindings_by_logical_switch( context, rec_dict)) > 1: if from_l2gw_plugin: ls = logical_switch.get('name') l2gateway_connections = ( self.service_plugin. get_l2_gateway_connections( context, filters={'network_id': [ls]})) if len(l2gateway_connections) > 1: continue ucast_mac_remote = ( db.get_ucast_mac_remote_by_mac_and_ls( context, record_dict)) del_count = 0 if not ucast_mac_remote: LOG.debug("delete_port_mac: MAC %s does" " not exist", mac) # It is possible that this MAC is present # in the pending_ucast_mac_remote table. # Delete this MAC as it was not inserted # into the OVSDB server earlier. del_count = db.delete_pending_ucast_mac_remote( context, 'insert', ovsdb_identifier, logical_switch_uuid, mac) if not del_count: mac_list = ls_dict.get(logical_switch_uuid, []) mac_list.append(mac) ls_dict[logical_switch_uuid] = mac_list else: LOG.debug("delete_port_mac:Logical Switch %s " "does not exist ", port_dict.get('network_id')) return for logical_switch_uuid, mac_list in ls_dict.items(): try: if mac_list: self.agent_rpc.delete_vif_from_gateway(context, ovsdb_identifier, logical_switch_uuid, mac_list) except messaging.MessagingTimeout: # If RPC is timed out, then the RabbitMQ # will retry the operation. LOG.exception(_LE("Communication error with " "the L2 gateway agent")) except Exception as ex: # The remote OVSDB server may be down. # We need to retry this operation later. LOG.debug("Exception occurred %s", str(ex)) db.add_pending_ucast_mac_remote( context, 'delete', ovsdb_identifier, logical_switch_uuid, None, mac_list)
def _get_driver_for_provider(self, provider): if provider in self.drivers: return self.drivers[provider] # raise if not associated (should never be reached) raise n_exc.Invalid( _LE("Error retrieving driver for provider %s") % provider)