def _process_ucast_macs_remote(self, uuid, uuid_dict, data_dict): """Processes Ucast_Macs_Remote record from the OVSDB event.""" new_row = uuid_dict.get('new', None) old_row = uuid_dict.get('old', None) if new_row: locator_list = new_row.get('locator') locator_id = locator_list[1] logical_switch_list = new_row.get('logical_switch') logical_switch_id = logical_switch_list[1] mac_remote = ovsdb_schema.UcastMacsRemote(uuid, new_row.get('MAC'), logical_switch_id, locator_id, new_row.get('ipaddr')) if old_row: modified_remote_macs = data_dict.get('modified_remote_macs') modified_remote_macs.append(mac_remote) else: new_remote_macs = data_dict.get('new_remote_macs') new_remote_macs.append(mac_remote) elif old_row: logical_switch_list = old_row.get('logical_switch') l_sw_id = logical_switch_list[1] mac_remote = ovsdb_schema.UcastMacsRemote(uuid, old_row.get('MAC'), l_sw_id, None, None) deleted_remote_macs = data_dict.get('deleted_remote_macs') deleted_remote_macs.append(mac_remote)
def update_ucast_macs_remote(self, locator_dict, mac_dict): """Update an entry in Ucast_Macs_Remote OVSDB table.""" # It is possible that the locator may not exist already. locator = ovsdb_schema.PhysicalLocator(locator_dict['uuid'], locator_dict['dst_ip']) macObject = ovsdb_schema.UcastMacsRemote( mac_dict['uuid'], mac_dict['mac'], mac_dict['logical_switch_id'], mac_dict['physical_locator_id'], mac_dict['ip_address']) # Form the insert query now. commit_dict = {"op": "commit", "durable": True} op_id = str(random.getrandbits(128)) params = [n_const.OVSDB_SCHEMA_NAME] # If the physical_locator does not exist (VM moving to a new compute # node), then insert a new record in Physical_Locator first. if locator.uuid: locator_list = ['uuid', locator.uuid] else: locator.uuid = ''.join(['a', str(random.getrandbits(128))]) locator_list = ["named-uuid", locator.uuid] params.append(self._get_physical_locator_dict(locator)) params.append( self._get_dict_for_update_ucast_mac_remote(macObject, locator_list)) params.append(commit_dict) query = {"method": "transact", "params": params, "id": op_id} LOG.debug("update_ucast_macs_remote: query: %s", query) self._send_and_receive(query, op_id)
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 insert_ucast_macs_remote(self, l_switch_dict, locator_dict, mac_dict, ovsdb_identifier, rcv_required=True): """Insert an entry in Ucast_Macs_Remote OVSDB table.""" # To insert an entry in Ucast_Macs_Remote table, it requires # corresponding entry in Physical_Locator (Compute node VTEP IP) # and Logical_Switch (Neutron network) tables. logical_switch = ovsdb_schema.LogicalSwitch(l_switch_dict['uuid'], l_switch_dict['name'], l_switch_dict['key'], l_switch_dict['description' ]) locator = ovsdb_schema.PhysicalLocator(locator_dict['uuid'], locator_dict['dst_ip']) macObject = ovsdb_schema.UcastMacsRemote(mac_dict['uuid'], mac_dict['mac'], mac_dict['logical_switch_id'], mac_dict['physical_locator_id' ], mac_dict['ip_address']) # Form the insert query now. commit_dict = {"op": "commit", "durable": True} op_id = str(random.getrandbits(128)) params = [n_const.OVSDB_SCHEMA_NAME] if locator.uuid: locator_list = ['uuid', locator.uuid] else: locator.uuid = ''.join(['a', str(random.getrandbits(128))]) locator_list = ["named-uuid", locator.uuid] params.append(self._get_physical_locator_dict(locator)) if logical_switch.uuid: l_switches = ['uuid', logical_switch.uuid] else: logical_switch.uuid = ''.join(['a', str(random.getrandbits(128))]) l_switches = ["named-uuid", logical_switch.uuid] params.append(self._get_logical_switch_dict(logical_switch)) params.append(self._get_ucast_macs_remote_dict( macObject, locator_list, l_switches)) params.append(commit_dict) query = {"method": "transact", "params": params, "id": op_id} LOG.debug("insert_ucast_macs_remote: query: %s", query) self._send_and_receive(query, op_id, ovsdb_identifier, rcv_required)
def test_get_bindings_to_update1(self): """Test case to test _get_bindings_to_update.""" fake_op_method = 'CREATE' with mock.patch.object( ovsdb_writer.OVSDBWriter, '_form_logical_switch') as form_ls, \ mock.patch.object( ovsdb_writer.OVSDBWriter, '_form_physical_locators') as form_pl, \ mock.patch.object( ovsdb_writer.OVSDBWriter, '_form_ports') as form_pp, \ mock.patch.object( ovsdb_schema, 'LogicalSwitch') as mock_ls, \ mock.patch.object( ovsdb_schema, 'PhysicalLocator') as mock_pl, \ mock.patch.object( ovsdb_schema, 'UcastMacsRemote') as mock_ucmr, \ mock.patch.object(ovsdb_schema, 'PhysicalPort') as mock_pp: ls = mock_ls.return_value = ovsdb_schema.LogicalSwitch( 'ls_uuid', 'ls_name', 'ls_key', 'ls_desc') pl = mock_pl.return_value = ovsdb_schema.PhysicalLocator( 'pl_uuid', 'pl_dst_ip') mock_ucmr.return_value = ovsdb_schema.UcastMacsRemote( 'ucmr_uuid', 'ucmr_mac', 'ucmr_ls_id', 'ucmr_pl_id', 'ucmr_ip') pp = mock_pp.return_value = ovsdb_schema.PhysicalPort( 'pp_uuid', 'pp_name', 'pp_ps_id', 'pp_vlan_bindings') form_ls.return_value = ['uuid', ls.uuid] self.l2gw_ovsdb._get_bindings_to_update( mock.MagicMock(), [{ 'uuid': 'uuid', 'dst_ip': 'dst_ip' }], mock.MagicMock(), [{ 'uuid': 'uuid', 'name': 'name', 'physical_switch_id': 'physical_switch_id', 'vlan_bindings': 'vlan_bindings', 'port_fault_status': 'port_fault_status' }], fake_op_method) form_ls.assert_called_with(ls, mock.ANY) form_pl.assert_called_with(['uuid', ls.uuid], [pl], mock.ANY, mock.ANY) form_pp.assert_called_with(['uuid', ls.uuid], [pp], mock.ANY, fake_op_method)
def _get_bindings_to_update(self, l_switch_dict, locator_dicts, mac_dicts, port_dicts): # For connection-create, there are two cases to be handled # Case 1: VMs exist in a network on compute nodes. # Connection request will contain locators, ports, MACs and # network. # Case 2: VMs do not exist in a network on compute nodes. # Connection request will contain only ports and network # # For connection-delete, we do not need logical_switch and locators # information, we just need ports. locator_list = [] port_list = [] ls_list = [] logical_switch = None # Convert logical switch dict to a class object if l_switch_dict: logical_switch = ovsdb_schema.LogicalSwitch( l_switch_dict['uuid'], l_switch_dict['name'], l_switch_dict['key'], l_switch_dict['description']) # Convert locator dicts into class objects for locator in locator_dicts: locator_list.append( ovsdb_schema.PhysicalLocator(locator['uuid'], locator['dst_ip'])) # Convert MAC dicts into class objects. mac_dicts is a dictionary with # locator VTEP IP as the key and list of MACs as the value. locator_macs = {} for locator_ip, mac_list in mac_dicts.items(): mac_object_list = [] for mac_dict in mac_list: mac_object = ovsdb_schema.UcastMacsRemote( mac_dict['uuid'], mac_dict['mac'], mac_dict['logical_switch_id'], mac_dict['physical_locator_id'], mac_dict['ip_address']) mac_object_list.append(mac_object) locator_macs[locator_ip] = mac_object_list # Convert port dicts into class objects for port in port_dicts: phys_port = ovsdb_schema.PhysicalPort(port['uuid'], port['name'], port['physical_switch_id'], port['vlan_bindings'], port['port_fault_status']) port_list.append(phys_port) bindings = [] bindings.append(n_const.OVSDB_SCHEMA_NAME) # Form the query. commit_dict = {"op": "commit", "durable": True} params = [n_const.OVSDB_SCHEMA_NAME] # Use logical switch if logical_switch: ls_list = self._form_logical_switch(logical_switch, params) # Use physical locators if locator_list: self._form_physical_locators(ls_list, locator_list, locator_macs, params) # Use ports self._form_ports(ls_list, port_list, params) params.append(commit_dict) return params
def create_l2_gateway_connection(self, context, l2_gateway_connection): """Process the call from the CLI and trigger the RPC, to update the connection to the gateway. """ u_mac_dict = {} ls_dict = {} mac_dict = {} is_mac = False self._admin_check(context, 'CREATE') gw_connection = l2_gateway_connection.get('l2_gateway_connection') # validate connection self._validate_connection(context, gw_connection) # get l2 gateway devices l2gateway_devices = self.get_l2gateway_devices_by_gateway_id( context, gw_connection.get('l2_gateway_id')) for device in l2gateway_devices: locator_list = [] ovsdb_identifier, logical_switch, port_dict = ( self._process_port_list(context, device, gw_connection, "CREATE")) ls_dict = self._get_logical_switch_dict( context, logical_switch, gw_connection) ports = self._get_port_details(context, gw_connection.get('network_id')) if not is_mac: is_mac = True for port in ports: mac_list = [] if port['device_owner']: dst_ip, ip_address = self._get_ip_details(context, port) mac_remote = self._get_dict( ovsdb_schema.UcastMacsRemote( uuid=None, mac=port.get('mac_address'), logical_switch_id=None, physical_locator_id=None, ip_address=ip_address)) if logical_switch: u_mac_dict['mac'] = port.get('mac_address') u_mac_dict['ovsdb_identifier'] = ovsdb_identifier u_mac_dict['logical_switch_uuid'] = ( logical_switch.get('uuid')) ucast_mac_remote = ( db.get_ucast_mac_remote_by_mac_and_ls( context, u_mac_dict)) if not ucast_mac_remote: mac_list.append(mac_remote) else: mac_list.append(mac_remote) locator_list = self._get_locator_list( context, dst_ip, ovsdb_identifier, mac_list, locator_list) for locator in locator_list: mac_dict[locator.get('dst_ip')] = locator.pop('macs') locator.pop('ovsdb_identifier') self.agent_rpc.update_connection_to_gateway( context, ovsdb_identifier, ls_dict, locator_list, mac_dict, port_dict) return super(L2GatewayPlugin, self).create_l2_gateway_connection( context, l2_gateway_connection)
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._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.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 create_l2_gateway_connection(self, context, l2_gateway_connection): """Process the call from the CLI and trigger the RPC, to update the connection to the gateway. """ u_mac_dict = {} ls_dict = {} mac_dict = {} self.service_plugin._admin_check(context, 'CREATE') gw_connection = l2_gateway_connection.get('l2_gateway_connection') # validate connection self._validate_connection(context, gw_connection) # get l2 gateway devices l2gateway_devices = ( self.service_plugin.get_l2gateway_devices_by_gateway_id( context, gw_connection.get('l2_gateway_id'))) for device in l2gateway_devices: locator_list = [] ovsdb_identifier, logical_switch, port_dict = ( self._process_port_list(context, device, gw_connection, "CREATE")) ls_dict = self._get_logical_switch_dict(context, logical_switch, gw_connection) ports = self._get_port_details(context, gw_connection.get('network_id')) for port in ports: mac_list = [] if port['device_owner']: dst_ip, ip_address = self._get_ip_details(context, port) mac_ip_pairs = [] if isinstance(port.get("allowed_address_pairs"), list): for address_pair in port['allowed_address_pairs']: mac = address_pair['mac_address'] mac_ip_pairs.append( (mac, address_pair['ip_address'])) mac_ip_pairs.append((port.get('mac_address'), ip_address)) for mac, ip in mac_ip_pairs: mac_remote = self._get_dict( ovsdb_schema.UcastMacsRemote( uuid=None, mac=mac, logical_switch_id=None, physical_locator_id=None, ip_address=ip)) if logical_switch: u_mac_dict['mac'] = mac u_mac_dict['ovsdb_identifier'] = ovsdb_identifier u_mac_dict['logical_switch_uuid'] = ( logical_switch.get('uuid')) ucast_mac_remote = ( db.get_ucast_mac_remote_by_mac_and_ls( context, u_mac_dict)) if not ucast_mac_remote: mac_list.append(mac_remote) else: mac_list.append(mac_remote) locator_list = self._get_locator_list( context, dst_ip, ovsdb_identifier, mac_list, locator_list) for locator in locator_list: mac_dict[locator.get('dst_ip')] = locator.pop('macs') locator.pop('ovsdb_identifier') self.agent_rpc.update_connection_to_gateway( context, ovsdb_identifier, ls_dict, locator_list, mac_dict, port_dict, 'CREATE')
def update_l2_gateway_postcommit(self, context, l2_gateway): """Process the call from the CLI and trigger the RPC, to update the connection of the gateway. """ self.service_plugin._admin_check(context, 'UPDATE') # get l2 gateway devices l2gateway_devices = ( self.service_plugin.get_l2gateway_devices_by_gateway_id( context, l2_gateway['id'])) # get l2 gateway connections gw_connections = self.service_plugin._get_l2_gateway_connections( context) for gw_connection in gw_connections: u_mac_dict = {} mac_dict = {} for device in l2gateway_devices: locator_list = [] ovsdb_identifier, logical_switch, port_dict = ( self._process_port_list(context, device, gw_connection, "UPDATE")) ls_dict = self._get_logical_switch_dict( context, logical_switch, gw_connection) port_dict_before_update_con = \ [port for port in self.port_dict_before_update if port['vlan_bindings'][0]['logical_switch_uuid'] == logical_switch['uuid']] port_dict_add = \ [port for port in port_dict if port not in port_dict_before_update_con] port_dict_delete = \ [port for port in port_dict_before_update_con if port not in port_dict] if port_dict_add: ports = self._get_port_details( context, gw_connection.get('network_id')) LOG.debug("L2gwRpcDriver.update_l2_gw: ports=%s", ports) for port in ports: mac_list = [] if port['device_owner']: dst_ip, ip_address = self._get_ip_details( context, port) mac_ip_pairs = [] if isinstance(port.get("allowed_address_pairs"), list): for address_pair in \ port['allowed_address_pairs']: mac = address_pair['mac_address'] mac_ip_pairs.append( (mac, address_pair['ip_address'])) mac_ip_pairs.append( (port.get('mac_address'), ip_address)) for mac, ip in mac_ip_pairs: mac_remote = self._get_dict( ovsdb_schema.UcastMacsRemote( uuid=None, mac=mac, logical_switch_id=None, physical_locator_id=None, ip_address=ip)) if logical_switch: u_mac_dict['mac'] = mac u_mac_dict['ovsdb_identifier'] = \ ovsdb_identifier u_mac_dict['logical_switch_uuid'] = ( logical_switch.get('uuid')) ucast_mac_remote = ( db.get_ucast_mac_remote_by_mac_and_ls( context, u_mac_dict)) if not ucast_mac_remote: mac_list.append(mac_remote) else: mac_list.append(mac_remote) locator_list = self._get_locator_list( context, dst_ip, ovsdb_identifier, mac_list, locator_list) for locator in locator_list: mac_dict[locator.get('dst_ip')] = locator.pop('macs') locator.pop('ovsdb_identifier') self.agent_rpc.update_connection_to_gateway( context, ovsdb_identifier, ls_dict, locator_list, mac_dict, port_dict_add, 'CREATE') if port_dict_delete: self.agent_rpc.update_connection_to_gateway( context, ovsdb_identifier, ls_dict, locator_list, mac_dict, port_dict_delete, 'DELETE')