Kyuhwi Choi
Committed by Jonathan Hart

[ONOS-4478][ONOS-4479] Implement scalable gateway get methods and gateway node management

 - Implements scalable gateway interface methods
 - Implements gateway node management

Change-Id: Ie5eb400b52df49dc36aef951e356e04b6238d59d
......@@ -47,6 +47,12 @@
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-core-serializers</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
......
/*
* 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.scalablegateway.api;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.onlab.packet.Ip4Address;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.Config;
import org.slf4j.Logger;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.net.config.Config.FieldPresence.MANDATORY;
/**
* Configuration object for OpensatckNode service.
*/
public class GatewayNodeConfig extends Config<ApplicationId> {
protected final Logger log = getLogger(getClass());
public static final String NODES = "nodes";
public static final String BRIDGE_ID = "bridgeId";
public static final String DATAPLANE_IP = "dataPlaneIp";
public static final String EXTERNAL_INTERFACE_NAME = "gatewayExternalInterfaceName";
/**
* Returns the set of nodes read from network config.
*
* @return set of OpensatckNodeConfig or null
*/
public Set<GatewayNode> gatewayNodes() {
Set<GatewayNode> nodes = Sets.newHashSet();
JsonNode jsonNodes = object.get(NODES);
if (jsonNodes == null) {
return null;
}
jsonNodes.forEach(jsonNode -> {
try {
nodes.add(new GatewayNode.Builder()
.gatewayDeviceId(DeviceId.deviceId(jsonNode.path(BRIDGE_ID).asText()))
.gatewayExternalInterfaceNames(
getExternalInterfaceName(jsonNode.path(EXTERNAL_INTERFACE_NAME).asText()))
.dataIpAddress(Ip4Address.valueOf(jsonNode.path(DATAPLANE_IP).asText())).build());
} catch (IllegalArgumentException | NullPointerException e) {
log.error("Failed to read {}", e.toString());
}
});
return nodes;
}
private List<String> getExternalInterfaceName(String s) {
List<String> list = Lists.newArrayList();
return Collections.addAll(list, s.split(",")) ? list : null;
}
@Override
public boolean isValid() {
return hasOnlyFields(NODES, BRIDGE_ID, DATAPLANE_IP, EXTERNAL_INTERFACE_NAME) &&
isIpAddress(DATAPLANE_IP, MANDATORY) && isString(BRIDGE_ID, MANDATORY) &&
isString(EXTERNAL_INTERFACE_NAME, MANDATORY);
}
}
......@@ -15,6 +15,6 @@
*/
/**
* Application for ScaleableGateway management.
* Application api for Scaleable Gateway management.
*/
package org.onosproject.scalablegateway.api;
\ No newline at end of file
......
......@@ -16,51 +16,196 @@
package org.onosproject.scalablegateway.impl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.GroupId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.device.DeviceService;
import org.onosproject.scalablegateway.api.GatewayNode;
import org.onosproject.scalablegateway.api.GatewayNodeConfig;
import org.onosproject.scalablegateway.api.ScalableGatewayService;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Manages gateway node for gateway scalability.
*/
@Service
@Component(immediate = true)
public class ScalableGatewayManager implements ScalableGatewayService {
private final Logger log = LoggerFactory.getLogger(getClass());
private ApplicationId appId;
private static final String APP_ID = "org.onosproject.scalablegateway";
private static final String APP_NAME = "scalablegateway";
private static final String GATEWAYNODE_CAN_NOT_BE_NULL = "The gateway node can not be null";
private static final String PORT_CAN_NOT_BE_NULL = "The port can not be null";
private static final String FAIL_ADD_GATEWAY = "Adding process is failed as existing deivce id";
private static final String FAIL_REMOVE_GATEWAY = "Removing process is failed as unknown deivce id";
private static final String PORT_NAME = "portName";
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigService configService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigRegistry configRegistry;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
private GatewayNodeConfig config;
private final NetworkConfigListener configListener = new InternalConfigListener();
private final ConfigFactory configFactory =
new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, GatewayNodeConfig.class, APP_NAME) {
@Override
public GatewayNodeConfig createConfig() {
return new GatewayNodeConfig();
}
};
private Map<DeviceId, GatewayNode> gatewayNodeMap = Maps.newHashMap(); // Map<GatewayNode`s Id, GatewayNode object>
@Activate
protected void activate() {
appId = coreService.registerApplication(APP_ID);
configRegistry.registerConfigFactory(configFactory);
configService.addListener(configListener);
readConfiguration();
log.info("started");
}
@Deactivate
protected void deactivate() {
gatewayNodeMap.clear();
configService.removeListener(configListener);
log.info("stopped");
}
@Override
public GatewayNode getGatewayNode(DeviceId deviceId) {
return null;
return checkNotNull(gatewayNodeMap.get(deviceId), GATEWAYNODE_CAN_NOT_BE_NULL);
}
@Override
public List<PortNumber> getGatewayExternalPorts(DeviceId deviceId) {
return null;
GatewayNode gatewayNode = checkNotNull(gatewayNodeMap.get(deviceId), GATEWAYNODE_CAN_NOT_BE_NULL);
List<PortNumber> portNumbers = Lists.newArrayList();
gatewayNode.getGatewayExternalInterfaceNames()
.stream()
.forEach(name -> portNumbers.add(findPortNumFromPortName(gatewayNode.getGatewayDeviceId(), name)));
return portNumbers;
}
private PortNumber findPortNumFromPortName(DeviceId gatewayDeviceId, String name) {
Port port = deviceService.getPorts(gatewayDeviceId)
.stream()
.filter(p -> p.annotations().value(PORT_NAME).equals(name))
.iterator()
.next();
return checkNotNull(port, PORT_CAN_NOT_BE_NULL).number();
}
@Override
public GroupId getGroupIdForGatewayLoadBalance(DeviceId srcDeviceId) {
//TODO: Implement group generation method by handler
return null;
}
@Override
public List<GatewayNode> getGatewayNodes() {
return null;
List<GatewayNode> gatewayNodeList = Lists.newArrayList();
gatewayNodeMap.values()
.stream()
.forEach(gatewayNode -> gatewayNodeList.add(gatewayNode));
return gatewayNodeList;
}
@Override
public List<DeviceId> getGatewayDeviceIds() {
return null;
List<DeviceId> deviceIdList = Lists.newArrayList();
gatewayNodeMap.values()
.stream()
.forEach(gatewayNode -> deviceIdList.add(gatewayNode.getGatewayDeviceId()));
return deviceIdList;
}
@Override
public boolean addGatewayNode(GatewayNode gatewayNode) {
return false;
gatewayNodeMap.putIfAbsent(gatewayNode.getGatewayDeviceId(), gatewayNode);
return true;
}
@Override
public boolean deleteGatewayNode(GatewayNode gatewayNode) {
return false;
return gatewayNodeMap.remove(gatewayNode.getGatewayDeviceId(), gatewayNode);
}
private class InternalConfigListener implements NetworkConfigListener {
@Override
public void event(NetworkConfigEvent event) {
if (!event.configClass().equals(GatewayNodeConfig.class)) {
return;
}
switch (event.type()) {
case CONFIG_UPDATED:
gatewayNodeMap.clear();
readConfiguration();
break;
case CONFIG_ADDED:
readConfiguration();
break;
default:
log.debug("Unsupportable event type is occurred");
break;
}
}
}
private void readConfiguration() {
config = configService.getConfig(appId, GatewayNodeConfig.class);
if (config == null) {
log.error("No configuration found");
return;
}
config.gatewayNodes().forEach(gatewayNode -> addGatewayNode(gatewayNode));
log.info("ScalableGateway configured");
}
}
......
......@@ -15,6 +15,6 @@
*/
/**
* Application for ScaleableGateway management.
* Application for Scaleable Gateway management.
*/
package org.onosproject.scalablegateway.impl;
\ No newline at end of file
......