mirror of
https://github.com/Telecominfraproject/wlan-cloud-opensync-controller.git
synced 2025-11-18 10:54:59 +00:00
WIFI-540: Introduce methods to cleanup stale GW and Routing record entries when we bounce the GW pod and it gets a new IP Address
This commit is contained in:
@@ -28,6 +28,11 @@
|
|||||||
<groupId>com.telecominfraproject.wlan</groupId>
|
<groupId>com.telecominfraproject.wlan</groupId>
|
||||||
<version>${tip-wlan-cloud.release.version}</version>
|
<version>${tip-wlan-cloud.release.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<artifactId>base-client</artifactId>
|
||||||
|
<groupId>com.telecominfraproject.wlan</groupId>
|
||||||
|
<version>${tip-wlan-cloud.release.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<artifactId>equipment-gateway-models</artifactId>
|
<artifactId>equipment-gateway-models</artifactId>
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ import java.util.function.Consumer;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import com.telecominfraproject.wlan.core.model.service.GatewayType;
|
||||||
|
import com.telecominfraproject.wlan.core.client.PingClient;
|
||||||
|
import com.telecominfraproject.wlan.datastore.exceptions.DsEntityNotFoundException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -78,6 +81,9 @@ public class OpensyncCloudGatewayController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private OvsdbClientInterface tipwlanOvsdbClient;
|
private OvsdbClientInterface tipwlanOvsdbClient;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PingClient pingClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag indicates if this gateway has registered with routing service
|
* Flag indicates if this gateway has registered with routing service
|
||||||
*/
|
*/
|
||||||
@@ -215,7 +221,6 @@ public class OpensyncCloudGatewayController {
|
|||||||
*
|
*
|
||||||
* @param session
|
* @param session
|
||||||
* @param command
|
* @param command
|
||||||
* @param protocolVersion
|
|
||||||
* @return NoRouteToCE if route Id does not match or Success
|
* @return NoRouteToCE if route Id does not match or Success
|
||||||
*/
|
*/
|
||||||
private EquipmentCommandResponse checkEquipmentRouting(OvsdbSession session, CEGWRouteCheck command) {
|
private EquipmentCommandResponse checkEquipmentRouting(OvsdbSession session, CEGWRouteCheck command) {
|
||||||
@@ -267,7 +272,6 @@ public class OpensyncCloudGatewayController {
|
|||||||
* @param session
|
* @param session
|
||||||
* @param inventoryId
|
* @param inventoryId
|
||||||
* @param command
|
* @param command
|
||||||
* @param request
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private EquipmentCommandResponse sendMessage(OvsdbSession session, String inventoryId, EquipmentCommand command) {
|
private EquipmentCommandResponse sendMessage(OvsdbSession session, String inventoryId, EquipmentCommand command) {
|
||||||
@@ -373,6 +377,8 @@ public class OpensyncCloudGatewayController {
|
|||||||
throw new ConfigurationException(
|
throw new ConfigurationException(
|
||||||
"Unable to register gateway with routing service: routing service interface not initialized");
|
"Unable to register gateway with routing service: routing service interface not initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cleanupStaleGwRecord();
|
||||||
EquipmentGatewayRecord gwRecord = new EquipmentGatewayRecord();
|
EquipmentGatewayRecord gwRecord = new EquipmentGatewayRecord();
|
||||||
|
|
||||||
// external facing service, protected by the client certificate auth
|
// external facing service, protected by the client certificate auth
|
||||||
@@ -396,6 +402,42 @@ 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
|
||||||
|
*/
|
||||||
|
protected void cleanupStaleGwRecord() {
|
||||||
|
LOG.debug("In CleanUp stale registered Gateways records ");
|
||||||
|
// Get Equipment gateway list
|
||||||
|
List<EquipmentGatewayRecord> eqGwRecList = eqRoutingSvc.getGateway(GatewayType.CEGW);
|
||||||
|
if (eqGwRecList != null) {
|
||||||
|
for (EquipmentGatewayRecord eqpRec : eqGwRecList) {
|
||||||
|
if (!isGwReachable(eqpRec.getIpAddr(), eqpRec.getPort())) {
|
||||||
|
// GW isn't reachable --> invoke deleteGw
|
||||||
|
LOG.debug("Gateway {} is not-reachable... deleting from Routing Svc", eqpRec.getHostname());
|
||||||
|
try {
|
||||||
|
eqRoutingSvc.deleteGateway(eqpRec.getId());
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// failed
|
||||||
|
LOG.error("Failed to delete Equipment Gateway (name={}) from Routing Service: {}",
|
||||||
|
eqpRec.getHostname(), e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG.debug("Gateway {} is reachable.", eqpRec.getHostname());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG.debug("No gateways registered with Routing Service");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isGwReachable(String ipAddr, int port) {
|
||||||
|
return pingClient.isReachable(ipAddr, port);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the current deployment identifier
|
* Return the current deployment identifier
|
||||||
*
|
*
|
||||||
@@ -445,6 +487,8 @@ public class OpensyncCloudGatewayController {
|
|||||||
equipmentId);
|
equipmentId);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
// Clean up stale records
|
||||||
|
cleanupStaleEqptRoutingRecord(equipmentId);
|
||||||
EquipmentRoutingRecord routingRecord = new EquipmentRoutingRecord();
|
EquipmentRoutingRecord routingRecord = new EquipmentRoutingRecord();
|
||||||
routingRecord.setCustomerId(customerId);
|
routingRecord.setCustomerId(customerId);
|
||||||
routingRecord.setEquipmentId(equipmentId);
|
routingRecord.setEquipmentId(equipmentId);
|
||||||
@@ -463,6 +507,61 @@ public class OpensyncCloudGatewayController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
List<EquipmentRoutingRecord> eqptRoutingRecsList = eqRoutingSvc.getRegisteredRouteList(equipmentId);
|
||||||
|
if (eqptRoutingRecsList != null) {
|
||||||
|
for(EquipmentRoutingRecord eqRouting : eqptRoutingRecsList) {
|
||||||
|
try {
|
||||||
|
EquipmentGatewayRecord gwRec = eqRoutingSvc.getGateway(eqRouting.getGatewayId());
|
||||||
|
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());
|
||||||
|
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());
|
||||||
|
deleteUnresponiveGwRoutingRecord(eqRouting.getId(), equipmentId);
|
||||||
|
}
|
||||||
|
} catch ( DsEntityNotFoundException entityNotFoundException) {
|
||||||
|
LOG.debug("Gateway ID: {} not found... Deleting the equipment routing entry", eqRouting.getGatewayId());
|
||||||
|
deleteUnresponiveGwRoutingRecord(eqRouting.getId(), equipmentId);
|
||||||
|
} catch ( Exception genericException) {
|
||||||
|
LOG.debug("Generic Exception encountered when trying to query/delete " +
|
||||||
|
"the Gateway with ID: {}. Error: {} ", eqRouting.getGatewayId(), genericException.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
LOG.debug("No gateways registered with Routing Service for Equipment ID {}", equipmentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean deleteUnresponiveGwRoutingRecord(Long routingId, Long eqptId) {
|
||||||
|
try {
|
||||||
|
eqRoutingSvc.delete(routingId);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// failed
|
||||||
|
LOG.error("Failed to delete Equipment routing record (ID={}) from Routing Service: {}",
|
||||||
|
eqptId, e.getLocalizedMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void deregisterCustomerEquipment(Long routingId, String equipmentName, Long equipmentId) {
|
public void deregisterCustomerEquipment(Long routingId, String equipmentName, Long equipmentId) {
|
||||||
if (!registeredWithRoutingService) {
|
if (!registeredWithRoutingService) {
|
||||||
LOG.error("Unable to deregister customer equipement (name={},id={}): gateway not registered", equipmentName,
|
LOG.error("Unable to deregister customer equipement (name={},id={}): gateway not registered", equipmentName,
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package com.telecominfraproject.wlan.opensync.external.integration.controller;
|
||||||
|
|
||||||
|
import com.telecominfraproject.wlan.core.client.PingClient;
|
||||||
|
import com.telecominfraproject.wlan.core.model.service.GatewayType;
|
||||||
|
import com.telecominfraproject.wlan.datastore.exceptions.DsEntityNotFoundException;
|
||||||
|
import com.telecominfraproject.wlan.routing.RoutingServiceInterface;
|
||||||
|
import com.telecominfraproject.wlan.routing.models.EquipmentGatewayRecord;
|
||||||
|
import com.telecominfraproject.wlan.routing.models.EquipmentRoutingRecord;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.atLeast;
|
||||||
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
|
||||||
|
class OpensyncCloudGatewayControllerTest {
|
||||||
|
|
||||||
|
OpensyncCloudGatewayController opensyncCloudGatewayController = new OpensyncCloudGatewayController();
|
||||||
|
|
||||||
|
RoutingServiceInterface routingSvc = Mockito.mock(RoutingServiceInterface.class);
|
||||||
|
PingClient pingClient = Mockito.mock(PingClient.class);
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
ReflectionTestUtils.setField(opensyncCloudGatewayController, "eqRoutingSvc", routingSvc);
|
||||||
|
ReflectionTestUtils.setField(opensyncCloudGatewayController, "pingClient", pingClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void cleanupStaleGwRecord() throws IOException {
|
||||||
|
EquipmentGatewayRecord gatewayRecord = readGatewayRecord();
|
||||||
|
Mockito.when(pingClient.isReachable(anyString(), anyInt())).thenReturn(true);
|
||||||
|
opensyncCloudGatewayController.cleanupStaleGwRecord();
|
||||||
|
verify(pingClient, atLeastOnce()).isReachable("1.1.1.1",123);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void cleanupStaleGwRecord_pingFail() throws IOException {
|
||||||
|
EquipmentGatewayRecord gatewayRecord = readGatewayRecord();
|
||||||
|
Mockito.when(pingClient.isReachable(anyString(), anyInt())).thenReturn(false);
|
||||||
|
Mockito.when(routingSvc.deleteGateway(anyLong())).thenReturn(gatewayRecord);
|
||||||
|
opensyncCloudGatewayController.cleanupStaleGwRecord();
|
||||||
|
verify(routingSvc, atLeastOnce()).deleteGateway(gatewayRecord.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void cleanupStaleEqptRoutingRecord_NoEntityFound() throws IOException {
|
||||||
|
EquipmentRoutingRecord routingRecord = readRoutingRecord();
|
||||||
|
Mockito.when(routingSvc.getGateway(anyLong())).thenThrow(new DsEntityNotFoundException());
|
||||||
|
Mockito.when(routingSvc.delete(anyLong())).thenReturn(new EquipmentRoutingRecord());
|
||||||
|
|
||||||
|
opensyncCloudGatewayController.cleanupStaleEqptRoutingRecord(123L);
|
||||||
|
verify(routingSvc, atLeastOnce()).delete(routingRecord.getId());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void cleanupStaleEqptRoutingRecord_GenericException() throws IOException {
|
||||||
|
EquipmentRoutingRecord routingRecord = readRoutingRecord();
|
||||||
|
Mockito.when(routingSvc.getGateway(anyLong())).thenThrow(new RuntimeException("Throwing exception to test"));
|
||||||
|
Mockito.when(routingSvc.delete(anyLong())).thenReturn(new EquipmentRoutingRecord());
|
||||||
|
|
||||||
|
opensyncCloudGatewayController.cleanupStaleEqptRoutingRecord(123L);
|
||||||
|
verify(routingSvc, atLeast(0)).delete(routingRecord.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void cleanupStaleEqptRoutingRecord_GatewayResponds() throws IOException {
|
||||||
|
EquipmentRoutingRecord routingRecord = readRoutingRecord();
|
||||||
|
EquipmentGatewayRecord gatewayRecord = readGatewayRecord();
|
||||||
|
Mockito.when(routingSvc.getGateway(anyLong())).thenReturn(gatewayRecord);
|
||||||
|
Mockito.when(routingSvc.delete(anyLong())).thenReturn(new EquipmentRoutingRecord());
|
||||||
|
Mockito.when(pingClient.isReachable(anyString(), anyInt())).thenReturn(true);
|
||||||
|
|
||||||
|
opensyncCloudGatewayController.cleanupStaleEqptRoutingRecord(123L);
|
||||||
|
verify(routingSvc, atLeast(0)).delete(routingRecord.getId());
|
||||||
|
verify(pingClient, atLeastOnce()).isReachable(anyString(), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void cleanupStaleEqptRoutingRecord_GatewayFails() throws IOException {
|
||||||
|
EquipmentRoutingRecord routingRecord = readRoutingRecord();
|
||||||
|
EquipmentGatewayRecord gatewayRecord = readGatewayRecord();
|
||||||
|
Mockito.when(routingSvc.getGateway(anyLong())).thenReturn(gatewayRecord);
|
||||||
|
Mockito.when(routingSvc.delete(anyLong())).thenReturn(new EquipmentRoutingRecord());
|
||||||
|
Mockito.when(pingClient.isReachable(anyString(), anyInt())).thenReturn(false);
|
||||||
|
|
||||||
|
opensyncCloudGatewayController.cleanupStaleEqptRoutingRecord(123L);
|
||||||
|
verify(routingSvc, atLeastOnce()).delete(routingRecord.getId());
|
||||||
|
verify(pingClient, atLeastOnce()).isReachable(anyString(), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
private EquipmentGatewayRecord readGatewayRecord() throws IOException {
|
||||||
|
EquipmentGatewayRecord gatewayRecord = EquipmentGatewayRecord.fromFile(
|
||||||
|
OpensyncCloudGatewayControllerTest.class.getResource("EquipmentGatewayRecords.json").getFile(),
|
||||||
|
EquipmentGatewayRecord.class);
|
||||||
|
|
||||||
|
Mockito.when(routingSvc.getGateway(GatewayType.CEGW)).thenReturn(Arrays.asList(gatewayRecord));
|
||||||
|
return gatewayRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
private EquipmentRoutingRecord readRoutingRecord() throws IOException {
|
||||||
|
EquipmentRoutingRecord routingRecord = EquipmentRoutingRecord.fromFile(
|
||||||
|
OpensyncCloudGatewayControllerTest.class.getResource("EquipmentRoutingRecord.json").getFile(),
|
||||||
|
EquipmentRoutingRecord.class);
|
||||||
|
|
||||||
|
Mockito.when(routingSvc.getRegisteredRouteList(anyLong())).thenReturn(Arrays.asList(routingRecord));
|
||||||
|
return routingRecord;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"hostname": "Host-1",
|
||||||
|
"ipAddr": "1.1.1.1",
|
||||||
|
"port": 123,
|
||||||
|
"gatewayType": "CEGW",
|
||||||
|
"createdTimestamp": 0,
|
||||||
|
"lastModifiedTimestamp": 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"equipmentId": 123,
|
||||||
|
"customerId": 2,
|
||||||
|
"gatewayId": 110,
|
||||||
|
"createdTimestamp": 0,
|
||||||
|
"lastModifiedTimestamp": 0
|
||||||
|
}
|
||||||
@@ -29,7 +29,11 @@
|
|||||||
<groupId>com.telecominfraproject.wlan</groupId>
|
<groupId>com.telecominfraproject.wlan</groupId>
|
||||||
<version>${tip-wlan-cloud.release.version}</version>
|
<version>${tip-wlan-cloud.release.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<artifactId>base-client</artifactId>
|
||||||
|
<groupId>com.telecominfraproject.wlan</groupId>
|
||||||
|
<version>${tip-wlan-cloud.release.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<artifactId>filestore-service</artifactId>
|
<artifactId>filestore-service</artifactId>
|
||||||
<groupId>com.telecominfraproject.wlan</groupId>
|
<groupId>com.telecominfraproject.wlan</groupId>
|
||||||
|
|||||||
Reference in New Issue
Block a user