diff --git a/opensync-ext-cloud/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/OpensyncExternalIntegrationCloud.java b/opensync-ext-cloud/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/OpensyncExternalIntegrationCloud.java index a1a8028..baad907 100644 --- a/opensync-ext-cloud/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/OpensyncExternalIntegrationCloud.java +++ b/opensync-ext-cloud/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/OpensyncExternalIntegrationCloud.java @@ -24,6 +24,7 @@ import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -119,6 +120,8 @@ import com.telecominfraproject.wlan.status.equipment.report.models.ClientConnect import com.telecominfraproject.wlan.status.equipment.report.models.EquipmentScanDetails; import com.telecominfraproject.wlan.status.equipment.report.models.OperatingSystemPerformance; import com.telecominfraproject.wlan.status.equipment.report.models.RadioUtilizationReport; +import com.telecominfraproject.wlan.status.equipment.report.models.WiredEthernetPortStatusData; +import com.telecominfraproject.wlan.status.equipment.report.models.WiredPortStatus; import com.telecominfraproject.wlan.status.models.Status; import com.telecominfraproject.wlan.status.models.StatusCode; import com.telecominfraproject.wlan.status.models.StatusDataType; @@ -134,6 +137,10 @@ import sts.OpensyncStats.Report; public class OpensyncExternalIntegrationCloud implements OpensyncExternalIntegrationInterface { protected static final String standard_linux_date_format = "EEE MMM dd HH:mm:ss zzz yyyy"; + private static final String VLAN_TRUNK_IF_TYPE = "vlan_trunk"; + private static final String ALLOWED_VLANS = "allowed_vlans"; + private static final String NATIVE_VLAN_ID = "pvid"; + private static final String SPACE_SEPERATOR = " "; private static final Logger LOG = LoggerFactory.getLogger(OpensyncExternalIntegrationCloud.class); @@ -185,6 +192,8 @@ public class OpensyncExternalIntegrationCloud implements OpensyncExternalIntegra public String defaultWanInterfaceType; @Value("${tip.wlan.ovsdb.wifi-iface.default_wan_name:wan}") public String defaultWanInterfaceName; + @Value("${tip.wlan.ovsdb.wifi-iface.default_wan6_name:wan6}") + public String defaultWan6InterfaceName; @Value("${tip.wlan.ovsdb.syncUpRadioConfigsForProvisionedEquipment:true}") private boolean syncUpRadioConfigsForProvisionedEquipment; @@ -1009,6 +1018,10 @@ public class OpensyncExternalIntegrationCloud implements OpensyncExternalIntegra ret.setRfProfile(profileContainer.getChildOfTypeOrNull(equipmentConfig.getProfileId(), ProfileType.rf)); ret.setSsidProfile(profileContainer.getChildrenOfType(equipmentConfig.getProfileId(), ProfileType.ssid)); + + ret.setWiredEthernetPortProfile( + profileContainer.getChildOfTypeOrNullByEquipmentModel(equipmentConfig.getProfileId(), + ProfileType.wired_ethernet_port, equipmentConfig.getDetails().getEquipmentModel())); ret.setMetricsProfiles(profileContainer.getChildrenOfType(equipmentConfig.getProfileId(), ProfileType.service_metrics_collection_config)); @@ -1448,7 +1461,7 @@ public class OpensyncExternalIntegrationCloud implements OpensyncExternalIntegra public void wifiInetStateDbTableUpdate(List inetStateTables, String apId) { LOG.debug("Received Wifi_Inet_State table update for AP {}", apId); - + OvsdbSession ovsdbSession = ovsdbSessionMapInterface.getSession(apId); if (ovsdbSession == null) { @@ -1491,26 +1504,48 @@ public class OpensyncExternalIntegrationCloud implements OpensyncExternalIntegra } EquipmentProtocolStatusData protocolStatusData = (EquipmentProtocolStatusData) protocolStatus.getDetails(); + + Status ethernetPortStatus = statusServiceInterface.getOrNull(customerId, equipmentId, StatusDataType.WIRED_ETHERNET_PORT); + if (ethernetPortStatus == null) { + ethernetPortStatus = new Status(); + ethernetPortStatus.setCustomerId(customerId); + ethernetPortStatus.setEquipmentId(equipmentId); + ethernetPortStatus.setStatusDataType(StatusDataType.WIRED_ETHERNET_PORT); + ethernetPortStatus.setDetails(new WiredEthernetPortStatusData()); + ethernetPortStatus = statusServiceInterface.update(ethernetPortStatus); + } + + WiredEthernetPortStatusData ethernetPortStatusData = (WiredEthernetPortStatusData) ethernetPortStatus.getDetails(); + Map> portStatus = ethernetPortStatusData.getInterfacePortStatusMap(); - for (OpensyncAPInetState inetState : inetStateTables) { + for (OpensyncAPInetState inetState : inetStateTables) { + if (inetState.ifName != null) { + parseRawDataToWiredPortStatus(customerId, equipmentId, portStatus, inetState); + ethernetPortStatusData.setInterfacePortStatusMap(portStatus); + ethernetPortStatus.setDetails(ethernetPortStatusData); + ethernetPortStatus = statusServiceInterface.update(ethernetPortStatus); + LOG.debug("EthernetPortStatus for AP {} updated to {}", apId, ethernetPortStatus); + } - if (inetState.ifName != null && inetState.ifName.equals(defaultWanInterfaceName)) { + if (inetState.ifName != null && inetState.ifName.equals(defaultWanInterfaceName)) { - if (inetState.inetAddr != null) { - try { - protocolStatusData.setReportedIpV4Addr(Inet4Address.getByName(inetState.inetAddr)); - protocolStatus.setDetails(protocolStatusData); - protocolStatus = statusServiceInterface.update(protocolStatus); - LOG.info("Updated IpV4Addr for AP {} to {} from Wifi_Inet_State change for if_name {}", apId, - ((EquipmentProtocolStatusData) protocolStatus.getDetails()).getReportedIpV4Addr(), inetState.ifName); - LOG.debug("ProtocolStatus for AP {} updated to {}", apId, protocolStatus); + if (inetState.inetAddr != null) { + try { + protocolStatusData.setReportedIpV4Addr(Inet4Address.getByName(inetState.inetAddr)); + protocolStatus.setDetails(protocolStatusData); + protocolStatus = statusServiceInterface.update(protocolStatus); + LOG.info("Updated IpV4Addr for AP {} to {} from Wifi_Inet_State change for if_name {}", apId, + ((EquipmentProtocolStatusData) protocolStatus.getDetails()).getReportedIpV4Addr(), + inetState.ifName); + LOG.debug("ProtocolStatus for AP {} updated to {}", apId, protocolStatus); - } catch (UnknownHostException e) { - LOG.error("Could not set IpV4Addr {} on AP {} due to UnknownHostException ", inetState.inetAddr, apId, e); - } - } + } catch (UnknownHostException e) { + LOG.error("Could not set IpV4Addr {} on AP {} due to UnknownHostException ", inetState.inetAddr, + apId, e); + } + } - } + } if (inetState.getIfType().equals("vlan") && inetState.parentIfName != null && inetState.parentIfName.equals(defaultWanInterfaceName)) { @@ -1564,13 +1599,122 @@ public class OpensyncExternalIntegrationCloud implements OpensyncExternalIntegra } - @Override - public void wifiInetStateDbTableDelete(List inetStateTables, String apId) { + protected void parseRawDataToWiredPortStatus(int customerId, long equipmentId, + Map> portStatus, OpensyncAPInetState inetState) { + LOG.debug("Entering parseRawDataToWiredPortStatus for Customer {}, Equipment {} with inetState {}", + customerId, equipmentId, inetState); + List ports = new ArrayList<>(); + inetState.ethPorts.forEach((key, ethPort) -> { + try { + // Raw data from AP example: ethPorts={eth1=up wan 1000Mbps full} + String[] ethPortsValues = ethPort.split(SPACE_SEPERATOR); + List allowedVlans = getAllowedVlans(inetState.getVlanTrunk()); - LOG.debug("Received Wifi_Inet_State table delete for AP {}", apId); + if (ethPortsValues.length == 4 && inetState.getIfType() != null) { + int speed = Integer.parseInt(ethPortsValues[2].replaceAll("[^0-9]", "")); + boolean isTrunkEnabled = VLAN_TRUNK_IF_TYPE.equalsIgnoreCase(inetState.getIfType()); + int vlanId = inetState.getVlanId(); + if (isTrunkEnabled) { + vlanId = getNativeVlanIdForTrunk(inetState.getVlanTrunk()); + } + + WiredPortStatus wps = new WiredPortStatus(key, ethPortsValues[1], inetState.getIfName(), + inetState.getIfType(), speed, ethPortsValues[3], ethPortsValues[0], vlanId, + isTrunkEnabled, allowedVlans); + + ports.add(wps); + } else { + LOG.error("EthPorts doesn't have enough raw data for CustomerId {} or EquipmentId {}", customerId, + equipmentId); + } + } catch (Exception e) { + LOG.error("CustomerId {} or EquipmentId {} has error when parsing raw data to WiredPortStatus: {}", + customerId, equipmentId, e); + } + }); + addToPortStatus(portStatus, inetState.getIfName(), ports); } + // Raw data from AP example: ["allowed_vlans": " 100 200 300 "] + // convert to List of Integer + private List getAllowedVlans(Map vlanTrunk) { + List allowedVlans = new ArrayList<>(); + try { + if (!vlanTrunk.isEmpty() && vlanTrunk.get(ALLOWED_VLANS) != null + && !Objects.equals(vlanTrunk.get(ALLOWED_VLANS), "")) { + List allowedVlansStringList = Arrays.asList(vlanTrunk.get(ALLOWED_VLANS).trim().split("\\s+")); + for (String allowedVlan : allowedVlansStringList) { + allowedVlans.add(Integer.parseInt(allowedVlan)); + } + } + } catch (Exception ex) { + LOG.error("Unable to parse the allowed vlans from the vlanTrunk. Returning empty AllowedVlanList", ex); + } + LOG.debug("Returning allowed Vlans {}", allowedVlans); + return allowedVlans; + } + + private int getNativeVlanIdForTrunk(Map vlanTrunk) { + int nativeVlanId = 0; + if (!vlanTrunk.isEmpty() && vlanTrunk.get(NATIVE_VLAN_ID) != null && + !Objects.equals(vlanTrunk.get(NATIVE_VLAN_ID), "")) { + nativeVlanId = Integer.parseInt(vlanTrunk.get(NATIVE_VLAN_ID)); + } + return nativeVlanId; + } + + private void addToPortStatus(Map> portStatus, String ifName, + List ports) { + portStatus.put(ifName, ports); + LOG.debug("Returning addToPortStatus with portStatus {}", portStatus); + } + + @Override + public void wifiInetStateDbTableDelete(List inetStateTables, String apId) { + + LOG.debug("Received Wifi_Inet_State table delete for AP {}", apId); + + OvsdbSession ovsdbSession = ovsdbSessionMapInterface.getSession(apId); + + if (ovsdbSession == null) { + LOG.debug("wifiInetStateDbTableDelete::Cannot get Session for AP {}", apId); + return; + } + + long equipmentId = ovsdbSession.getEquipmentId(); + Equipment ce = equipmentServiceInterface.getOrNull(equipmentId); + if (ce == null) { + LOG.debug("wifiInetStateDbTableDelete Cannot get customer Equipment for {}", apId); + return; + } + + int customerId = ce.getCustomerId(); + if ((customerId < 0) || (equipmentId < 0)) { + LOG.debug("wifiInetStateDbTableUpdate::Cannot get valid CustomerId {} or EquipmentId {} for AP {}", + customerId, equipmentId, apId); + return; + } + + Status ethernetPortStatus = statusServiceInterface.getOrNull(customerId, equipmentId, + StatusDataType.WIRED_ETHERNET_PORT); + if (ethernetPortStatus != null) { + WiredEthernetPortStatusData ethernetPortStatusData = (WiredEthernetPortStatusData) ethernetPortStatus + .getDetails(); + Map> portStatus = ethernetPortStatusData.getInterfacePortStatusMap(); + + for (OpensyncAPInetState inetState : inetStateTables) { + + portStatus.remove(inetState.getIfName()); + ethernetPortStatusData.setInterfacePortStatusMap(portStatus); + ethernetPortStatus.setDetails(ethernetPortStatusData); + ethernetPortStatus = statusServiceInterface.update(ethernetPortStatus); + LOG.debug("Deleted ifName {} from the AP {}. EthernetPortStatus after deletion{}", + inetState.getIfName(), apId, ethernetPortStatus); + } + } + } + @Override public void wifiAssociatedClientsDbTableUpdate(List wifiAssociatedClients, String apId) { diff --git a/opensync-ext-cloud/src/test/java/com/telecominfraproject/wlan/opensync/external/integration/OpensyncExternalIntegrationCloudTest.java b/opensync-ext-cloud/src/test/java/com/telecominfraproject/wlan/opensync/external/integration/OpensyncExternalIntegrationCloudTest.java index f1e8e50..c892643 100644 --- a/opensync-ext-cloud/src/test/java/com/telecominfraproject/wlan/opensync/external/integration/OpensyncExternalIntegrationCloudTest.java +++ b/opensync-ext-cloud/src/test/java/com/telecominfraproject/wlan/opensync/external/integration/OpensyncExternalIntegrationCloudTest.java @@ -50,7 +50,6 @@ import com.telecominfraproject.wlan.core.model.entity.CountryCode; import com.telecominfraproject.wlan.core.model.equipment.EquipmentType; import com.telecominfraproject.wlan.core.model.equipment.MacAddress; import com.telecominfraproject.wlan.core.model.equipment.RadioType; -import com.telecominfraproject.wlan.core.model.pagination.PaginationContext; import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse; import com.telecominfraproject.wlan.customer.models.Customer; import com.telecominfraproject.wlan.customer.models.CustomerDetails; @@ -68,6 +67,7 @@ import com.telecominfraproject.wlan.location.models.LocationType; import com.telecominfraproject.wlan.location.service.LocationServiceInterface; import com.telecominfraproject.wlan.opensync.external.integration.controller.OpensyncCloudGatewayController; import com.telecominfraproject.wlan.opensync.external.integration.models.ConnectNodeInfo; +import com.telecominfraproject.wlan.opensync.external.integration.models.OpensyncAPInetState; import com.telecominfraproject.wlan.opensync.external.integration.models.OpensyncAPRadioState; import com.telecominfraproject.wlan.opensync.external.integration.models.OpensyncAPVIFState; import com.telecominfraproject.wlan.opensync.external.integration.utils.MqttStatsPublisher; @@ -85,6 +85,7 @@ import com.telecominfraproject.wlan.status.equipment.models.EquipmentUpgradeStat import com.telecominfraproject.wlan.status.equipment.report.models.ActiveBSSID; import com.telecominfraproject.wlan.status.equipment.report.models.ActiveBSSIDs; import com.telecominfraproject.wlan.status.equipment.report.models.ClientConnectionDetails; +import com.telecominfraproject.wlan.status.equipment.report.models.WiredPortStatus; import com.telecominfraproject.wlan.status.models.Status; import com.telecominfraproject.wlan.status.models.StatusDataType; import com.vmware.ovsdb.protocol.operation.notation.Uuid; @@ -93,7 +94,6 @@ import sts.OpensyncStats.AssocType; import sts.OpensyncStats.Client; import sts.OpensyncStats.ClientReport; import sts.OpensyncStats.EventReport; -import sts.OpensyncStats.EventReport.ClientAssocEvent; import sts.OpensyncStats.RadioBandType; import sts.OpensyncStats.Report; @@ -702,6 +702,26 @@ public class OpensyncExternalIntegrationCloudTest { Mockito.verify(statusServiceInterface, Mockito.never()).update(bssidStatus); } + + @Test + public void testParseRawDataToWiredPortStatus() { + Map> portStatus = new HashMap<>(); + OpensyncAPInetState inetState = new OpensyncAPInetState(); + inetState.setIfType("bridge"); + @SuppressWarnings("serial") + Map ethPorts = new HashMap(){{ + put("eth0", "up lan 1000Mbps full"); + put("eth1", "up wan 1000Mbps full"); + put("eth2", "incorrect value"); + }}; + inetState.setIfName("lan"); + inetState.setEthPorts(ethPorts); + opensyncExternalIntegrationCloud.parseRawDataToWiredPortStatus(2, 1, portStatus, inetState); + assertEquals(1, portStatus.size()); + assertEquals(true, portStatus.containsKey("lan")); + assertEquals(2, portStatus.get("lan").size()); + assertEquals("lan", portStatus.get("lan").get(0).getCurrentIfName()); + } @Ignore public void testWifiInetStateDbTableUpdate() { diff --git a/opensync-ext-interface/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/models/OpensyncAPConfig.java b/opensync-ext-interface/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/models/OpensyncAPConfig.java index 69d6f24..4d70999 100644 --- a/opensync-ext-interface/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/models/OpensyncAPConfig.java +++ b/opensync-ext-interface/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/models/OpensyncAPConfig.java @@ -38,6 +38,7 @@ public class OpensyncAPConfig extends OpensyncAPBase { private List ssidProfile; private List metricsProfile; private List radiusProfiles; + private Profile wiredEthernetPortProfile; private Location equipmentLocation; private EquipmentRoutingRecord equipmentRouting; private EquipmentGatewayRecord equipmentGateway; @@ -136,7 +137,8 @@ public class OpensyncAPConfig extends OpensyncAPBase { && Objects.equals(hotspotConfig, other.hotspotConfig) && Objects.equals(metricsProfile, other.metricsProfile) && Objects.equals(radiusProfiles, other.radiusProfiles) && Objects.equals(rfProfile, other.rfProfile) - && Objects.equals(ssidProfile, other.ssidProfile); + && Objects.equals(ssidProfile, other.ssidProfile) + && Objects.equals(wiredEthernetPortProfile, other.wiredEthernetPortProfile); } public Profile getApProfile() { @@ -195,11 +197,15 @@ public class OpensyncAPConfig extends OpensyncAPBase { return ssidProfile; } + public Profile getWiredEthernetPortProfile() { + return wiredEthernetPortProfile; + } + @Override public int hashCode() { return Objects.hash(apProfile, blockedClients, bonjourGatewayProfiles, captiveProfiles, customerEquipment, equipmentGateway, equipmentLocation, equipmentRouting, hotspotConfig, metricsProfile, radiusProfiles, - rfProfile, ssidProfile); + rfProfile, ssidProfile, wiredEthernetPortProfile); } public void setApProfile(Profile apProfile) { @@ -325,4 +331,8 @@ public class OpensyncAPConfig extends OpensyncAPBase { this.ssidProfile = ssidProfile; } + public void setWiredEthernetPortProfile(Profile wiredEthernetPortProfile) { + this.wiredEthernetPortProfile = wiredEthernetPortProfile; + } + } diff --git a/opensync-ext-interface/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/models/OpensyncAPInetState.java b/opensync-ext-interface/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/models/OpensyncAPInetState.java index 1c18f5f..3864f61 100644 --- a/opensync-ext-interface/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/models/OpensyncAPInetState.java +++ b/opensync-ext-interface/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/models/OpensyncAPInetState.java @@ -22,8 +22,10 @@ public class OpensyncAPInetState extends OpensyncAPBase { public String ifType; public String softwdsMacAddr; public boolean enabled; + public Map ethPorts; public boolean sofwdsWrap; public int vlanId; + public Map vlanTrunk; public String netmask; public boolean nat; public String greRemoteInetAddr; @@ -43,17 +45,21 @@ public class OpensyncAPInetState extends OpensyncAPBase { public Uuid _uuid; public Uuid version; public String greLocalInetAddr; - + // the following attribute is in inetC but not in inetS public String greRemoteMacAddr; public OpensyncAPInetState() { dns = new HashMap<>(); dhcpc = new HashMap<>(); + ethPorts = new HashMap<>(); + vlanTrunk = new HashMap<>(); } public OpensyncAPInetState(Row row) { dns = new HashMap<>(); dhcpc = new HashMap<>(); + ethPorts = new HashMap<>(); + vlanTrunk = new HashMap<>(); Map map = row.getColumns(); @@ -83,6 +89,12 @@ public class OpensyncAPInetState extends OpensyncAPBase { if (map.containsKey("dns")) { this.setDns(row.getMapColumn("dns")); } + if (map.containsKey("eth_ports")) { + this.setEthPorts(row.getMapColumn("eth_ports")); + } + if (map.containsKey("vlan_trunk")) { + this.setVlanTrunk(row.getMapColumn("vlan_trunk")); + } if (map.get("inet_addr") != null && map.get("inet_addr").getClass().equals(com.vmware.ovsdb.protocol.operation.notation.Atom.class)) { this.setInetAddr(row.getStringColumn("inet_addr")); @@ -157,6 +169,12 @@ public class OpensyncAPInetState extends OpensyncAPBase { if (!Objects.equals(dhcpd, other.dhcpd)) { return false; } + if (!Objects.equals(ethPorts, other.ethPorts)) { + return false; + } + if (!Objects.equals(vlanTrunk, other.vlanTrunk)) { + return false; + } if (!Objects.equals(dns, other.dns)) { return false; } @@ -251,6 +269,14 @@ public class OpensyncAPInetState extends OpensyncAPBase { public Map getDns() { return dns; } + + public Map getEthPorts() { + return ethPorts; + } + + public Map getVlanTrunk() { + return vlanTrunk; + } public String getGateway() { return gateway; @@ -330,9 +356,9 @@ public class OpensyncAPInetState extends OpensyncAPBase { @Override public int hashCode() { - return Objects.hash(_uuid, broadcast, dhcpc, dhcpd, dns, enabled, gateway, greIfName, greLocalInetAddr, greRemoteInetAddr, + return Objects.hash(_uuid, broadcast, dhcpc, dhcpd, dns, ethPorts, enabled, gateway, greIfName, greLocalInetAddr, greRemoteInetAddr, hwAddr, ifName, ifType, ifUuid, inetAddr, inetConfig, ipAssignScheme, mtw, nat, netmask, network, - parentIfName, greRemoteMacAddr, softwdsMacAddr, sofwdsWrap, unpnpMode, version, vlanId); + parentIfName, greRemoteMacAddr, softwdsMacAddr, sofwdsWrap, unpnpMode, version, vlanId, vlanTrunk); } public boolean isEnabled() { @@ -370,6 +396,14 @@ public class OpensyncAPInetState extends OpensyncAPBase { public void setDns(Map dns) { this.dns = dns; } + + public void setEthPorts(Map ethPorts) { + this.ethPorts = ethPorts; + } + + public void setVlanTrunk(Map vlanTrunk) { + this.vlanTrunk = vlanTrunk; + } public void setEnabled(boolean enabled) { this.enabled = enabled; @@ -466,9 +500,9 @@ public class OpensyncAPInetState extends OpensyncAPBase { @Override public String toString() { - return "OpensyncAPInetState [ifName=" + ifName + ", dhcpd=" + dhcpd + ", unpnpMode=" + unpnpMode + ", ifType=" + return "OpensyncAPInetState [ifName=" + ifName + ", dhcpd=" + dhcpd + ", ethPorts=" + ethPorts + ", unpnpMode=" + unpnpMode + ", ifType=" + ifType + ", softwdsMacAddr=" + softwdsMacAddr + ", enabled=" + enabled + ", sofwdsWrap=" + sofwdsWrap - + ", vlanId=" + vlanId + ", netmask=" + netmask + ", nat=" + nat + ", greRemoteInetAddr=" + + ", vlanId=" + vlanId + ", vlanTrunk=" + vlanTrunk + ", netmask=" + netmask + ", nat=" + nat + ", greRemoteInetAddr=" + greRemoteInetAddr + ", ifUuid=" + ifUuid + ", inetAddr=" + inetAddr + ", hwAddr=" + hwAddr + ", mtw=" + mtw + ", network=" + network + ", dns=" + dns + ", parentIfName=" + parentIfName + ", greIfName=" + greIfName + ", broadcast=" + broadcast + ", dhcpc=" + dhcpc + ", gateway=" + gateway diff --git a/opensync-gateway/pom.xml b/opensync-gateway/pom.xml index bac8c3f..97308f6 100644 --- a/opensync-gateway/pom.xml +++ b/opensync-gateway/pom.xml @@ -73,4 +73,3 @@ - diff --git a/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/TipWlanOvsdbClient.java b/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/TipWlanOvsdbClient.java index 14c72bf..cff1d98 100644 --- a/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/TipWlanOvsdbClient.java +++ b/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/TipWlanOvsdbClient.java @@ -256,6 +256,7 @@ public class TipWlanOvsdbClient implements OvsdbClientInterface { ovsdbDao.configureWifiRrm(ovsdbClient, opensyncAPConfig); ovsdbDao.configureGreTunnels(ovsdbClient, opensyncAPConfig); ovsdbDao.createVlanNetworkInterfaces(ovsdbClient, opensyncAPConfig); + ovsdbDao.configureWiredPort(ovsdbClient, opensyncAPConfig); ovsdbDao.configureRadsecRadiusAndRealm(ovsdbClient, opensyncAPConfig); ovsdbDao.configureSsids(ovsdbClient, opensyncAPConfig); if (opensyncAPConfig.getHotspotConfig() != null) { @@ -338,6 +339,7 @@ public class TipWlanOvsdbClient implements OvsdbClientInterface { ovsdbDao.configureWifiRrm(ovsdbClient, opensyncAPConfig); ovsdbDao.configureGreTunnels(ovsdbClient, opensyncAPConfig); ovsdbDao.createVlanNetworkInterfaces(ovsdbClient, opensyncAPConfig); + ovsdbDao.configureWiredPort(ovsdbClient, opensyncAPConfig); ovsdbDao.configureRadsecRadiusAndRealm(ovsdbClient, opensyncAPConfig); ovsdbDao.configureSsids(ovsdbClient, opensyncAPConfig); if (opensyncAPConfig.getHotspotConfig() != null) { @@ -643,7 +645,7 @@ public class TipWlanOvsdbClient implements OvsdbClientInterface { List inetStateDelete = new ArrayList<>(); for (TableUpdate tableUpdate : tableUpdates.getTableUpdates().values()) { - + for (RowUpdate rowUpdate : tableUpdate.getRowUpdates().values()) { if (rowUpdate.getNew() == null) { @@ -654,9 +656,9 @@ public class TipWlanOvsdbClient implements OvsdbClientInterface { } } - + // delete first - extIntegrationInterface.wifiInetStateDbTableUpdate(inetStateDelete, key); + extIntegrationInterface.wifiInetStateDbTableDelete(inetStateDelete, key); // now process updates and mutations extIntegrationInterface.wifiInetStateDbTableUpdate(inetStateInsertOrUpdate, key); diff --git a/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbDao.java b/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbDao.java index b8b4a3f..d1ffaaa 100644 --- a/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbDao.java +++ b/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbDao.java @@ -7,7 +7,6 @@ import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.telecominfraproject.wlan.core.model.equipment.LedStatus; import com.telecominfraproject.wlan.core.model.equipment.MacAddress; import com.telecominfraproject.wlan.core.model.equipment.RadioType; import com.telecominfraproject.wlan.equipment.models.ApElementConfiguration; @@ -87,6 +86,10 @@ public class OvsdbDao extends OvsdbDaoBase { ovsdbNetwork.configureInterfaces(ovsdbClient); } + public void configureWiredPort(OvsdbClient ovsdbClient, OpensyncAPConfig opensyncAPConfig) { + ovsdbNetwork.configureEthernetPorts(ovsdbClient, opensyncAPConfig); + } + public void configureNode(OvsdbClient ovsdbClient, OpensyncAPConfig opensyncAPConfig) { configureNtpServer(ovsdbClient, opensyncAPConfig); configureSyslog(ovsdbClient, opensyncAPConfig); diff --git a/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbMonitor.java b/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbMonitor.java index f05ac16..7339b45 100644 --- a/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbMonitor.java +++ b/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbMonitor.java @@ -93,6 +93,8 @@ public class OvsdbMonitor extends OvsdbDaoBase { if (rowUpdate.getOld() != null) { row = rowUpdate.getOld(); row.getColumns().putAll(rowUpdate.getNew().getColumns()); + } else { + row = rowUpdate.getNew(); } } else { row = rowUpdate.getOld(); diff --git a/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbNetworkConfig.java b/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbNetworkConfig.java index f13318b..a962abd 100644 --- a/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbNetworkConfig.java +++ b/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbNetworkConfig.java @@ -21,6 +21,8 @@ import org.springframework.stereotype.Component; import com.telecominfraproject.wlan.equipment.models.NetworkForwardMode; import com.telecominfraproject.wlan.opensync.external.integration.models.OpensyncAPConfig; import com.telecominfraproject.wlan.opensync.ovsdb.dao.models.WifiInetConfigInfo; +import com.telecominfraproject.wlan.profile.ethernetport.models.WiredEthernetPortConfiguration; +import com.telecominfraproject.wlan.profile.ethernetport.models.WiredPort; import com.telecominfraproject.wlan.profile.models.Profile; import com.telecominfraproject.wlan.profile.network.models.ApNetworkConfiguration; import com.telecominfraproject.wlan.profile.network.models.GreTunnelConfiguration; @@ -45,7 +47,16 @@ import com.vmware.ovsdb.service.OvsdbClient; public class OvsdbNetworkConfig extends OvsdbDaoBase { @Autowired - OvsdbGet ovsdbGet; + private OvsdbGet ovsdbGet; + + private static final String VLAN_IF_TYPE = "vlan"; + private static final String VLAN_TRUNK_IF_TYPE = "vlan_trunk"; + private static final String BRIDGE_IF_TYPE = "bridge"; + private static final String LAN_IF_NAME = "lan"; + private static final String WAN_IF_NAME = "wan"; + private static final int DEFAULT_MAX_INTERNAL_VLAN_ID = 2; + private static final String SEPARATOR = " "; + void configureGreTunnel(OvsdbClient ovsdbClient, Profile apNetworkConfiguration) { try { @@ -92,7 +103,7 @@ public class OvsdbNetworkConfig extends OvsdbDaoBase { LOG.info("configureGreTunnel {}", ((UpdateResult) res).toString()); } else if (res instanceof ErrorResult) { LOG.error("configureGreTunnel error {}", (res)); - throw new RuntimeException("configureGreTunnel " + ((ErrorResult) res).getError() + " " + throw new RuntimeException("configureGreTunnel " + ((ErrorResult) res).getError() + SEPARATOR + ((ErrorResult) res).getDetails()); } } @@ -137,10 +148,216 @@ public class OvsdbNetworkConfig extends OvsdbDaoBase { } else { operations.add(new Insert(wifiInetConfigDbTable, row)); } + } + void configureEthernetPorts(OvsdbClient ovsdbClient, OpensyncAPConfig opensyncApConfig) { + Profile wiredEthernetPortProfile = opensyncApConfig.getWiredEthernetPortProfile(); + + if (wiredEthernetPortProfile != null) { + LOG.debug("Entering configure Ethernet Ports for wiredEthernetPortProfile {} for equipment {}", + wiredEthernetPortProfile, opensyncApConfig.getCustomerEquipment().getId()); + // Getting the config from the UI + WiredEthernetPortConfiguration ethernetPortConfig = (WiredEthernetPortConfiguration) wiredEthernetPortProfile + .getDetails(); + LOG.debug("Configure EthernetPorts {}", ethernetPortConfig); + Set desiredWiredPorts = ethernetPortConfig.getEthPorts(); + + handleEthernetPortConfiguration(ovsdbClient, desiredWiredPorts); + + } else { + LOG.info("opensyncApConfig for Customer {}, Equipment {} has no wiredEthernetPortProfile attached" , + opensyncApConfig.getCustomerEquipment().getCustomerId(), opensyncApConfig.getCustomerEquipment().getId()); + } + } + + private void handleEthernetPortConfiguration(OvsdbClient ovsdbClient, Set desiredWiredPorts) { + if (desiredWiredPorts == null) { + LOG.info("Cannot handle the EthernetPort config for null desired Wired Ports. Exiting"); + return; + } + LOG.debug("In handleEthernetPortConfiguration with desiredWiredPorts {}", desiredWiredPorts); + WiredPort wanPort = getDefaultWanPort(desiredWiredPorts); + if (wanPort == null) { + LOG.error("Cannot find the default wan port from the desired list of ports {}" , desiredWiredPorts); + return; + } + for (WiredPort desiredPort : desiredWiredPorts) { + if (!desiredPort.equals(wanPort)) { + if (isLanToBridgeConversion(desiredPort) && !desiredPort.isTrunkEnabled()) { + // Flow 1: Desired Bridge + Access + LOG.debug("Desired Config is Bridge with Access Mode"); + changeLanToWan(ovsdbClient, desiredPort, wanPort); + createVlanTag(ovsdbClient, desiredPort); + } else if (isLanToBridgeConversion(desiredPort) && desiredPort.isTrunkEnabled()) { + // Flow 2: Desired Bridge + Trunk + LOG.debug("Desired Config is Bridge with Trunk Mode"); + changeLanToWan(ovsdbClient, desiredPort, wanPort); + createTrunkInterface(ovsdbClient, desiredPort); + } else if (!BRIDGE_IF_TYPE.equalsIgnoreCase(desiredPort.getIfType())) { + // Flow 3: Desired ifType is NAT + LOG.debug("Desired Config is NAT (LAN) mode. Desired Port {} may still be tagged to WAN interface. Convert to LAN mode", desiredPort.getIfName()); + changeWanToLan(ovsdbClient, desiredPort, wanPort); + } else { + LOG.info("Not a supported Config change requested for the port {}", desiredPort); + } + } else { + LOG.error("It's the default WAN port. No changes needed!"); + } + } // end of for loop + } + + private String generateInterfaceId(String portName, int vlanId, boolean trunk) { + if (!trunk) { + return String.format("%s_%s", portName, vlanId); + } else { + return String.format("%s_trunk", portName); + } + } + + private boolean isLanToBridgeConversion(WiredPort desiredPort) { + return LAN_IF_NAME.equalsIgnoreCase(desiredPort.getIfName()) && + BRIDGE_IF_TYPE.equals(desiredPort.getIfType()); + } + + WiredPort getDefaultWanPort(Set desiredPorts) { + WiredPort wanWiredPort = desiredPorts.stream() + .filter(entry -> WAN_IF_NAME.equals(entry.getIfName())).findFirst().orElse(null); + + LOG.debug("Returning wanWiredPort {}", wanWiredPort); + return wanWiredPort; + } + + void changeLanToWan(OvsdbClient ovsdbClient, WiredPort desiredWiredPort, WiredPort wanPort) { + LOG.debug("Moving Port {} with current ifName {} to WAN", desiredWiredPort.getName(), desiredWiredPort.getIfName()); + List operations = new ArrayList<>(); + // Step1: remove lan from eth_ports + // /usr/opensync/bin/ovsh u Wifi_Inet_Config eth_ports:=" " -w if_name==lan + addEthPortsOperation(operations, SEPARATOR, LAN_IF_NAME); + + // Step2: make lan to a wan port + // /usr/opensync/bin/ovsh u Wifi_Inet_Config eth_ports:="eth0 eth1" -w if_name==wan + // eth_ports syntax is set by AP (i.e, eth0 eth1) + addEthPortsOperation(operations, desiredWiredPort.getName() + SEPARATOR + wanPort.getName(), WAN_IF_NAME); + sendOperationsToAP(ovsdbClient, operations, "changeLanToWan"); + } + + private void createVlanTag(OvsdbClient ovsdbClient, WiredPort desiredWiredPort) { + LOG.debug("Creating a new VlanInterface for wiredPort {}", desiredWiredPort); + if (desiredWiredPort.getVlanId() > DEFAULT_MAX_INTERNAL_VLAN_ID) { + // Tag to vlan + // /usr/opensync/bin/ovsh i Wifi_Inet_Config NAT:=true enabled:=true + // if_name:=eth0_100 if_type:=vlan ip_assign_scheme:=none network:=true + // parent_ifname:=eth0 vlan_id:=100 dhcp_sniff:=false eth_ports:="eth0" + List operations = new ArrayList<>(); + Map tableColumns = new HashMap<>(); + tableColumns.put("NAT", new Atom<>(true)); + tableColumns.put("enabled", new Atom<>(true)); + tableColumns.put("if_name", new Atom<>(generateInterfaceId(desiredWiredPort.getName(), desiredWiredPort.getVlanId(), false))); + tableColumns.put("if_type", new Atom<>(VLAN_IF_TYPE)); + tableColumns.put("ip_assign_scheme", new Atom<>("none")); + tableColumns.put("network", new Atom<>(true)); + tableColumns.put("parent_ifname", new Atom<>(desiredWiredPort.getName())); + tableColumns.put("vlan_id", new Atom<>(desiredWiredPort.getVlanId())); + tableColumns.put("dhcp_sniff", new Atom<>(false)); + tableColumns.put("eth_ports", new Atom<>(desiredWiredPort.getName())); + Row row = new Row(tableColumns); + operations.add(new Insert(wifiInetConfigDbTable, row)); + + sendOperationsToAP(ovsdbClient, operations, "createVlanTag"); + } else { + LOG.info("Desired vlanId {} is lower than default {}; no tagging needed", + desiredWiredPort.getVlanId(), DEFAULT_MAX_INTERNAL_VLAN_ID); + } + } + + private void createTrunkInterface(OvsdbClient ovsdbClient, WiredPort desiredWiredPort) { + LOG.debug("Creating a new TrunkInterface for wiredPort {}", desiredWiredPort); + + // Create Trunk Interface + // /usr/opensync/bin/ovsh i Wifi_Inet_Config NAT:=true enabled:=true + // if_name:=eth0_trunk if_type:=vlan_trunk ip_assign_scheme:=none network:=true + // parent_ifname:=eth0 dhcp_sniff:=false eth_ports:="eth0" + // vlan_trunk:='["map",[["allowed_vlans","100 200 300"],["pvid","10"]]]' + + List operations = new ArrayList<>(); + Map tableColumns = new HashMap<>(); + tableColumns.put("NAT", new Atom<>(true)); + tableColumns.put("enabled", new Atom<>(true)); + tableColumns.put("if_name", new Atom<>(generateInterfaceId(desiredWiredPort.getName(), desiredWiredPort.getVlanId(), true))); + tableColumns.put("if_type", new Atom<>(VLAN_TRUNK_IF_TYPE)); + tableColumns.put("ip_assign_scheme", new Atom<>("none")); + tableColumns.put("network", new Atom<>(true)); + tableColumns.put("parent_ifname", new Atom<>(desiredWiredPort.getName())); + tableColumns.put("dhcp_sniff", new Atom<>(false)); + tableColumns.put("eth_ports", new Atom<>(desiredWiredPort.getName())); + + Map vlanTrunkMap = new HashMap<>(); + + if (desiredWiredPort.getAllowedVlanIds() != null) { + vlanTrunkMap.put("allowed_vlans", getAllowedVlanAsString(desiredWiredPort)); + if (desiredWiredPort.getVlanId() > DEFAULT_MAX_INTERNAL_VLAN_ID) { + vlanTrunkMap.put("pvid", String.valueOf(desiredWiredPort.getVlanId())); + } + } + + com.vmware.ovsdb.protocol.operation.notation.Map vlanTrunkVal = com.vmware.ovsdb.protocol.operation.notation.Map.of(vlanTrunkMap); + + tableColumns.put(VLAN_TRUNK_IF_TYPE, vlanTrunkVal); + Row row = new Row(tableColumns); + operations.add(new Insert(wifiInetConfigDbTable, row)); + + sendOperationsToAP(ovsdbClient, operations, "createTrunkInterface"); + + } + + private String getAllowedVlanAsString(WiredPort desiredWiredPort) { + return desiredWiredPort.getAllowedVlanIds().stream().map(String::valueOf).collect(Collectors.joining(SEPARATOR)); + } + + void changeWanToLan(OvsdbClient ovsdbClient, WiredPort desiredWiredPort, WiredPort wanPort) { + // Step1: set the correct port to lan + // /usr/opensync/bin/ovsh u Wifi_Inet_Config eth_ports:="eth0" -w if_name==lan + List operations = new ArrayList<>(); + addEthPortsOperation(operations, desiredWiredPort.getName(), LAN_IF_NAME); + + // Step2: set the correct port to wan + // /usr/opensync/bin/ovsh u Wifi_Inet_Config eth_ports:="eth1" -w if_name==wan + addEthPortsOperation(operations, wanPort.getName(), WAN_IF_NAME); + + sendOperationsToAP(ovsdbClient, operations, "changeWanToLan"); + } + + void addEthPortsOperation(List operations, String ethPorts, String ifName) { + Map tableColumn = new HashMap<>(); + tableColumn.put("eth_ports", new Atom<>(ethPorts)); + Row row = new Row(tableColumn); + operations.add(new Update(wifiInetConfigDbTable, + List.of(new Condition("if_name", Function.EQUALS, new Atom<>(ifName))), row)); + } + + void sendOperationsToAP(OvsdbClient ovsdbClient, List operations, String methodName) { + try { + CompletableFuture fResult = ovsdbClient.transact(ovsdbName, operations); + OperationResult[] result = fResult.get(ovsdbTimeoutSec, TimeUnit.SECONDS); + for (OperationResult res : result) { + if (res instanceof InsertResult) { + LOG.info("{} - {}", methodName, res); + } else if (res instanceof UpdateResult) { + LOG.info("{} {}", methodName, res); + } else if (res instanceof ErrorResult) { + LOG.error("{} {}", methodName, res); + throw new RuntimeException("createVlanNetworkInterfaces - " + ((ErrorResult) res).getError() + SEPARATOR + + ((ErrorResult) res).getDetails()); + } + } + } catch (OvsdbClientException | InterruptedException | ExecutionException | TimeoutException e) { + throw new RuntimeException(e); + } + } + /** - * @param ovsdbClient + * @param ovsdbClient * @param vifInterfaceName * @param enabled * @param networkForwardMode @@ -193,7 +410,7 @@ public class OvsdbNetworkConfig extends OvsdbDaoBase { LOG.info("createVlanNetworkInterfaces {}", ((UpdateResult) res).toString()); } else if (res instanceof ErrorResult) { LOG.error("createVlanNetworkInterfaces error {}", (res)); - throw new RuntimeException("createVlanNetworkInterfaces " + ((ErrorResult) res).getError() + " " + throw new RuntimeException("createVlanNetworkInterfaces " + ((ErrorResult) res).getError() + SEPARATOR + ((ErrorResult) res).getDetails()); } } @@ -245,7 +462,7 @@ public class OvsdbNetworkConfig extends OvsdbDaoBase { LOG.info("createVlanNetworkInterfaces {}", ((UpdateResult) res).toString()); } else if (res instanceof ErrorResult) { LOG.error("createVlanNetworkInterfaces error {}", (res)); - throw new RuntimeException("createVlanNetworkInterfaces " + ((ErrorResult) res).getError() + " " + throw new RuntimeException("createVlanNetworkInterfaces " + ((ErrorResult) res).getError() + SEPARATOR + ((ErrorResult) res).getDetails()); } } @@ -288,33 +505,34 @@ public class OvsdbNetworkConfig extends OvsdbDaoBase { Collection provisionedWifiInetConfigs = ovsdbGet .getProvisionedWifiInetConfigs(ovsdbClient).values(); List operations = new ArrayList<>(); - List conditions = new ArrayList<>(); for (WifiInetConfigInfo wifiInetConfigInfo : provisionedWifiInetConfigs) { - if (wifiInetConfigInfo.vlanId > 1 || wifiInetConfigInfo.ifType.equals("vif") - || wifiInetConfigInfo.ifName.startsWith("gre") || wifiInetConfigInfo.ifType.equals("gre")) { - conditions = new ArrayList<>(); + if (wifiInetConfigInfo.vlanId > 1 + || wifiInetConfigInfo.ifType.equals("vif") + || wifiInetConfigInfo.ifName.startsWith("gre") || wifiInetConfigInfo.ifType.equals("gre") + || VLAN_IF_TYPE.equalsIgnoreCase(wifiInetConfigInfo.ifType) // Remove any existing vlan/vlan_trunk tagging + || VLAN_TRUNK_IF_TYPE.equalsIgnoreCase(wifiInetConfigInfo.ifType) ) { + List conditions = new ArrayList<>(); conditions.add(new Condition("if_name", Function.EQUALS, new Atom<>(wifiInetConfigInfo.ifName))); operations.add(new Delete(wifiInetConfigDbTable, conditions)); } } CompletableFuture fResult = ovsdbClient.transact(ovsdbName, operations); OperationResult[] result = fResult.get(ovsdbTimeoutSec, TimeUnit.SECONDS); - LOG.info("Removed all existing vif, vlan, and gre interface configs from {}:", wifiInetConfigDbTable); + LOG.info("Removed all existing vif, vlan, vlan_trunk and gre interface configs from {}:", wifiInetConfigDbTable); for (OperationResult res : result) { LOG.info("Op Result {}", res); } provisionedWifiInetConfigs = ovsdbGet.getProvisionedWifiInetConfigs(ovsdbClient).values(); for (WifiInetConfigInfo inetConfigInfo : provisionedWifiInetConfigs) { - if (inetConfigInfo.ifType.equals("vif") || inetConfigInfo.ifType.equals("gre")) { + if (inetConfigInfo.ifType.equals("vif") || inetConfigInfo.ifType.equals("gre") || + VLAN_IF_TYPE.equals(inetConfigInfo.ifType) || VLAN_TRUNK_IF_TYPE.equals(inetConfigInfo.ifType)) { throw new RuntimeException( - "Failed to remove all vif and gre interface configurations from Wifi_Inet_Config dbTable, still has " + "Failed to remove all vif, gre, vlan interface configurations from Wifi_Inet_Config dbTable, still has " + provisionedWifiInetConfigs.stream().filter(new Predicate() { @Override public boolean test(WifiInetConfigInfo t) { - if ((t.ifType.equals("vif")) || (t.ifType.equals("gre"))) { - return true; - } - return false; + return (t.ifType.equals("vif")) || (t.ifType.equals("gre")) || + VLAN_IF_TYPE.equals(t.ifType) || VLAN_TRUNK_IF_TYPE.equals(t.ifType); } }).collect(Collectors.toList())); diff --git a/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbDaoTest.java b/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbDaoTest.java index f89d0d3..7abe859 100644 --- a/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbDaoTest.java +++ b/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbDaoTest.java @@ -34,11 +34,8 @@ import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.telecominfraproject.wlan.core.model.equipment.RadioType; import com.telecominfraproject.wlan.location.models.Location; -import com.telecominfraproject.wlan.opensync.external.integration.models.ConnectNodeInfo; import com.telecominfraproject.wlan.opensync.external.integration.models.OpensyncAPConfig; import com.telecominfraproject.wlan.opensync.external.integration.models.OpensyncAPHotspot20Config; import com.telecominfraproject.wlan.profile.models.Profile; @@ -47,10 +44,8 @@ import com.telecominfraproject.wlan.profile.network.models.ApNetworkConfiguratio import com.telecominfraproject.wlan.profile.network.models.GreTunnelConfiguration; import com.telecominfraproject.wlan.profile.ssid.models.SsidConfiguration; import com.vmware.ovsdb.exception.OvsdbClientException; -import com.vmware.ovsdb.protocol.operation.notation.Atom; import com.vmware.ovsdb.protocol.operation.notation.Row; import com.vmware.ovsdb.protocol.operation.notation.Uuid; -import com.vmware.ovsdb.protocol.operation.notation.Value; import com.vmware.ovsdb.protocol.operation.result.ErrorResult; import com.vmware.ovsdb.protocol.operation.result.InsertResult; import com.vmware.ovsdb.protocol.operation.result.OperationResult; diff --git a/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbNetworkConfigTest.java b/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbNetworkConfigTest.java new file mode 100644 index 0000000..44166a9 --- /dev/null +++ b/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbNetworkConfigTest.java @@ -0,0 +1,160 @@ +package com.telecominfraproject.wlan.opensync.ovsdb.dao; + +import com.telecominfraproject.wlan.equipment.models.Equipment; +import com.telecominfraproject.wlan.opensync.external.integration.models.OpensyncAPConfig; +import com.telecominfraproject.wlan.profile.ethernetport.models.WiredEthernetPortConfiguration; +import com.telecominfraproject.wlan.profile.ethernetport.models.WiredPort; +import com.telecominfraproject.wlan.profile.models.Profile; +import com.telecominfraproject.wlan.profile.models.ProfileType; +import com.vmware.ovsdb.exception.OvsdbClientException; +import com.vmware.ovsdb.protocol.operation.result.OperationResult; +import com.vmware.ovsdb.protocol.operation.result.UpdateResult; +import com.vmware.ovsdb.service.OvsdbClient; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoSession; +import org.mockito.quality.Strictness; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static org.mockito.Mockito.times; + +/** + * @author rsharma + */ + +@RunWith(SpringRunner.class) +@ActiveProfiles(profiles = { "integration_test", }) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = OvsdbNetworkConfigTest.class) +@Import(value = { OvsdbNetworkConfig.class + +}) +public class OvsdbNetworkConfigTest { + + @Mock(answer = Answers.RETURNS_MOCKS) + OvsdbClient ovsdbClient; + + @Autowired + OvsdbNetworkConfig ovsdbNetworkConfig; + + @MockBean(answer = Answers.RETURNS_MOCKS) + OvsdbGet ovsdbGet; + + @Mock(answer = Answers.RETURNS_MOCKS) + CompletableFuture futureResult; + + private MockitoSession mockito; + + @Before + public void setUp() throws Exception { + mockito = Mockito.mockitoSession().initMocks(this).strictness(Strictness.STRICT_STUBS).startMocking(); + Mockito.when(ovsdbClient.transact(Mockito.eq(OvsdbDao.ovsdbName), Mockito.anyList())).thenReturn(futureResult); + } + + @After + public void tearDown() throws Exception { + mockito.finishMocking(); + } + + // Eth0 port is in LAN mode and we need it to convert to eth0_trunk + @Test + public void testConfigureEthernetPorts_BridgeTrunkMode() throws ExecutionException, InterruptedException, TimeoutException, OvsdbClientException { + OperationResult[] updateResult = new OperationResult[] { new UpdateResult(1) }; + Mockito.when(futureResult.get(ovsdbNetworkConfig.ovsdbTimeoutSec, TimeUnit.SECONDS)) + .thenReturn(updateResult); + + ovsdbNetworkConfig.configureEthernetPorts(ovsdbClient, createOpensyncApConfig(true, "bridge")); + + Mockito.verify(ovsdbClient, times(2)).transact(Mockito.eq(OvsdbDao.ovsdbName), Mockito.anyList()); + } + + // Other tests that are useful to consider -- NOT anymore with GW deleting existing interfaces + // Case when ETH port is in eth0_trunk mode and no changes are required + // Case when ETH port is already in eth0_vlan100 and no changes are required + + // Case when ETH port is in LAN mode and we convert it into BRIDGE + VlanId + @Test + public void testConfigureEthernetPorts_BridgeAccessMode() throws ExecutionException, InterruptedException, TimeoutException, OvsdbClientException { + OperationResult[] updateResult = new OperationResult[] { new UpdateResult(1) }; + Mockito.when(futureResult.get(ovsdbNetworkConfig.ovsdbTimeoutSec, TimeUnit.SECONDS)) + .thenReturn(updateResult); + + ovsdbNetworkConfig.configureEthernetPorts(ovsdbClient, createOpensyncApConfig(false, "bridge")); + + Mockito.verify(ovsdbClient, times(2)).transact(Mockito.eq(OvsdbDao.ovsdbName), Mockito.anyList()); + } + + // Case when ETH port is in BRIDGE + VlanId and we convert it into NAT (LAN) + @Test + public void testConfigureEthernetPorts_BridgeAccessToNATConversion() throws ExecutionException, InterruptedException, TimeoutException, OvsdbClientException { + OperationResult[] updateResult = new OperationResult[] { new UpdateResult(1) }; + Mockito.when(futureResult.get(ovsdbNetworkConfig.ovsdbTimeoutSec, TimeUnit.SECONDS)) + .thenReturn(updateResult); + + ovsdbNetworkConfig.configureEthernetPorts(ovsdbClient, createOpensyncApConfig(false, "NAT")); + + Mockito.verify(ovsdbClient, times(1)).transact(Mockito.eq(OvsdbDao.ovsdbName), Mockito.anyList()); + } + + private OpensyncAPConfig createOpensyncApConfig(boolean isTrunkEnabled, String ifType) { + OpensyncAPConfig opensyncApConfig = new OpensyncAPConfig(); + + Equipment customerEquip = new Equipment(); + customerEquip.setCustomerId(1); + customerEquip.setId(1L); + opensyncApConfig.setCustomerEquipment(customerEquip); + opensyncApConfig.setWiredEthernetPortProfile(createWiredEthernetPortProfile(isTrunkEnabled, ifType)); + + return opensyncApConfig; + } + + private Profile createWiredEthernetPortProfile(boolean isTrunkEnabled, String ifType) { + WiredPort portLan = createWiredPort("lan", ifType, isTrunkEnabled, 10, List.of(100, 200), "eth0", "ETHERNET"); + WiredPort portWan = createWiredPort("wan", "bridge", false, 0, null, "eth1", "INTERNET"); + + WiredEthernetPortConfiguration details = new WiredEthernetPortConfiguration(); + details.setEquipmentModel("EA8300"); + details.setEthPorts(Set.of(portLan, portWan)); + + Profile wiredEthernetPortProfile = new Profile(); + wiredEthernetPortProfile.setCustomerId(1); + wiredEthernetPortProfile.setProfileType(ProfileType.wired_ethernet_port); + wiredEthernetPortProfile.setId(10L); + wiredEthernetPortProfile.setName("WiredProfileForTest"); + wiredEthernetPortProfile.setCreatedTimestamp(1634060798000L); + wiredEthernetPortProfile.setLastModifiedTimestamp(1634060798000L); + wiredEthernetPortProfile.setDetails(details); + + return wiredEthernetPortProfile; + } + + private WiredPort createWiredPort(String ifName, String ifType, boolean isTrunkEnabled, int vlanId, List allowedVlans, + String name, String displayName) { + WiredPort wiredPort = new WiredPort(); + wiredPort.setIfName(ifName); + wiredPort.setIfType(ifType); + wiredPort.setTrunkEnabled(isTrunkEnabled); + wiredPort.setVlanId(vlanId); + wiredPort.setAllowedVlanIds(allowedVlans); + wiredPort.setName(name); + wiredPort.setDisplayName(displayName); + + return wiredPort; + } +} \ No newline at end of file diff --git a/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbNodeTest.java b/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbNodeTest.java index c94a46f..c918c2c 100644 --- a/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbNodeTest.java +++ b/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbNodeTest.java @@ -37,7 +37,6 @@ import com.vmware.ovsdb.service.OvsdbClient; OvsdbHotspotConfig.class, OvsdbCommandConfig.class, OvsdbMonitor.class, OvsdbFirmwareConfig.class, OvsdbStatsConfig.class, OvsdbSsidConfig.class, OvsdbRrmConfig.class, OvsdbNetworkConfig.class, OvsdbNodeConfig.class,OvsdbRadiusProxyConfig.class - }) public class OvsdbNodeTest { diff --git a/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbSsidConfigTest.java b/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbSsidConfigTest.java index 53d2a0f..91cc469 100644 --- a/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbSsidConfigTest.java +++ b/opensync-gateway/src/test/java/com/telecominfraproject/wlan/opensync/ovsdb/dao/OvsdbSsidConfigTest.java @@ -42,7 +42,6 @@ import com.vmware.ovsdb.service.OvsdbClient; OvsdbHotspotConfig.class, OvsdbCommandConfig.class, OvsdbMonitor.class, OvsdbFirmwareConfig.class, OvsdbStatsConfig.class, OvsdbSsidConfig.class, OvsdbRrmConfig.class, OvsdbNetworkConfig.class, OvsdbNodeConfig.class,OvsdbRadiusProxyConfig.class - }) public class OvsdbSsidConfigTest {