blob: 734cbdcd0293461ddaa5191a1d630908edd022d2 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdxl2;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.edge.EdgePortEvent;
import org.onosproject.net.edge.EdgePortListener;
import org.onosproject.net.edge.EdgePortService;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentListener;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.Key;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Implementation of the SdxL2MonitoringService.
*/
public class SdxL2MonitoringManager implements SdxL2MonitoringService {
private static Logger log = LoggerFactory.getLogger(SdxL2MonitoringManager.class);
protected ApplicationId appId;
private final IntentService intentService;
private final EdgePortService edgePortService;
/**
* It is a local cache for the Intents' events.
*/
private ConcurrentMap<Key, IntentEvent> intentsState;
/**
* Last time intentsState has been updated.
*/
private long lastIntentUpdate;
/**
* It is a local cache for the edge ports related events.
*/
private ConcurrentMap<ConnectPoint, EdgePortEvent> edgeportsState;
/**
* Last time edgeportsState has been updated.
*/
private long lastEdgePortUpdate;
// A kind of timeout which causes a manual update.
private static int deltaUpdate = 60000;
private InternalIntentListener intentListener;
private InternalEdgePortListener edgePortListener;
/**
* Creates an SdxL2MonitoringManager.
*
* @param sdxl2id application id.
* @param intentService reference to the Intent service.
* @param edgePortService reference to the EdgePort service.
*/
public SdxL2MonitoringManager(ApplicationId sdxl2id, IntentService intentService, EdgePortService edgePortService) {
this.appId = sdxl2id;
this.intentListener = new InternalIntentListener();
this.edgePortListener = new InternalEdgePortListener();
this.intentService = intentService;
this.edgePortService = edgePortService;
this.intentService.addListener(this.intentListener);
this.edgePortService.addListener(this.edgePortListener);
this.intentsState = new ConcurrentHashMap<>();
this.edgeportsState = new ConcurrentHashMap<>();
this.lastEdgePortUpdate = 0;
this.lastIntentUpdate = 0;
log.info("Started");
}
/**
* Remove listeners.
*/
public void cleanup() {
this.intentService.removeListener(intentListener);
this.edgePortService.removeListener(edgePortListener);
}
/**
* Returns the state of the Intent that has been provided as input.
*
* @param intentKey key of the intent;
* @return the last state of the intent;
*/
@Override
public SdxL2State getIntentState(Key intentKey) {
synchronized (intentsState) {
IntentEvent event = this.intentsState.get(intentKey);
long ts = System.currentTimeMillis();
if (event == null || (ts > lastIntentUpdate && ts - lastIntentUpdate > deltaUpdate)) {
Intent intent = this.intentService.getIntent(intentKey);
IntentState intentState = this.intentService.getIntentState(intentKey);
event = IntentEvent.getEvent(intentState, intent).get();
intentsState.put(intentKey, event);
this.lastIntentUpdate = ts;
}
return this.getSdxL2State(event.type());
}
}
/**
* Updates intentsState after an Intent event.
*
* @param event the event just happened
*/
private void processIntentEvent(IntentEvent event) {
synchronized (intentsState) {
intentsState.put(event.subject().key(), event);
this.lastIntentUpdate = System.currentTimeMillis();
}
}
/**
* Translates the type of the IntentEvent in SdxL2State.
*
* @param type the type of event
* @return the SdxL2State
*/
private SdxL2State getSdxL2State(IntentEvent.Type type) {
SdxL2State state;
switch (type) {
case INSTALLED:
state = SdxL2State.ONLINE;
break;
case FAILED:
state = SdxL2State.OFFLINE;
break;
case INSTALL_REQ:
case WITHDRAW_REQ:
case WITHDRAWN:
case CORRUPT:
case PURGED:
default:
state = SdxL2State.CHECK;
}
return state;
}
private class InternalIntentListener implements IntentListener {
/**
* Reacts to the specified event.
*
* @param event event to be processed
*/
@Override
public void event(IntentEvent event) {
Intent intent = event.subject();
if (intent.appId().equals(appId)) {
if (event.type() == IntentEvent.Type.INSTALLED ||
event.type() == IntentEvent.Type.FAILED ||
event.type() == IntentEvent.Type.WITHDRAWN) {
log.info("Intent {} {}", event.subject().key(), event.type());
}
processIntentEvent(event);
}
}
}
/**
* Returns the state of the EdgePort that has been provided as input.
*
* @param edgeport the connect point representing the edge port
* @return the last state of the edge port;
*/
@Override
public SdxL2State getEdgePortState(ConnectPoint edgeport) {
synchronized (edgeportsState) {
EdgePortEvent event = this.edgeportsState.get(edgeport);
long ts = System.currentTimeMillis();
if (event == null ||
(ts > lastEdgePortUpdate && ts - lastEdgePortUpdate > deltaUpdate)) {
event = new EdgePortEvent(EdgePortEvent.Type.EDGE_PORT_REMOVED, edgeport);
Iterator<ConnectPoint> cps = this.edgePortService.getEdgePoints(edgeport.deviceId()).iterator();
while (cps.hasNext()) {
if (edgeport.equals(cps.next())) {
event = new EdgePortEvent(EdgePortEvent.Type.EDGE_PORT_ADDED, edgeport);
break;
}
}
edgeportsState.put(edgeport, event);
this.lastEdgePortUpdate = ts;
}
return this.getSdxL2State(event.type());
}
}
/**
* Updates edgeportsState after an EdgePort event.
*
* @param event the event just happened
*/
private void processEdgePortEvent(EdgePortEvent event) {
synchronized (edgeportsState) {
edgeportsState.put(event.subject(), event);
this.lastEdgePortUpdate = System.currentTimeMillis();
}
}
/**
* Translates the type of EdgePortEvent in SdxL2State.
*
* @param type the type of event
* @return the SdxL2State
*/
private SdxL2State getSdxL2State(EdgePortEvent.Type type) {
return type == EdgePortEvent.Type.EDGE_PORT_ADDED ? SdxL2State.ONLINE : SdxL2State.OFFLINE;
}
private class InternalEdgePortListener implements EdgePortListener {
/**
* Reacts to the specified event.
*
* @param event event to be processed
*/
@Override
public void event(EdgePortEvent event) {
ConnectPoint cp = event.subject();
log.info("ConnectPoint {}/{} {}", cp.elementId().toString(), cp.port().toString(), event.type().toString());
processEdgePortEvent(event);
}
}
}