TW-208: ChannelInfoReport from Survey, RSSI metrics enable

This commit is contained in:
Mike Hansen
2020-03-25 16:00:13 -04:00
parent 78de332437
commit 03e627fb26
2 changed files with 1931 additions and 1888 deletions

View File

@@ -36,264 +36,278 @@ import io.netty.handler.ssl.SslContext;
@Component
public class ConnectusOvsdbClient implements ConnectusOvsdbClientInterface {
private static final Logger LOG = LoggerFactory.getLogger(ConnectusOvsdbClient.class);
private static final Logger LOG = LoggerFactory.getLogger(ConnectusOvsdbClient.class);
@org.springframework.beans.factory.annotation.Value("${connectus.ovsdb.listenPort:6640}")
private int ovsdbListenPort;
@org.springframework.beans.factory.annotation.Value("${connectus.ovsdb.listenPort:6640}")
private int ovsdbListenPort;
@org.springframework.beans.factory.annotation.Value("${connectus.manager.collectionIntervalSec.deviceStats:10}")
private long collectionIntervalSecDeviceStats;
@org.springframework.beans.factory.annotation.Value("${connectus.manager.collectionIntervalSec.deviceStats:10}")
private long collectionIntervalSecDeviceStats;
@Autowired
private SslContext sslContext;
@Autowired
private SslContext sslContext;
@Autowired
private OvsdbPassiveConnectionListener listener;
@Autowired
private OvsdbPassiveConnectionListener listener;
@Autowired
private OvsdbDao ovsdbDao;
@Autowired
private OvsdbDao ovsdbDao;
@Autowired
private OpensyncExternalIntegrationInterface extIntegrationInterface;
@Autowired
private OpensyncExternalIntegrationInterface extIntegrationInterface;
@Autowired
private OvsdbSessionMapInterface ovsdbSessionMapInterface;
@Autowired
private OvsdbSessionMapInterface ovsdbSessionMapInterface;
@PostConstruct
private void postCreate() {
listenForConnections();
}
@PostConstruct
private void postCreate() {
listenForConnections();
}
public void listenForConnections() {
public void listenForConnections() {
// This class is only used here, therefore changed it back to an inner class,
// removed the package level class.
// All calling classes related to OVSDB are calling the MonitorCallback
// interface, so the implementation can remain
// hidden. This also gives handy access to the Autowired instances in the
// container class.
// This class is only used here, therefore changed it back to an inner
// class,
// removed the package level class.
// All calling classes related to OVSDB are calling the MonitorCallback
// interface, so the implementation can remain
// hidden. This also gives handy access to the Autowired instances in
// the
// container class.
class ConnectusMonitorCallback implements MonitorCallback {
class ConnectusMonitorCallback implements MonitorCallback {
private String connectedClientId;
private String connectedClientId;
public ConnectusMonitorCallback(String clientId) {
this.connectedClientId = clientId;
}
public ConnectusMonitorCallback(String clientId) {
this.connectedClientId = clientId;
}
@Override
public void update(TableUpdates tableUpdates) {
Set<String> tableNames = tableUpdates.getTableUpdates().keySet();
@Override
public void update(TableUpdates tableUpdates) {
Set<String> tableNames = tableUpdates.getTableUpdates().keySet();
for (String name : tableNames) {
LOG.debug("Receive update for table {}", name);
for (String name : tableNames) {
LOG.trace("Receive update for table {}", name);
Map<UUID, RowUpdate> updates = tableUpdates.getTableUpdates().get(name).getRowUpdates();
for (UUID id : updates.keySet()) {
Map<UUID, RowUpdate> updates = tableUpdates.getTableUpdates().get(name).getRowUpdates();
for (UUID id : updates.keySet()) {
LOG.debug("Receive row update for uuid {}", id);
RowUpdate rowUpdate = updates.get(id);
Row newRow = rowUpdate.getNew();
Set<String> newRowColumns = newRow.getColumns().keySet();
Row oldRow = rowUpdate.getOld();
for (String column : newRowColumns) {
Value oldVal = null;
if (oldRow != null && oldRow.getColumns().containsKey(column)) oldVal = oldRow.getColumns().get(column);
Value newVal = newRow.getColumns().get(column);
LOG.debug("For column {} previous value {} is now {}", column, oldVal, newVal);
}
}
}
// get session information for this client
// OvsdbSession ovsdbSession = ovsdbSessionMapInterface.getSession(connectedClientId);
// if (ovsdbSession == null) {
// throw new IllegalStateException("AP with id " + connectedClientId + " is not connected");
// }
//
// OvsdbClient ovsdbClient = ovsdbSession.getOvsdbClient();
// OpensyncAPConfig opensyncAPConfig = extIntegrationInterface.getApConfig(connectedClientId);
// TODO:
// example wifiVifStateDbTable get MAC ADDRESS via ovsdbClient from
// Wifi_Associated_Clients given the associated UUID for the client
// TODO:
// Changes from other Status (Wifi, Inet, etc.) tables?
// Updates to session etc.
// Needs to be reflected in the Cloud
}
}
ConnectionCallback connectionCallback = new ConnectionCallback() {
public void connected(OvsdbClient ovsdbClient) {
String remoteHost = ovsdbClient.getConnectionInfo().getRemoteAddress().getHostAddress();
int localPort = ovsdbClient.getConnectionInfo().getLocalPort();
String subjectDn = null;
try {
subjectDn = ((X509Certificate) ovsdbClient.getConnectionInfo().getRemoteCertificate())
.getSubjectDN().getName();
String clientCn = SslUtil.extractCN(subjectDn);
LOG.info("ovsdbClient connecting from {} on port {} clientCn {}", remoteHost, localPort, clientCn);
ConnectNodeInfo connectNodeInfo = ovsdbDao.getConnectNodeInfo(ovsdbClient);
// successfully connected - register it in our connectedClients table
// In Plume's environment clientCn is not unique that's why we are augmenting it
// with the serialNumber and using it as a key (equivalent of KDC unique qrCode)
String key = clientCn + "_" + connectNodeInfo.serialNumber;
ConnectusOvsdbClient.this.ovsdbSessionMapInterface.newSession(key, ovsdbClient);
extIntegrationInterface.apConnected(key, connectNodeInfo);
// push configuration to AP
connectNodeInfo = processConnectRequest(ovsdbClient, clientCn, connectNodeInfo);
LOG.info("ovsdbClient connected from {} on port {} key {} ", remoteHost, localPort, key);
LOG.info("ovsdbClient connectedClients = {}",
ConnectusOvsdbClient.this.ovsdbSessionMapInterface.getNumSessions());
// monitor radio config state
ovsdbDao.monitorRadioConfigState(ovsdbClient, new ConnectusMonitorCallback(key));
// monitor inet state
ovsdbDao.monitorInetState(ovsdbClient, new ConnectusMonitorCallback(key));
// monitor vif state
ovsdbDao.monitorVIFState(ovsdbClient, new ConnectusMonitorCallback(key));
// monitor Route state
ovsdbDao.monitorRouteState(ovsdbClient, new ConnectusMonitorCallback(key));
// monitor Master State
ovsdbDao.monitorMasterState(ovsdbClient, new ConnectusMonitorCallback(key));
} catch (Exception e) {
LOG.error("ovsdbClient error", e);
// something is wrong with the SSL
ovsdbClient.shutdown();
return;
}
}
public void disconnected(OvsdbClient ovsdbClient) {
String remoteHost = ovsdbClient.getConnectionInfo().getRemoteAddress().getHostAddress();
int localPort = ovsdbClient.getConnectionInfo().getLocalPort();
String subjectDn = null;
try {
subjectDn = ((X509Certificate) ovsdbClient.getConnectionInfo().getRemoteCertificate())
.getSubjectDN().getName();
} catch (Exception e) {
// do nothing
}
String clientCn = SslUtil.extractCN(subjectDn);
// disconnected - deregister ovsdbClient from our connectedClients table
// unfortunately we only know clientCn at this point, but in Plume's environment
// they are not unique
// so we are doing a reverse lookup here, and then if we find the key we will
// remove the entry from the connectedClients.
String key = ConnectusOvsdbClient.this.ovsdbSessionMapInterface.lookupClientId(ovsdbClient);
if (key != null) {
extIntegrationInterface.apDisconnected(key);
ConnectusOvsdbClient.this.ovsdbSessionMapInterface.removeSession(key);
}
// turn off monitor
ovsdbDao.cancelMonitors(ovsdbClient);
ovsdbClient.shutdown();
LOG.info("ovsdbClient disconnected from {} on port {} clientCn {} key {} ", remoteHost, localPort,
clientCn, key);
LOG.info("ovsdbClient connectedClients = {}",
ConnectusOvsdbClient.this.ovsdbSessionMapInterface.getNumSessions());
}
};
listener.startListeningWithSsl(ovsdbListenPort, sslContext, connectionCallback).join();
LOG.debug("manager waiting for connection on port {}...", ovsdbListenPort);
}
private ConnectNodeInfo processConnectRequest(OvsdbClient ovsdbClient, String clientCn,
ConnectNodeInfo connectNodeInfo) {
LOG.debug("Starting Client connect");
connectNodeInfo = ovsdbDao.updateConnectNodeInfoOnConnect(ovsdbClient, clientCn, connectNodeInfo);
String apId = clientCn + "_" + connectNodeInfo.serialNumber;
OpensyncAPConfig opensyncAPConfig = extIntegrationInterface.getApConfig(apId);
ovsdbDao.configureStats(ovsdbClient);
// Check if device stats is configured in Wifi_Stats_Config table, provision it
// if needed
if (ovsdbDao.getDeviceStatsReportingInterval(ovsdbClient) != collectionIntervalSecDeviceStats) {
ovsdbDao.updateDeviceStatsReportingInterval(ovsdbClient, collectionIntervalSecDeviceStats);
}
ovsdbDao.provisionBridgePortInterface(ovsdbClient);
ovsdbDao.removeAllSsids(ovsdbClient);
if (opensyncAPConfig != null) {
ovsdbDao.configureWifiRadios(ovsdbClient, opensyncAPConfig.getRadioConfig());
ovsdbDao.configureSsids(ovsdbClient, opensyncAPConfig.getSsidConfigs());
}
ovsdbDao.configureWifiInet(ovsdbClient);
LOG.debug("Client connect Done");
return connectNodeInfo;
}
public Set<String> getConnectedClientIds() {
return ovsdbSessionMapInterface.getConnectedClientIds();
}
/**
* @param apId
* @param newRedirectorAddress
* @return updated value of the redirector
*/
public String changeRedirectorAddress(String apId, String newRedirectorAddress) {
OvsdbSession ovsdbSession = ovsdbSessionMapInterface.getSession(apId);
if (ovsdbSession == null) {
throw new IllegalStateException("AP with id " + apId + " is not connected");
}
String ret = ovsdbDao.changeRedirectorAddress(ovsdbSession.getOvsdbClient(), apId, newRedirectorAddress);
return ret;
}
@Override
public void processConfigChanged(String apId) {
LOG.debug("Starting processConfigChanged for {}", apId);
OvsdbSession ovsdbSession = ovsdbSessionMapInterface.getSession(apId);
if (ovsdbSession == null) {
throw new IllegalStateException("AP with id " + apId + " is not connected");
}
OvsdbClient ovsdbClient = ovsdbSession.getOvsdbClient();
OpensyncAPConfig opensyncAPConfig = extIntegrationInterface.getApConfig(apId);
if (opensyncAPConfig != null) {
ovsdbDao.removeAllSsids(ovsdbClient);
ovsdbDao.configureWifiRadios(ovsdbClient, opensyncAPConfig.getRadioConfig());
ovsdbDao.configureSsids(ovsdbClient, opensyncAPConfig.getSsidConfigs());
}
LOG.debug("Finished processConfigChanged for {}", apId);
}
LOG.trace("Receive row update for uuid {}", id);
RowUpdate rowUpdate = updates.get(id);
Row newRow = rowUpdate.getNew();
if (newRow != null) {
Set<String> newRowColumns = newRow.getColumns().keySet();
Row oldRow = rowUpdate.getOld();
for (String column : newRowColumns) {
Value oldVal = null;
if (oldRow != null && oldRow.getColumns().containsKey(column))
oldVal = oldRow.getColumns().get(column);
Value newVal = newRow.getColumns().get(column);
}
}
}
}
// get session information for this client
// OvsdbSession ovsdbSession =
// ovsdbSessionMapInterface.getSession(connectedClientId);
// if (ovsdbSession == null) {
// throw new IllegalStateException("AP with id " +
// connectedClientId + " is not connected");
// }
//
// OvsdbClient ovsdbClient = ovsdbSession.getOvsdbClient();
// OpensyncAPConfig opensyncAPConfig =
// extIntegrationInterface.getApConfig(connectedClientId);
// TODO:
// example wifiVifStateDbTable get MAC ADDRESS via ovsdbClient
// from
// Wifi_Associated_Clients given the associated UUID for the
// client
// TODO:
// Changes from other Status (Wifi, Inet, etc.) tables?
// Updates to session etc.
// Needs to be reflected in the Cloud
}
}
ConnectionCallback connectionCallback = new ConnectionCallback() {
public void connected(OvsdbClient ovsdbClient) {
String remoteHost = ovsdbClient.getConnectionInfo().getRemoteAddress().getHostAddress();
int localPort = ovsdbClient.getConnectionInfo().getLocalPort();
String subjectDn = null;
try {
subjectDn = ((X509Certificate) ovsdbClient.getConnectionInfo().getRemoteCertificate())
.getSubjectDN().getName();
String clientCn = SslUtil.extractCN(subjectDn);
LOG.info("ovsdbClient connecting from {} on port {} clientCn {}", remoteHost, localPort, clientCn);
ConnectNodeInfo connectNodeInfo = ovsdbDao.getConnectNodeInfo(ovsdbClient);
// successfully connected - register it in our
// connectedClients table
// In Plume's environment clientCn is not unique that's why
// we are augmenting it
// with the serialNumber and using it as a key (equivalent
// of KDC unique qrCode)
String key = clientCn + "_" + connectNodeInfo.serialNumber;
ConnectusOvsdbClient.this.ovsdbSessionMapInterface.newSession(key, ovsdbClient);
extIntegrationInterface.apConnected(key, connectNodeInfo);
// push configuration to AP
connectNodeInfo = processConnectRequest(ovsdbClient, clientCn, connectNodeInfo);
LOG.info("ovsdbClient connected from {} on port {} key {} ", remoteHost, localPort, key);
LOG.info("ovsdbClient connectedClients = {}",
ConnectusOvsdbClient.this.ovsdbSessionMapInterface.getNumSessions());
// monitor radio config state
ovsdbDao.monitorRadioConfigState(ovsdbClient, new ConnectusMonitorCallback(key));
// monitor inet state
ovsdbDao.monitorInetState(ovsdbClient, new ConnectusMonitorCallback(key));
// monitor vif state
ovsdbDao.monitorVIFState(ovsdbClient, new ConnectusMonitorCallback(key));
// monitor Route state
ovsdbDao.monitorRouteState(ovsdbClient, new ConnectusMonitorCallback(key));
// monitor Master State
ovsdbDao.monitorMasterState(ovsdbClient, new ConnectusMonitorCallback(key));
} catch (Exception e) {
LOG.error("ovsdbClient error", e);
// something is wrong with the SSL
ovsdbClient.shutdown();
return;
}
}
public void disconnected(OvsdbClient ovsdbClient) {
String remoteHost = ovsdbClient.getConnectionInfo().getRemoteAddress().getHostAddress();
int localPort = ovsdbClient.getConnectionInfo().getLocalPort();
String subjectDn = null;
try {
subjectDn = ((X509Certificate) ovsdbClient.getConnectionInfo().getRemoteCertificate())
.getSubjectDN().getName();
} catch (Exception e) {
// do nothing
}
String clientCn = SslUtil.extractCN(subjectDn);
// disconnected - deregister ovsdbClient from our
// connectedClients table
// unfortunately we only know clientCn at this point, but in
// Plume's environment
// they are not unique
// so we are doing a reverse lookup here, and then if we find
// the key we will
// remove the entry from the connectedClients.
String key = ConnectusOvsdbClient.this.ovsdbSessionMapInterface.lookupClientId(ovsdbClient);
if (key != null) {
extIntegrationInterface.apDisconnected(key);
ConnectusOvsdbClient.this.ovsdbSessionMapInterface.removeSession(key);
}
// turn off monitor
ovsdbDao.cancelMonitors(ovsdbClient);
ovsdbClient.shutdown();
LOG.info("ovsdbClient disconnected from {} on port {} clientCn {} key {} ", remoteHost, localPort,
clientCn, key);
LOG.info("ovsdbClient connectedClients = {}",
ConnectusOvsdbClient.this.ovsdbSessionMapInterface.getNumSessions());
}
};
listener.startListeningWithSsl(ovsdbListenPort, sslContext, connectionCallback).join();
LOG.debug("manager waiting for connection on port {}...", ovsdbListenPort);
}
private ConnectNodeInfo processConnectRequest(OvsdbClient ovsdbClient, String clientCn,
ConnectNodeInfo connectNodeInfo) {
LOG.debug("Starting Client connect");
connectNodeInfo = ovsdbDao.updateConnectNodeInfoOnConnect(ovsdbClient, clientCn, connectNodeInfo);
String apId = clientCn + "_" + connectNodeInfo.serialNumber;
OpensyncAPConfig opensyncAPConfig = extIntegrationInterface.getApConfig(apId);
ovsdbDao.configureStats(ovsdbClient);
// Check if device stats is configured in Wifi_Stats_Config table,
// provision it
// if needed
if (ovsdbDao.getDeviceStatsReportingInterval(ovsdbClient) != collectionIntervalSecDeviceStats) {
ovsdbDao.updateDeviceStatsReportingInterval(ovsdbClient, collectionIntervalSecDeviceStats);
}
ovsdbDao.provisionBridgePortInterface(ovsdbClient);
ovsdbDao.removeAllSsids(ovsdbClient);
if (opensyncAPConfig != null) {
ovsdbDao.configureWifiRadios(ovsdbClient, opensyncAPConfig.getRadioConfig());
ovsdbDao.configureSsids(ovsdbClient, opensyncAPConfig.getSsidConfigs());
}
ovsdbDao.configureWifiInet(ovsdbClient);
LOG.debug("Client connect Done");
return connectNodeInfo;
}
public Set<String> getConnectedClientIds() {
return ovsdbSessionMapInterface.getConnectedClientIds();
}
/**
* @param apId
* @param newRedirectorAddress
* @return updated value of the redirector
*/
public String changeRedirectorAddress(String apId, String newRedirectorAddress) {
OvsdbSession ovsdbSession = ovsdbSessionMapInterface.getSession(apId);
if (ovsdbSession == null) {
throw new IllegalStateException("AP with id " + apId + " is not connected");
}
String ret = ovsdbDao.changeRedirectorAddress(ovsdbSession.getOvsdbClient(), apId, newRedirectorAddress);
return ret;
}
@Override
public void processConfigChanged(String apId) {
LOG.debug("Starting processConfigChanged for {}", apId);
OvsdbSession ovsdbSession = ovsdbSessionMapInterface.getSession(apId);
if (ovsdbSession == null) {
throw new IllegalStateException("AP with id " + apId + " is not connected");
}
OvsdbClient ovsdbClient = ovsdbSession.getOvsdbClient();
OpensyncAPConfig opensyncAPConfig = extIntegrationInterface.getApConfig(apId);
if (opensyncAPConfig != null) {
ovsdbDao.removeAllSsids(ovsdbClient);
ovsdbDao.configureWifiRadios(ovsdbClient, opensyncAPConfig.getRadioConfig());
ovsdbDao.configureSsids(ovsdbClient, opensyncAPConfig.getSsidConfigs());
}
LOG.debug("Finished processConfigChanged for {}", apId);
}
}