From 956ce78bfc0be51f2c4f4048e12b479d6ebbcd6e Mon Sep 17 00:00:00 2001 From: Mike Hansen Date: Thu, 3 Sep 2020 12:00:01 -0400 Subject: [PATCH] WIFI-691: modify OSGW to send to the AP a new set of commands for managing remote ssh agent and sessions Handle the start and stop of the debug engine REST commands coming via gateway controller. Change gateway controller to use new method to handle redirector change. NB. Ap commands being sent via the command config in OvsdbDao are not finalized and will change. --- .../OpensyncExternalIntegrationCloud.java | 1 + .../OpensyncCloudGatewayController.java | 162 ++++++++++-------- .../integration/OvsdbClientInterface.java | 6 +- .../experiment/OpenSyncGatewayController.java | 2 +- .../opensync/ovsdb/TipWlanOvsdbClient.java | 36 +++- .../wlan/opensync/ovsdb/dao/OvsdbDao.java | 33 ++-- 6 files changed, 157 insertions(+), 83 deletions(-) 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 10a1f13..f2fa3ad 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 @@ -275,6 +275,7 @@ public class OpensyncExternalIntegrationCloud implements OpensyncExternalIntegra + autoProvisionedCustomerId); } +// String dbUrlString = customer.getDetails().getClientFingerPrintsDbUrl(); ce = new Equipment(); ce.setEquipmentType(EquipmentType.AP); ce.setInventoryId(apId); diff --git a/opensync-ext-cloud/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/controller/OpensyncCloudGatewayController.java b/opensync-ext-cloud/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/controller/OpensyncCloudGatewayController.java index e0f313d..62b1964 100644 --- a/opensync-ext-cloud/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/controller/OpensyncCloudGatewayController.java +++ b/opensync-ext-cloud/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/controller/OpensyncCloudGatewayController.java @@ -33,6 +33,7 @@ import com.telecominfraproject.wlan.core.model.service.ServiceInstanceInformatio import com.telecominfraproject.wlan.core.server.container.ConnectorProperties; import com.telecominfraproject.wlan.equipmentgateway.models.CEGWBaseCommand; import com.telecominfraproject.wlan.equipmentgateway.models.CEGWBlinkRequest; +import com.telecominfraproject.wlan.equipmentgateway.models.CEGWChangeRedirectorHost; import com.telecominfraproject.wlan.equipmentgateway.models.CEGWClientBlocklistChangeNotification; import com.telecominfraproject.wlan.equipmentgateway.models.CEGWCloseSessionRequest; import com.telecominfraproject.wlan.equipmentgateway.models.CEGWCommandResultCode; @@ -42,6 +43,7 @@ import com.telecominfraproject.wlan.equipmentgateway.models.CEGWFirmwareFlashReq import com.telecominfraproject.wlan.equipmentgateway.models.CEGWRadioResetRequest; import com.telecominfraproject.wlan.equipmentgateway.models.CEGWRouteCheck; import com.telecominfraproject.wlan.equipmentgateway.models.CEGWStartDebugEngine; +import com.telecominfraproject.wlan.equipmentgateway.models.CEGWStopDebugEngine; import com.telecominfraproject.wlan.equipmentgateway.models.EquipmentCommand; import com.telecominfraproject.wlan.equipmentgateway.models.EquipmentCommandResponse; import com.telecominfraproject.wlan.equipmentgateway.models.GatewayDefaults; @@ -66,6 +68,7 @@ import com.telecominfraproject.wlan.server.exceptions.ConfigurationException; public class OpensyncCloudGatewayController { public static class ListOfEquipmentCommandResponses extends ArrayList { + private static final long serialVersionUID = 3070319062835500930L; } @@ -112,6 +115,7 @@ public class OpensyncCloudGatewayController { * latestTimetamp used when updating {@link #activeCustomerMap} */ private final BiFunction latestTimestamp = new BiFunction<>() { + @Override public Long apply(Long oldValue, Long newValue) { if (newValue.compareTo(oldValue) > 0) { @@ -131,6 +135,7 @@ public class OpensyncCloudGatewayController { } commands.stream().forEach(new Consumer() { + @Override public void accept(CEGWBaseCommand command) { LOG.debug("sendCommands - processing {}", command); @@ -156,43 +161,51 @@ public class OpensyncCloudGatewayController { switch (command.getCommandType()) { - case ConfigChangeNotification: - ret.add(sendConfigChangeNotification(session, (CEGWConfigChangeNotification) command)); - break; - case CloseSessionRequest: - ret.add(closeSession(session, (CEGWCloseSessionRequest) command)); - break; - case CheckRouting: - ret.add(checkEquipmentRouting(session, (CEGWRouteCheck) command)); - break; - case BlinkRequest: - ret.add(processBlinkRequest(session, (CEGWBlinkRequest) command)); - break; - case StartDebugEngine: - ret.add(processChangeRedirector(session, (CEGWStartDebugEngine) command)); - break; - case FirmwareDownloadRequest: - ret.add(processFirmwareDownload(session, (CEGWFirmwareDownloadRequest) command)); - break; - case FirmwareFlashRequest: - ret.add(processFirmwareFlash(session, (CEGWFirmwareFlashRequest) command)); - break; - case RadioReset: - ret.add(processRadioReset(session, (CEGWRadioResetRequest) command)); - break; - case ClientBlocklistChangeNotification: - ret.add(sendClientBlocklistChangeNotification(session, - (CEGWClientBlocklistChangeNotification) command)); - break; - default: - LOG.warn("[{}] Failed to deliver command {}, unsupported command type", inventoryId, command); - ret.add(new EquipmentCommandResponse( - CEGWCommandResultCode.UnsupportedCommand, "Invalid command type (" - + command.getCommandType() + ") for equipment (" + inventoryId + ")", - command, registeredGateway.getHostname(), registeredGateway.getPort())); + case ConfigChangeNotification: + ret.add(sendConfigChangeNotification(session, (CEGWConfigChangeNotification) command)); + break; + case CloseSessionRequest: + ret.add(closeSession(session, (CEGWCloseSessionRequest) command)); + break; + case CheckRouting: + ret.add(checkEquipmentRouting(session, (CEGWRouteCheck) command)); + break; + case BlinkRequest: + ret.add(processBlinkRequest(session, (CEGWBlinkRequest) command)); + break; + case ChangeRedirectorHost: + ret.add(processChangeRedirector(session, (CEGWChangeRedirectorHost) command)); + break; + case StartDebugEngine: + ret.add(processStartDebugEngine(session, (CEGWStartDebugEngine) command)); + break; + case StopDebugEngine: + ret.add(processStopDebugEngine(session, (CEGWStopDebugEngine) command)); + break; + case FirmwareDownloadRequest: + ret.add(processFirmwareDownload(session, (CEGWFirmwareDownloadRequest) command)); + break; + case FirmwareFlashRequest: + ret.add(processFirmwareFlash(session, (CEGWFirmwareFlashRequest) command)); + break; + case RadioReset: + ret.add(processRadioReset(session, (CEGWRadioResetRequest) command)); + break; + case ClientBlocklistChangeNotification: + ret.add(sendClientBlocklistChangeNotification(session, + (CEGWClientBlocklistChangeNotification) command)); + break; + default: + LOG.warn("[{}] Failed to deliver command {}, unsupported command type", inventoryId, command); + ret.add(new EquipmentCommandResponse( + CEGWCommandResultCode.UnsupportedCommand, "Invalid command type (" + + command.getCommandType() + ") for equipment (" + inventoryId + ")", + command, registeredGateway.getHostname(), registeredGateway.getPort())); } } + + }); return ret; @@ -286,14 +299,15 @@ public class OpensyncCloudGatewayController { } else if (command instanceof CEGWClientBlocklistChangeNotification) { tipwlanOvsdbClient.processClientBlocklistChange(inventoryId, ((CEGWClientBlocklistChangeNotification) command).getBlockList()); + } else if (command instanceof CEGWChangeRedirectorHost) { + String newRedirectorAddress = ((CEGWChangeRedirectorHost) command).getRedirectorHost(); + tipwlanOvsdbClient.changeRedirectorHost(inventoryId, newRedirectorAddress); } else if (command instanceof CEGWStartDebugEngine) { - // dtop: we will be using CEGWStartDebugEngine command to deliver - // request to - // change redirector - // TODO: after the demo introduce a specialized command for this! - String newRedirectorAddress = ((CEGWStartDebugEngine) command).getGatewayHostname(); - tipwlanOvsdbClient.changeRedirectorAddress(inventoryId, newRedirectorAddress); - // TODO: add support for additional commands below + String gatewayHostname = ((CEGWStartDebugEngine) command).getGatewayHostname(); + int gatewayPort = ((CEGWStartDebugEngine) command).getGatewayPort(); + tipwlanOvsdbClient.startDebugEngine(inventoryId, gatewayHostname, gatewayPort); + } else if (command instanceof CEGWStopDebugEngine) { + tipwlanOvsdbClient.stopDebugEngine(inventoryId); } else if (command instanceof CEGWFirmwareDownloadRequest) { CEGWFirmwareDownloadRequest dlRequest = (CEGWFirmwareDownloadRequest) command; @@ -330,10 +344,19 @@ public class OpensyncCloudGatewayController { return response; } - private EquipmentCommandResponse processChangeRedirector(OvsdbSession session, CEGWStartDebugEngine command) { + private EquipmentCommandResponse processChangeRedirector(OvsdbSession session, CEGWChangeRedirectorHost command) { return sendMessage(session, command.getInventoryId(), command); } + private EquipmentCommandResponse processStartDebugEngine(OvsdbSession session, CEGWStartDebugEngine command) { + return sendMessage(session, command.getInventoryId(), command); + } + + private EquipmentCommandResponse processStopDebugEngine(OvsdbSession session, CEGWStopDebugEngine command) { + return sendMessage(session, command.getInventoryId(), command); + } + + private EquipmentCommandResponse processBlinkRequest(OvsdbSession session, CEGWBlinkRequest command) { return sendMessage(session, command.getInventoryId(), command); @@ -403,11 +426,10 @@ public class OpensyncCloudGatewayController { } /** - * This method does the following: - * See WIFI-540 - * 1. Retrieves the existing list of Gateway entries from the Routing Service - * 2. Check each one of them for reachability (using PING method) - * 3. If the Gw does not respond (stale IP), they will be unregistered/cleaned + * This method does the following: See WIFI-540 1. Retrieves the existing + * list of Gateway entries from the Routing Service 2. Check each one of + * them for reachability (using PING method) 3. If the Gw does not respond + * (stale IP), they will be unregistered/cleaned */ protected void cleanupStaleGwRecord() { LOG.debug("In CleanUp stale registered Gateways records "); @@ -433,10 +455,11 @@ public class OpensyncCloudGatewayController { } else { LOG.debug("No gateways registered with Routing Service"); } - } catch (Exception ex) { // Catching Exception to prevent crashing the register thread - LOG.debug("Generic Exception encountered when trying to cleanup " + - "the stale not-reachable GateWays. Continuing to register the new Gateway." + - " Error: {} ", ex.getMessage()); + } catch (Exception ex) { // Catching Exception to prevent crashing the + // register thread + LOG.debug("Generic Exception encountered when trying to cleanup " + + "the stale not-reachable GateWays. Continuing to register the new Gateway." + " Error: {} ", + ex.getMessage()); } } @@ -514,13 +537,14 @@ public class OpensyncCloudGatewayController { } /** - * Deletes the Equipment to Gateway relationship for gateway's that don't respond - * See WIFI-540 - * 1. Get List of EquipmentRoutingRecords for an Equipment - * 2. Get the GW from GW-Id associated with 'this' EquipmentRoutingRecord - * 3. Try to ping the gateway - * 4. If ping fails or Gateway does not exist, delete the equipmentRouting entry. - * @param equipmentId: Equipment's ID + * Deletes the Equipment to Gateway relationship for gateway's that don't + * respond See WIFI-540 1. Get List of EquipmentRoutingRecords for an + * Equipment 2. Get the GW from GW-Id associated with 'this' + * EquipmentRoutingRecord 3. Try to ping the gateway 4. If ping fails or + * Gateway does not exist, delete the equipmentRouting entry. + * + * @param equipmentId: + * Equipment's ID */ protected void cleanupStaleEqptRoutingRecord(Long equipmentId) { LOG.debug("In Clean Up stale Equipment Routing record for Equipment ID {}", equipmentId); @@ -533,27 +557,31 @@ public class OpensyncCloudGatewayController { if (gwRec != null) { if (!isGwReachable(gwRec.getIpAddr(), gwRec.getPort())) { // GW isn't reachable --> invoke unregister - LOG.debug("Gateway {} is not-reachable... Deleting the equipment routing entry", gwRec.getHostname()); + LOG.debug("Gateway {} is not-reachable... Deleting the equipment routing entry", + gwRec.getHostname()); deleteUnresponiveGwRoutingRecord(eqRouting.getId(), equipmentId); } else { LOG.debug("Gateway {} is reachable.", gwRec.getHostname()); } } else { - LOG.debug("Gateway with ID {} not found. Deleting the equipment routing entry ", eqRouting.getGatewayId()); + LOG.debug("Gateway with ID {} not found. Deleting the equipment routing entry ", + eqRouting.getGatewayId()); deleteUnresponiveGwRoutingRecord(eqRouting.getId(), equipmentId); } } catch (DsEntityNotFoundException entityNotFoundException) { - LOG.debug("Gateway ID: {} not found... Deleting the equipment routing entry", eqRouting.getGatewayId()); + LOG.debug("Gateway ID: {} not found... Deleting the equipment routing entry", + eqRouting.getGatewayId()); deleteUnresponiveGwRoutingRecord(eqRouting.getId(), equipmentId); } } } else { LOG.debug("No gateways registered with Routing Service for Equipment ID {}", equipmentId); } - } catch (Exception genericException) { // Catching Exception to prevent crashing the register thread - LOG.debug("Generic Exception encountered when trying to cleanup " + - "the stale routing records for equipment ID: {}. Continuing to register the new RoutingRecord." + - " Error: {} ", equipmentId, genericException.getMessage()); + } catch (Exception genericException) { // Catching Exception to prevent + // crashing the register thread + LOG.debug("Generic Exception encountered when trying to cleanup " + + "the stale routing records for equipment ID: {}. Continuing to register the new RoutingRecord." + + " Error: {} ", equipmentId, genericException.getMessage()); } } @@ -562,8 +590,8 @@ public class OpensyncCloudGatewayController { eqRoutingSvc.delete(routingId); } catch (RuntimeException e) { // failed - LOG.error("Failed to delete Equipment routing record (ID={}) from Routing Service: {}", - eqptId, e.getLocalizedMessage()); + LOG.error("Failed to delete Equipment routing record (ID={}) from Routing Service: {}", eqptId, + e.getLocalizedMessage()); return false; } return true; diff --git a/opensync-ext-interface/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/OvsdbClientInterface.java b/opensync-ext-interface/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/OvsdbClientInterface.java index 4071407..18b183d 100644 --- a/opensync-ext-interface/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/OvsdbClientInterface.java +++ b/opensync-ext-interface/src/main/java/com/telecominfraproject/wlan/opensync/external/integration/OvsdbClientInterface.java @@ -9,7 +9,11 @@ public interface OvsdbClientInterface { Set getConnectedClientIds(); - String changeRedirectorAddress(String apId, String newRedirectorAddress); + String changeRedirectorHost(String apId, String newRedirectorHost); + + String startDebugEngine(String apId, String gatewayHostname, Integer gatewayPort); + + String stopDebugEngine(String apId); void processConfigChanged(String apId); diff --git a/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/experiment/OpenSyncGatewayController.java b/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/experiment/OpenSyncGatewayController.java index 03d27eb..c223f0f 100644 --- a/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/experiment/OpenSyncGatewayController.java +++ b/opensync-gateway/src/main/java/com/telecominfraproject/wlan/opensync/experiment/OpenSyncGatewayController.java @@ -34,7 +34,7 @@ public class OpenSyncGatewayController { @RequestMapping(value = "/changeRedirectorAddress", method = RequestMethod.POST) public String changeRedirectorAddress(@RequestParam String apId, @RequestParam String newRedirectorAddress) { LOG.info("Changing redirector address for AP {} to {}", apId, newRedirectorAddress); - String ret = tipwlanOvsdbClient.changeRedirectorAddress(apId, newRedirectorAddress); + String ret = tipwlanOvsdbClient.changeRedirectorHost(apId, newRedirectorAddress); LOG.info("Changed redirector address for AP {} to {}", apId, ret); return ret; } 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 0355e7e..c982ac6 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 @@ -235,7 +235,7 @@ public class TipWlanOvsdbClient implements OvsdbClientInterface { * @return updated value of the redirector */ @Override - public String changeRedirectorAddress(String apId, String newRedirectorAddress) { + public String changeRedirectorHost(String apId, String newRedirectorAddress) { OvsdbSession ovsdbSession = ovsdbSessionMapInterface.getSession(apId); if (ovsdbSession == null) { throw new IllegalStateException("AP with id " + apId + " is not connected"); @@ -746,4 +746,38 @@ public class TipWlanOvsdbClient implements OvsdbClientInterface { return "Initiated firmware flash for AP " + apId + " to " + firmwareVersion; } + @Override + public String startDebugEngine(String apId, String gatewayHostname, Integer gatewayPort) { + LOG.debug("TipWlanOvsdbClient::startDebugEngine apId {} gatewayHostname {} gatewayPort {}", apId,gatewayHostname,gatewayPort); + + OvsdbSession session = ovsdbSessionMapInterface.getSession(apId); + OvsdbClient ovsdbClient = session.getOvsdbClient(); + + // TODO: need to establish what the command will be to start debug logging, on the AP side + // For now, use start_debug_engine + // Map will have gateway_host and gateway_port for now + // Delay/Duration TBD, just use 0s for now + Map payload = new HashMap<>(); + payload.put("gateway_hostname", gatewayHostname); + payload.put("gateway_port", gatewayPort.toString()); + ovsdbDao.configureCommands(ovsdbClient, OvsdbDao.StartDebugEngineApCommand, payload, Long.valueOf(0L), Long.valueOf(0L)); + + LOG.debug("Started debug engine on AP {} with gateway {} port {}", apId, gatewayHostname, gatewayPort); + return "Started debug engine on AP " + apId + " with gateway " + gatewayHostname + " port " + gatewayPort; + } + + @Override + public String stopDebugEngine(String apId) { + LOG.debug("TipWlanOvsdbClient::stopDebugEngine apId {}", apId); + + OvsdbSession session = ovsdbSessionMapInterface.getSession(apId); + OvsdbClient ovsdbClient = session.getOvsdbClient(); + + Map payload = new HashMap<>(); + ovsdbDao.configureCommands(ovsdbClient, OvsdbDao.StopDebugEngineApCommand, payload, Long.valueOf(0L), Long.valueOf(0L)); + + LOG.debug("Stop debug engine on AP {}", apId); + return "Stop debug engine on AP " + apId ; + } + } 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 8b7469c..1252304 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 @@ -177,6 +177,10 @@ public class OvsdbDao { public static final String commandStateDbTable = "Command_State"; + public static final String StartDebugEngineApCommand = "start_debug_engine"; + + public static final String StopDebugEngineApCommand = "stop_debug_engine"; + public ConnectNodeInfo getConnectNodeInfo(OvsdbClient ovsdbClient) { ConnectNodeInfo ret = new ConnectNodeInfo(); @@ -988,10 +992,10 @@ public class OvsdbDao { return ret; } - + public Map getProvisionedCommandConfigs(OvsdbClient ovsdbClient) { Map ret = new HashMap<>(); - + List operations = new ArrayList<>(); List conditions = new ArrayList<>(); List columns = new ArrayList<>(); @@ -1002,7 +1006,7 @@ public class OvsdbDao { columns.add("command"); columns.add("payload"); columns.add("timestamp"); - + try { LOG.debug("Retrieving CommandConfig:"); @@ -1019,24 +1023,24 @@ public class OvsdbDao { CommandConfigInfo commandConfigInfo = new CommandConfigInfo(); commandConfigInfo.uuid = row.getUuidColumn("_uuid"); - commandConfigInfo.delay = row.getIntegerColumn("delay"); + commandConfigInfo.delay = row.getIntegerColumn("delay"); commandConfigInfo.duration = row.getIntegerColumn("duration"); commandConfigInfo.command = row.getStringColumn("command"); commandConfigInfo.payload = row.getMapColumn("payload"); commandConfigInfo.timestamp = row.getIntegerColumn("timestamp"); - + ret.put(commandConfigInfo.command, commandConfigInfo); } LOG.debug("Retrieved CommandConfig: {}", ret); - + } catch (ExecutionException | InterruptedException | OvsdbClientException | TimeoutException e) { - + LOG.error("Error in getProvisionedCommandConfigs", e); throw new RuntimeException(e); - } - + } + return ret; } @@ -2202,6 +2206,8 @@ public class OvsdbDao { public void configureCommands(OvsdbClient ovsdbClient, String command, Map payload, Long delay, Long duration) { + LOG.debug("OvsdbDao::configureCommands command {}, payload {}, delay {} duration {}", command, payload, delay, + duration); List operations = new ArrayList<>(); Map commandConfigColumns = new HashMap<>(); @@ -2226,13 +2232,13 @@ public class OvsdbDao { CompletableFuture fResult = ovsdbClient.transact(ovsdbName, operations); OperationResult[] result = fResult.get(ovsdbTimeoutSec, TimeUnit.SECONDS); - LOG.debug("Configured command {} for duration {} payload {}", command, duration, payload); + LOG.debug("OvsdbDao::configureCommands successfully configured command {} for duration {} payload {}", command, duration, payload); for (OperationResult res : result) { LOG.debug("Op Result {}", res); } } catch (OvsdbClientException | InterruptedException | ExecutionException | TimeoutException e) { - LOG.error("configureCommands interrupted.", e); + LOG.error("OvsdbDao::configureCommands failed.", e); throw new RuntimeException(e); } @@ -3065,7 +3071,8 @@ public class OvsdbDao { } } - // TODO: when schema support is added, these should be part of the bulk provisioning operation above. + // TODO: when schema support is added, these should be part of the + // bulk provisioning operation above. provisionUccStatsConfig(ovsdbClient); provisionEventReporting(ovsdbClient); @@ -3327,7 +3334,7 @@ public class OvsdbDao { * */ public void provisionEventReporting(OvsdbClient ovsdbClient) { - + LOG.debug("Enable event reporting from AP"); try {