Moved ecord.metro app to onos repo. (ONOS-4441)
Change-Id: I9a5d2935012eee433a4f63c672c16bdcb8d6b6b8
diff --git a/apps/newoptical/BUCK b/apps/newoptical/BUCK
new file mode 100644
index 0000000..c21f807
--- /dev/null
+++ b/apps/newoptical/BUCK
@@ -0,0 +1,16 @@
+COMPILE_DEPS = [
+ '//lib:CORE_DEPS',
+ '//lib:org.apache.karaf.shell.console',
+ '//cli:onos-cli',
+]
+
+osgi_jar_with_tests (
+ deps = COMPILE_DEPS,
+)
+
+onos_app (
+ title = 'Packet/Optical Use-Case App',
+ category = 'Traffic Steering',
+ url = 'http://onosproject.org',
+ description = 'Packet/Optical use-case application.',
+)
diff --git a/apps/newoptical/pom.xml b/apps/newoptical/pom.xml
new file mode 100644
index 0000000..1ca4f0d
--- /dev/null
+++ b/apps/newoptical/pom.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>onos-apps</artifactId>
+ <groupId>org.onosproject</groupId>
+ <version>1.6.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-app-newoptical</artifactId>
+ <packaging>bundle</packaging>
+
+ <description>Application for setup optical network</description>
+ <url>http://onosproject.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <onos.app.name>org.onosproject.newoptical</onos.app.name>
+ <onos.app.category>Traffic Steering</onos.app.category>
+ <onos.app.url>http://onosproject.org</onos.app.url>
+ <onos.app.origin>Open Networking Lab</onos.app.origin>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-dist</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <classifier>tests</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.annotations</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-cli</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-maven-plugin</artifactId>
+ <extensions>true</extensions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>generate-scr-srcdescriptor</id>
+ <goals>
+ <goal>scr</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <supportedProjectTypes>
+ <supportedProjectType>bundle</supportedProjectType>
+ <supportedProjectType>war</supportedProjectType>
+ </supportedProjectTypes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>cfg</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>cfg</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>swagger</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>swagger</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>app</id>
+ <phase>package</phase>
+ <goals>
+ <goal>app</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/apps/newoptical/src/main/java/org/onosproject/newoptical/OpticalConnectivity.java b/apps/newoptical/src/main/java/org/onosproject/newoptical/OpticalConnectivity.java
new file mode 100644
index 0000000..db127e7
--- /dev/null
+++ b/apps/newoptical/src/main/java/org/onosproject/newoptical/OpticalConnectivity.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2016 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.newoptical;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.onlab.util.Bandwidth;
+import org.onosproject.newoptical.api.OpticalConnectivityId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.intent.IntentId;
+
+import java.time.Duration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Entity to store optical connectivity request and related information.
+ */
+@Beta
+public class OpticalConnectivity {
+
+ private final OpticalConnectivityId id;
+ private final List<Link> links;
+ private final Bandwidth requestBandwidth;
+ private final Duration requestLatency;
+
+ // Bandwidth capacity of optical layer
+ private Bandwidth opticalCapacity;
+
+ private final Set<PacketLinkRealizedByOptical> realizingLinks = new HashSet<>();
+
+ // TODO: This IntentId is used only to reserve bandwidth resource.
+ // After ResourceManager is made to accept app-defined ResourceConsumer,
+ // this Intent should be replaced with OpticalConnectivityId.
+ private IntentId intentId;
+
+ private State state = State.CREATED;
+
+ public enum State {
+ CREATED,
+ INSTALLING,
+ INSTALLED,
+ WITHDRAWING,
+ WITHDRAWN,
+ FAILED
+ }
+
+ public OpticalConnectivity(OpticalConnectivityId id, Path path, Bandwidth requestBandwidth,
+ Duration requestLatency) {
+ this.id = id;
+ this.links = ImmutableList.copyOf(path.links());
+ this.requestBandwidth = requestBandwidth;
+ this.requestLatency = requestLatency;
+ }
+
+ public void setLinkEstablished(ConnectPoint src, ConnectPoint dst) {
+ realizingLinks.stream().filter(l -> l.isBetween(src, dst))
+ .findAny()
+ .ifPresent(l -> l.setEstablished(true));
+ }
+
+ public void setLinkRemoved(ConnectPoint src, ConnectPoint dst) {
+ realizingLinks.stream().filter(l -> l.isBetween(src, dst))
+ .findAny()
+ .ifPresent(l -> l.setEstablished(false));
+ }
+
+ public boolean isAllRealizingLinkEstablished() {
+ return realizingLinks.stream().allMatch(PacketLinkRealizedByOptical::isEstablished);
+ }
+
+ public boolean isAllRealizingLinkNotEstablished() {
+ return !realizingLinks.stream().anyMatch(PacketLinkRealizedByOptical::isEstablished);
+ }
+
+ public OpticalConnectivityId id() {
+ return id;
+ }
+
+ public List<Link> links() {
+ return links;
+ }
+
+ public Bandwidth bandwidth() {
+ return requestBandwidth;
+ }
+
+ public Duration latency() {
+ return requestLatency;
+ }
+
+ public State state() {
+ return state;
+ }
+
+ public boolean state(State state) {
+ boolean valid = true;
+ // reject invalid state transition
+ switch (this.state) {
+ case CREATED:
+ valid = (state == State.INSTALLING || state == State.FAILED);
+ break;
+ case INSTALLING:
+ valid = (state == State.INSTALLED || state == State.FAILED);
+ break;
+ case INSTALLED:
+ valid = (state == State.WITHDRAWING || state == State.FAILED);
+ break;
+ case WITHDRAWING:
+ valid = (state == State.WITHDRAWN || state == State.FAILED);
+ break;
+ case FAILED:
+ valid = (state == State.INSTALLING || state == State.WITHDRAWING || state == State.FAILED);
+ break;
+ default:
+ break;
+ }
+
+ if (valid) {
+ this.state = state;
+ }
+
+ return valid;
+ }
+
+ public Bandwidth getOpticalCapacity() {
+ return opticalCapacity;
+ }
+
+ public void setOpticalCapacity(Bandwidth opticalCapacity) {
+ this.opticalCapacity = opticalCapacity;
+ }
+
+ public void addRealizingLink(PacketLinkRealizedByOptical link) {
+ checkNotNull(link);
+ realizingLinks.add(link);
+ }
+
+ public void removeRealizingLink(PacketLinkRealizedByOptical link) {
+ checkNotNull(link);
+ realizingLinks.remove(link);
+ }
+
+ public Set<PacketLinkRealizedByOptical> getRealizingLinks() {
+ return ImmutableSet.copyOf(realizingLinks);
+ }
+
+ public IntentId getIntentId() {
+ return intentId;
+ }
+
+ public void setIntentId(IntentId intentId) {
+ this.intentId = intentId;
+ }
+}
diff --git a/apps/newoptical/src/main/java/org/onosproject/newoptical/OpticalPathProvisioner.java b/apps/newoptical/src/main/java/org/onosproject/newoptical/OpticalPathProvisioner.java
new file mode 100644
index 0000000..995b0f3
--- /dev/null
+++ b/apps/newoptical/src/main/java/org/onosproject/newoptical/OpticalPathProvisioner.java
@@ -0,0 +1,689 @@
+/*
+ * Copyright 2016 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.newoptical;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
+
+import org.apache.commons.lang3.tuple.Pair;
+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.onlab.util.Bandwidth;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.newoptical.api.OpticalConnectivityId;
+import org.onosproject.newoptical.api.OpticalPathEvent;
+import org.onosproject.newoptical.api.OpticalPathListener;
+import org.onosproject.newoptical.api.OpticalPathService;
+import org.onosproject.event.AbstractListenerManager;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.CltSignalType;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.OchPort;
+import org.onosproject.net.OduCltPort;
+import org.onosproject.net.OduSignalType;
+import org.onosproject.net.Path;
+import org.onosproject.net.Port;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentEvent;
+import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.intent.IntentListener;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.OpticalCircuitIntent;
+import org.onosproject.net.intent.OpticalConnectivityIntent;
+import org.onosproject.net.intent.PointToPointIntent;
+import org.onosproject.net.link.LinkEvent;
+import org.onosproject.net.link.LinkListener;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.net.resource.BandwidthCapacity;
+import org.onosproject.net.resource.ContinuousResource;
+import org.onosproject.net.resource.Resource;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
+import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.PathService;
+import org.onosproject.net.topology.TopologyEdge;
+import org.onosproject.store.service.AtomicCounter;
+import org.onosproject.store.service.StorageService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.Duration;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Main component to configure optical connectivity.
+ */
+@Beta
+@Service
+@Component(immediate = true)
+public class OpticalPathProvisioner
+ extends AbstractListenerManager<OpticalPathEvent, OpticalPathListener>
+ implements OpticalPathService {
+ protected static final Logger log = LoggerFactory.getLogger(OpticalPathProvisioner.class);
+
+ private static final String OPTICAL_CONNECTIVITY_ID_COUNTER = "optical-connectivity-id";
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected IntentService intentService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PathService pathService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LinkService linkService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected MastershipService mastershipService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ClusterService clusterService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigService networkConfigService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ResourceService resourceService;
+
+
+ private ApplicationId appId;
+
+ private AtomicCounter idCounter;
+
+ private LinkListener linkListener = new InternalLinkListener();
+ private IntentListener intentListener = new InternalIntentListener();
+
+ private Map<PacketLinkRealizedByOptical, OpticalConnectivity> linkPathMap = new ConcurrentHashMap<>();
+
+ // TODO this should be stored to distributed store
+ private Map<OpticalConnectivityId, OpticalConnectivity> connectivities = new ConcurrentHashMap<>();
+
+ // TODO this should be stored to distributed store
+ // Map of cross connect link and installed path which uses the link
+ private Set<Link> usedCrossConnectLinks = Sets.newConcurrentHashSet();
+
+ @Activate
+ protected void activate() {
+ appId = coreService.registerApplication("org.onosproject.newoptical");
+
+ idCounter = storageService.atomicCounterBuilder()
+ .withName(OPTICAL_CONNECTIVITY_ID_COUNTER)
+ .withMeteringDisabled()
+ .build()
+ .asAtomicCounter();
+
+ eventDispatcher.addSink(OpticalPathEvent.class, listenerRegistry);
+ linkService.addListener(linkListener);
+ intentService.addListener(intentListener);
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ intentService.removeListener(intentListener);
+ linkService.removeListener(linkListener);
+
+ log.info("Stopped");
+ }
+
+ @Override
+ public OpticalConnectivityId setupConnectivity(ConnectPoint ingress, ConnectPoint egress,
+ Bandwidth bandwidth, Duration latency) {
+ checkNotNull(ingress);
+ checkNotNull(egress);
+ log.info("setupConnectivity({}, {}, {}, {})", ingress, egress, bandwidth, latency);
+
+ bandwidth = (bandwidth == null) ? Bandwidth.bps(0) : bandwidth;
+
+ Set<Path> paths = pathService.getPaths(ingress.deviceId(), egress.deviceId(),
+ new BandwidthLinkWeight(bandwidth));
+ if (paths.isEmpty()) {
+ log.warn("Unable to find multi-layer path.");
+ return null;
+ }
+
+ // Search path with available cross connect points
+ for (Path path : paths) {
+ OpticalConnectivityId id = setupPath(path, bandwidth, latency);
+ if (id != null) {
+ log.info("Assigned OpticalConnectivityId: {}", id);
+ return id;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public OpticalConnectivityId setupPath(Path path, Bandwidth bandwidth, Duration latency) {
+ checkNotNull(path);
+ log.info("setupPath({}, {}, {})", path, bandwidth, latency);
+
+ // validate optical path
+ List<Pair<ConnectPoint, ConnectPoint>> xcPointPairs = getCrossConnectPoints(path);
+ if (!checkXcPoints(xcPointPairs)) {
+ // Can't setup path if cross connect points are mismatched
+ return null;
+ }
+
+ OpticalConnectivity connectivity = createConnectivity(path, bandwidth, latency);
+
+ // create intents from cross connect points and set connectivity information
+ List<Intent> intents = createIntents(xcPointPairs, connectivity);
+
+ // store cross connect port usage
+ path.links().stream().filter(this::isCrossConnectLink)
+ .forEach(usedCrossConnectLinks::add);
+
+ // Submit the intents
+ for (Intent i : intents) {
+ intentService.submit(i);
+ log.debug("Submitted an intent: {}", i);
+ }
+
+ return connectivity.id();
+ }
+
+ private OpticalConnectivity createConnectivity(Path path, Bandwidth bandwidth, Duration latency) {
+ OpticalConnectivityId id = OpticalConnectivityId.of(idCounter.getAndIncrement());
+ OpticalConnectivity connectivity = new OpticalConnectivity(id, path, bandwidth, latency);
+
+ ConnectPoint ingress = path.src();
+ ConnectPoint egress = path.dst();
+
+ Intent pktIntent = PointToPointIntent.builder()
+ .appId(appId)
+ .ingressPoint(ingress)
+ .egressPoint(egress)
+ .key(Key.of(id.id(), appId))
+ .build();
+
+ connectivity.setIntentId(pktIntent.id());
+
+ // store connectivity information
+ connectivities.put(connectivity.id(), connectivity);
+
+ return connectivity;
+ }
+
+ @Override
+ public boolean removeConnectivity(OpticalConnectivityId id) {
+ log.info("removeConnectivity({})", id);
+ OpticalConnectivity connectivity = connectivities.remove(id);
+
+ if (connectivity == null) {
+ return false;
+ }
+
+ // TODO withdraw intent only if all of connectivities that use the optical path are withdrawn
+ connectivity.getRealizingLinks().forEach(l -> {
+ Intent intent = intentService.getIntent(l.realizingIntentKey());
+ intentService.withdraw(intent);
+ });
+
+ return true;
+ }
+
+ @Override
+ public List<Link> getPath(OpticalConnectivityId id) {
+ OpticalConnectivity connectivity = connectivities.get(id);
+ if (connectivity == null) {
+ return null;
+ }
+
+ return ImmutableList.copyOf(connectivity.links());
+ }
+
+ /**
+ * Returns list of (optical, packet) pairs of cross connection points of missing optical path sections.
+ *
+ * Scans the given multi-layer path and looks for sections that use cross connect links.
+ * The ingress and egress points in the optical layer are combined to the packet layer ports, and
+ * are returned in a list.
+ *
+ * @param path the multi-layer path
+ * @return List of cross connect link's (packet port, optical port) pairs
+ */
+ private List<Pair<ConnectPoint, ConnectPoint>> getCrossConnectPoints(Path path) {
+ List<Pair<ConnectPoint, ConnectPoint>> xcPointPairs = new LinkedList<>();
+ boolean scanning = false;
+
+ for (Link link : path.links()) {
+ if (!isCrossConnectLink(link)) {
+ continue;
+ }
+
+ if (scanning) {
+ // link.src() is packet, link.dst() is optical
+ xcPointPairs.add(Pair.of(checkNotNull(link.src()), checkNotNull(link.dst())));
+ scanning = false;
+ } else {
+ // link.src() is optical, link.dst() is packet
+ xcPointPairs.add(Pair.of(checkNotNull(link.dst()), checkNotNull(link.src())));
+ scanning = true;
+ }
+ }
+
+ return xcPointPairs;
+ }
+
+ /**
+ * Checks if optical cross connect points are of same type.
+ *
+ * @param xcPointPairs list of cross connection points
+ * @return true if cross connect point pairs are of same type, false otherwise
+ */
+ private boolean checkXcPoints(List<Pair<ConnectPoint, ConnectPoint>> xcPointPairs) {
+ checkArgument(xcPointPairs.size() % 2 == 0);
+
+ Iterator<Pair<ConnectPoint, ConnectPoint>> itr = xcPointPairs.iterator();
+
+ while (itr.hasNext()) {
+ // checkArgument at start ensures we'll always have pairs of connect points
+ Pair<ConnectPoint, ConnectPoint> src = itr.next();
+ Pair<ConnectPoint, ConnectPoint> dst = itr.next();
+
+ Device.Type srcType = deviceService.getDevice(src.getKey().deviceId()).type();
+ Device.Type dstType = deviceService.getDevice(dst.getKey().deviceId()).type();
+
+ // Only support connections between identical port types
+ if (srcType != dstType) {
+ log.warn("Unsupported mix of cross connect points");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Scans the list of cross connection points and returns a list of optical connectivity intents.
+ * During the process, store intent ID and its realizing link information to given connectivity object.
+ *
+ * @param xcPointPairs list of cross connection points
+ * @return list of optical connectivity intents
+ */
+ private List<Intent> createIntents(List<Pair<ConnectPoint, ConnectPoint>> xcPointPairs,
+ OpticalConnectivity connectivity) {
+ checkArgument(xcPointPairs.size() % 2 == 0);
+
+ List<Intent> intents = new LinkedList<>();
+ Iterator<Pair<ConnectPoint, ConnectPoint>> itr = xcPointPairs.iterator();
+
+ while (itr.hasNext()) {
+ // checkArgument at start ensures we'll always have pairs of connect points
+ Pair<ConnectPoint, ConnectPoint> src = itr.next();
+ Pair<ConnectPoint, ConnectPoint> dst = itr.next();
+
+ Port srcPort = deviceService.getPort(src.getKey().deviceId(), src.getKey().port());
+ Port dstPort = deviceService.getPort(dst.getKey().deviceId(), dst.getKey().port());
+
+ if (srcPort instanceof OduCltPort && dstPort instanceof OduCltPort) {
+ // Create OTN circuit
+ OpticalCircuitIntent circuitIntent = OpticalCircuitIntent.builder()
+ .appId(appId)
+ .src(src.getKey())
+ .dst(dst.getKey())
+ .signalType(CltSignalType.CLT_10GBE)
+ .bidirectional(true)
+ .build();
+ intents.add(circuitIntent);
+ PacketLinkRealizedByOptical pLink = PacketLinkRealizedByOptical.create(src.getValue(), dst.getValue(),
+ circuitIntent);
+ connectivity.addRealizingLink(pLink);
+ linkPathMap.put(pLink, connectivity);
+ } else if (srcPort instanceof OchPort && dstPort instanceof OchPort) {
+ // Create lightpath
+ // FIXME: hardcoded ODU signal type
+ OpticalConnectivityIntent opticalIntent = OpticalConnectivityIntent.builder()
+ .appId(appId)
+ .src(src.getKey())
+ .dst(dst.getKey())
+ .signalType(OduSignalType.ODU4)
+ .bidirectional(true)
+ .build();
+ intents.add(opticalIntent);
+ PacketLinkRealizedByOptical pLink = PacketLinkRealizedByOptical.create(src.getValue(), dst.getValue(),
+ opticalIntent);
+ connectivity.addRealizingLink(pLink);
+ linkPathMap.put(pLink, connectivity);
+ } else {
+ log.warn("Unsupported cross connect point types {} {}", srcPort.type(), dstPort.type());
+ return Collections.emptyList();
+ }
+ }
+
+ return intents;
+ }
+
+ /**
+ * Verifies if given device type is in packet layer, i.e., ROADM, OTN or ROADM_OTN device.
+ *
+ * @param type device type
+ * @return true if in packet layer, false otherwise
+ */
+ private boolean isPacketLayer(Device.Type type) {
+ return type == Device.Type.SWITCH || type == Device.Type.ROUTER || type == Device.Type.VIRTUAL;
+ }
+
+ /**
+ * Verifies if given device type is in packet layer, i.e., switch or router device.
+ *
+ * @param type device type
+ * @return true if in packet layer, false otherwise
+ */
+ private boolean isTransportLayer(Device.Type type) {
+ return type == Device.Type.ROADM || type == Device.Type.OTN || type == Device.Type.ROADM_OTN;
+ }
+
+ /**
+ * Verifies if given link forms a cross-connection between packet and optical layer.
+ *
+ * @param link the link
+ * @return true if the link is a cross-connect link, false otherwise
+ */
+ private boolean isCrossConnectLink(Link link) {
+ if (link.type() != Link.Type.OPTICAL) {
+ return false;
+ }
+
+ Device.Type src = deviceService.getDevice(link.src().deviceId()).type();
+ Device.Type dst = deviceService.getDevice(link.dst().deviceId()).type();
+
+ return src != dst &&
+ ((isPacketLayer(src) && isTransportLayer(dst)) || (isPacketLayer(dst) && isTransportLayer(src)));
+ }
+
+ /**
+ * Updates bandwidth resource of given connect point.
+ * @param cp Connect point
+ * @param bandwidth New bandwidth
+ */
+ private void updatePortBandwidth(ConnectPoint cp, Bandwidth bandwidth) {
+ NodeId localNode = clusterService.getLocalNode().id();
+ NodeId sourceMaster = mastershipService.getMasterFor(cp.deviceId());
+ if (localNode.equals(sourceMaster)) {
+ log.debug("update Port {} Bandwidth {}", cp, bandwidth);
+ BandwidthCapacity bwCapacity = networkConfigService.addConfig(cp, BandwidthCapacity.class);
+ bwCapacity.capacity(bandwidth).apply();
+ }
+ }
+
+ /**
+ * Updates usage information of bandwidth based on connectivity which is established.
+ * @param connectivity Optical connectivity
+ */
+ private void updateBandwidthUsage(OpticalConnectivity connectivity) {
+ IntentId intentId = connectivity.getIntentId();
+ if (intentId == null) {
+ return;
+ }
+
+ List<Link> links = connectivity.links();
+
+ List<Resource> resources = links.stream().flatMap(l -> Stream.of(l.src(), l.dst()))
+ .filter(cp -> !isTransportLayer(deviceService.getDevice(cp.deviceId()).type()))
+ .map(cp -> Resources.continuous(cp.deviceId(), cp.port(),
+ Bandwidth.class).resource(connectivity.bandwidth().bps()))
+ .collect(Collectors.toList());
+
+ log.debug("allocating bandwidth for {} : {}", connectivity.getIntentId(), resources);
+ List<ResourceAllocation> allocations = resourceService.allocate(intentId, resources);
+ if (allocations.isEmpty()) {
+ log.warn("Failed to allocate bandwidth {} to {}",
+ connectivity.bandwidth().bps(), resources);
+ // TODO any recovery?
+ }
+ log.debug("Done allocating bandwidth for {}", connectivity.getIntentId());
+ }
+
+ /**
+ * Release bandwidth allocated by given connectivity.
+ * @param connectivity Optical connectivity
+ */
+ private void releaseBandwidthUsage(OpticalConnectivity connectivity) {
+ IntentId intentId = connectivity.getIntentId();
+ if (intentId == null) {
+ return;
+ }
+
+ log.debug("releasing bandwidth allocated to {}", connectivity.getIntentId());
+ if (!resourceService.release(connectivity.getIntentId())) {
+ log.warn("Failed to release bandwidth allocated to {}",
+ connectivity.getIntentId());
+ // TODO any recovery?
+ }
+ log.debug("DONE releasing bandwidth for {}", connectivity.getIntentId());
+ }
+
+ private class BandwidthLinkWeight implements LinkWeight {
+ private Bandwidth bandwidth = null;
+
+ public BandwidthLinkWeight(Bandwidth bandwidth) {
+ this.bandwidth = bandwidth;
+ }
+
+ @Override
+ public double weight(TopologyEdge edge) {
+ Link l = edge.link();
+
+ // Ignore inactive links
+ if (l.state() == Link.State.INACTIVE) {
+ return -1.0;
+ }
+
+ // Ignore cross connect links with used ports
+ if (isCrossConnectLink(l) && usedCrossConnectLinks.contains(l)) {
+ return -1.0;
+ }
+
+ // Check availability of bandwidth
+ if (bandwidth != null) {
+ if (hasEnoughBandwidth(l.src()) && hasEnoughBandwidth(l.dst())) {
+ return 1.0;
+ } else {
+ return -1.0;
+ }
+ } else {
+ // TODO needs to differentiate optical and packet?
+ if (l.type() == Link.Type.OPTICAL) {
+ // Transport links
+ return 1.0;
+ } else {
+ // Packet links
+ return 1.0;
+ }
+ }
+ }
+
+ private boolean hasEnoughBandwidth(ConnectPoint cp) {
+ if (cp.elementId() instanceof DeviceId) {
+ Device.Type type = deviceService.getDevice(cp.deviceId()).type();
+ if (isTransportLayer(type)) {
+ // Optical ports are assumed to have enough bandwidth
+ // TODO should look up physical limit?
+ return true;
+ }
+
+ ContinuousResource resource = Resources.continuous(cp.deviceId(), cp.port(), Bandwidth.class)
+ .resource(bandwidth.bps());
+
+ return resourceService.isAvailable(resource);
+ }
+ return false;
+ }
+ }
+
+
+ public class InternalIntentListener implements IntentListener {
+ @Override
+ public void event(IntentEvent event) {
+ switch (event.type()) {
+ case INSTALLED:
+ log.info("Intent {} installed.", event.subject());
+ updateCrossConnectLink(event.subject());
+ break;
+ case WITHDRAWN:
+ log.info("Intent {} withdrawn.", event.subject());
+ removeCrossConnectLinks(event.subject());
+ break;
+ case FAILED:
+ log.info("Intent {} failed.", event.subject());
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void updateCrossConnectLink(Intent intent) {
+ linkPathMap.entrySet().stream()
+ .filter(e -> e.getKey().realizingIntentKey().equals(intent.key()))
+ .forEach(e -> {
+ ConnectPoint packetSrc = e.getKey().src();
+ ConnectPoint packetDst = e.getKey().dst();
+ Bandwidth bw = e.getKey().bandwidth();
+ // Updates bandwidth of packet ports
+ updatePortBandwidth(packetSrc, bw);
+ updatePortBandwidth(packetDst, bw);
+
+ OpticalConnectivity connectivity = e.getValue();
+ connectivity.setLinkEstablished(packetSrc, packetDst);
+
+ if (e.getValue().isAllRealizingLinkEstablished()) {
+ updateBandwidthUsage(connectivity);
+
+ // Notifies listeners if all links are established
+ post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_INSTALLED, e.getValue().id()));
+ }
+ });
+ }
+
+ private void removeCrossConnectLinks(Intent intent) {
+ ConnectPoint src, dst;
+
+ if (intent instanceof OpticalCircuitIntent) {
+ OpticalCircuitIntent circuit = (OpticalCircuitIntent) intent;
+ src = circuit.getSrc();
+ dst = circuit.getDst();
+ } else if (intent instanceof OpticalConnectivityIntent) {
+ OpticalConnectivityIntent conn = (OpticalConnectivityIntent) intent;
+ src = conn.getSrc();
+ dst = conn.getDst();
+ } else {
+ return;
+ }
+
+ removeXcLinkUsage(src);
+ removeXcLinkUsage(dst);
+
+ // Set bandwidth of 0 to cross connect ports
+ Bandwidth bw = Bandwidth.bps(0);
+ linkPathMap.entrySet().stream()
+ .filter(e -> e.getKey().realizingIntentKey().equals(intent.key()))
+ .forEach(e -> {
+ ConnectPoint packetSrc = e.getKey().src();
+ ConnectPoint packetDst = e.getKey().dst();
+ // Updates bandwidth of packet ports
+ updatePortBandwidth(packetSrc, bw);
+ updatePortBandwidth(packetDst, bw);
+ OpticalConnectivity connectivity = e.getValue();
+ connectivity.setLinkRemoved(packetSrc, packetDst);
+
+ // Notifies listeners if all links are gone
+ if (e.getValue().isAllRealizingLinkNotEstablished()) {
+ releaseBandwidthUsage(connectivity);
+ post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_REMOVED, e.getValue().id()));
+ }
+ });
+ }
+
+ private void removeXcLinkUsage(ConnectPoint cp) {
+ Optional<Link> link = linkService.getLinks(cp).stream()
+ .filter(usedCrossConnectLinks::contains)
+ .findAny();
+
+ if (!link.isPresent()) {
+ log.warn("Cross connect point {} has no cross connect link.", cp);
+ return;
+ }
+
+ usedCrossConnectLinks.remove(link.get());
+ }
+ }
+
+
+ private class InternalLinkListener implements LinkListener {
+
+ @Override
+ public void event(LinkEvent event) {
+ switch (event.type()) {
+ case LINK_REMOVED:
+ Link link = event.subject();
+ Set<PacketLinkRealizedByOptical> pLinks = linkPathMap.keySet().stream()
+ .filter(l -> l.isBetween(link.src(), link.dst()) || l.isBetween(link.dst(), link.src()))
+ .collect(Collectors.toSet());
+
+ pLinks.forEach(l -> {
+ OpticalConnectivity c = linkPathMap.get(l);
+ // Notifies listeners if all links are gone
+ if (c.isAllRealizingLinkNotEstablished()) {
+ post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_REMOVED, c.id()));
+ }
+ linkPathMap.remove(l);
+ });
+ default:
+ break;
+ }
+ }
+ }
+}
+
diff --git a/apps/newoptical/src/main/java/org/onosproject/newoptical/PacketLinkRealizedByOptical.java b/apps/newoptical/src/main/java/org/onosproject/newoptical/PacketLinkRealizedByOptical.java
new file mode 100644
index 0000000..2e969c2
--- /dev/null
+++ b/apps/newoptical/src/main/java/org/onosproject/newoptical/PacketLinkRealizedByOptical.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2016 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.newoptical;
+
+import com.google.common.annotations.Beta;
+import org.onlab.util.Bandwidth;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.OpticalCircuitIntent;
+import org.onosproject.net.intent.OpticalConnectivityIntent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Entity to represent packet link realized by optical intent.
+ */
+@Beta
+public class PacketLinkRealizedByOptical {
+ private final ConnectPoint src, dst;
+ private final Bandwidth bandwidth;
+ // TODO should be list of Intent Key?
+ private final Key realizingIntentKey;
+ // established=false represents that this (packet) link is expected to be
+ // discovered after underlying (optical) path has been provisioned.
+ private boolean established;
+
+ /**
+ * Creates instance with specified parameters.
+ *
+ * @param src source connect point
+ * @param dst destination connect point
+ * @param realizingIntentKey key of Optical*Intent that realizes packet link between src and dst
+ * @param bandwidth assigned bandwidth
+ */
+ public PacketLinkRealizedByOptical(ConnectPoint src, ConnectPoint dst,
+ Key realizingIntentKey, Bandwidth bandwidth) {
+ this.src = src;
+ this.dst = dst;
+ this.realizingIntentKey = realizingIntentKey;
+ this.bandwidth = bandwidth;
+ this.established = false;
+ }
+
+ /**
+ * Creates PacketLinkRealizedByOptical instance with specified connect points and OpticalCircuitIntent.
+ * Assigned bandwidth is taken from physical limit of optical link.
+ *
+ * @param src source connect point
+ * @param dst destination connect point
+ * @param intent OpticalCircuitIntent that realizes packet link between src and dst
+ * @return
+ */
+ public static PacketLinkRealizedByOptical create(ConnectPoint src, ConnectPoint dst,
+ OpticalCircuitIntent intent) {
+ checkNotNull(src);
+ checkNotNull(dst);
+ checkNotNull(intent);
+
+ long rate = intent.getSignalType().bitRate();
+ return new PacketLinkRealizedByOptical(src, dst, intent.key(), Bandwidth.bps(rate));
+ }
+
+ /**
+ * Creates PacketLinkRealizedByOptical instance with specified connect points and OpticalConnectivityIntent.
+ * Assigned bandwidth is taken from physical limit of optical link.
+ *
+ * @param src source connect point
+ * @param dst destination connect point
+ * @param intent OpticalConnectivityIntent that realizes packet link between src and dst
+ * @return
+ */
+ public static PacketLinkRealizedByOptical create(ConnectPoint src, ConnectPoint dst,
+ OpticalConnectivityIntent intent) {
+ checkNotNull(src);
+ checkNotNull(dst);
+ checkNotNull(intent);
+
+ long rate = intent.getSignalType().bitRate();
+ return new PacketLinkRealizedByOptical(src, dst, intent.key(), Bandwidth.bps(rate));
+ }
+
+ /**
+ * Returns source connect point.
+ *
+ * @return source connect point
+ */
+ public ConnectPoint src() {
+ return src;
+ }
+
+ /**
+ * Returns destination connect point.
+ *
+ * @return destination connect point
+ */
+ public ConnectPoint dst() {
+ return dst;
+ }
+
+ /**
+ * Returns assigned bandwidth.
+ *
+ * @return assigned bandwidth
+ */
+ public Bandwidth bandwidth() {
+ return bandwidth;
+ }
+
+ /**
+ * Returns intent key.
+ *
+ * @return intent key
+ */
+ public Key realizingIntentKey() {
+ return realizingIntentKey;
+ }
+
+ /**
+ * Returns whether packet link is realized or not.
+ *
+ * @return true if packet link is realized. false if not.
+ */
+ public boolean isEstablished() {
+ return established;
+ }
+
+ /**
+ * Sets packet link to be established.
+ *
+ * @param established status of packet link
+ */
+ public void setEstablished(boolean established) {
+ this.established = established;
+ }
+
+ /**
+ * Check if packet link is between specified two connect points.
+ *
+ * @param src source connect point
+ * @param dst destination connect point
+ * @return true if this link is between src and dst. false if not.
+ */
+ public boolean isBetween(ConnectPoint src, ConnectPoint dst) {
+ return (this.src.equals(src) && this.dst.equals(dst));
+ }
+
+}
diff --git a/apps/newoptical/src/main/java/org/onosproject/newoptical/api/OpticalConnectivityId.java b/apps/newoptical/src/main/java/org/onosproject/newoptical/api/OpticalConnectivityId.java
new file mode 100644
index 0000000..4926373
--- /dev/null
+++ b/apps/newoptical/src/main/java/org/onosproject/newoptical/api/OpticalConnectivityId.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016 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.newoptical.api;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import org.onlab.util.Identifier;
+
+// TODO: After ResourceManager is made to accept app-defined ResourceConsumer,
+// this class should be implemented as ResourceConsumer.
+/**
+ * ID for optical connectivity.
+ */
+@Beta
+public final class OpticalConnectivityId extends Identifier<Long> {
+
+ public static OpticalConnectivityId of(long value) {
+ return new OpticalConnectivityId(value);
+ }
+
+ OpticalConnectivityId(long value) {
+ super(value);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("value", id())
+ .toString();
+ }
+}
diff --git a/apps/newoptical/src/main/java/org/onosproject/newoptical/api/OpticalPathEvent.java b/apps/newoptical/src/main/java/org/onosproject/newoptical/api/OpticalPathEvent.java
new file mode 100644
index 0000000..95b87e6
--- /dev/null
+++ b/apps/newoptical/src/main/java/org/onosproject/newoptical/api/OpticalPathEvent.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016 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.newoptical.api;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Event related to optical domain path setup.
+ */
+@Beta
+public class OpticalPathEvent extends AbstractEvent<OpticalPathEvent.Type, OpticalConnectivityId> {
+ public enum Type {
+ PATH_INSTALLED,
+ PATH_REMOVED
+ }
+
+ /**
+ * Creates OpticalPathEvent object with specified type and subject.
+ * @param type
+ * @param subject
+ */
+ public OpticalPathEvent(Type type, OpticalConnectivityId subject) {
+ super(type, subject);
+ }
+
+}
diff --git a/apps/newoptical/src/main/java/org/onosproject/newoptical/api/OpticalPathListener.java b/apps/newoptical/src/main/java/org/onosproject/newoptical/api/OpticalPathListener.java
new file mode 100644
index 0000000..d413a27
--- /dev/null
+++ b/apps/newoptical/src/main/java/org/onosproject/newoptical/api/OpticalPathListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 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.newoptical.api;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving optical path related events.
+ */
+public interface OpticalPathListener extends EventListener<OpticalPathEvent> {
+}
diff --git a/apps/newoptical/src/main/java/org/onosproject/newoptical/api/OpticalPathService.java b/apps/newoptical/src/main/java/org/onosproject/newoptical/api/OpticalPathService.java
new file mode 100644
index 0000000..e6df0cb
--- /dev/null
+++ b/apps/newoptical/src/main/java/org/onosproject/newoptical/api/OpticalPathService.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016 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.newoptical.api;
+
+import com.google.common.annotations.Beta;
+import org.onlab.util.Bandwidth;
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+
+import java.time.Duration;
+import java.util.List;
+
+/**
+ * Service to setup optical domain connectivity.
+ */
+@Beta
+public interface OpticalPathService extends ListenerService<OpticalPathEvent, OpticalPathListener> {
+
+ /**
+ * Calculates optical path between connect points and sets up connectivity.
+ *
+ * @param ingress ingress port
+ * @param egress egress port
+ * @param bandwidth required bandwidth. No bandwidth is assured if null.
+ * @param latency required latency. No latency is assured if null.
+ * @return ID of created connectivity if successful. null otherwise.
+ */
+ OpticalConnectivityId setupConnectivity(ConnectPoint ingress, ConnectPoint egress,
+ Bandwidth bandwidth, Duration latency);
+
+ /**
+ * Sets up connectivity along given optical path.
+ *
+ * @param path path along which connectivity will be set up
+ * @param bandwidth required bandwidth. No bandwidth is assured if null.
+ * @param latency required latency. No latency is assured if null.
+ * @return true if successful. false otherwise.
+ */
+ OpticalConnectivityId setupPath(Path path, Bandwidth bandwidth, Duration latency);
+
+ /**
+ * Removes connectivity with given ID.
+ *
+ * @param id ID of connectivity
+ * @return true if succeed. false if failed.
+ */
+ boolean removeConnectivity(OpticalConnectivityId id);
+
+ /**
+ * Returns path assigned to given ID.
+ * @param id ID of connectivity
+ * @return list of link that compose a path. null if ID is invalid.
+ */
+ List<Link> getPath(OpticalConnectivityId id);
+}
diff --git a/apps/newoptical/src/main/java/org/onosproject/newoptical/api/package-info.java b/apps/newoptical/src/main/java/org/onosproject/newoptical/api/package-info.java
new file mode 100644
index 0000000..7f10af4
--- /dev/null
+++ b/apps/newoptical/src/main/java/org/onosproject/newoptical/api/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 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.
+ */
+/**
+ * API to optical path service.
+ */
+package org.onosproject.newoptical.api;
\ No newline at end of file
diff --git a/apps/newoptical/src/main/java/org/onosproject/newoptical/cli/AddOpticalConnectivityCommand.java b/apps/newoptical/src/main/java/org/onosproject/newoptical/cli/AddOpticalConnectivityCommand.java
new file mode 100644
index 0000000..dc50999
--- /dev/null
+++ b/apps/newoptical/src/main/java/org/onosproject/newoptical/cli/AddOpticalConnectivityCommand.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2016 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.newoptical.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.util.Bandwidth;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.newoptical.api.OpticalConnectivityId;
+import org.onosproject.newoptical.api.OpticalPathService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+@Command(scope = "onos", name = "add-optical-connectivity",
+ description = "Configure optical domain connectivity")
+public class AddOpticalConnectivityCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "ingress", description = "Ingress connect point",
+ required = true, multiValued = false)
+ String ingressStr = null;
+
+ @Argument(index = 1, name = "egress", description = "Egress connect point",
+ required = true, multiValued = false)
+ String egressStr = null;
+
+ @Argument(index = 2, name = "bandwidth", description = "Bandwidth",
+ required = false, multiValued = false)
+ String bandwidthStr = null;
+
+ @Argument(index = 3, name = "latency", description = "Latency",
+ required = true, multiValued = false)
+ String latencyStr = null;
+
+
+ @Override
+ protected void execute() {
+ OpticalPathService opticalPathService = get(OpticalPathService.class);
+
+ ConnectPoint ingress = readConnectPoint(ingressStr);
+ ConnectPoint egress = readConnectPoint(egressStr);
+ if (ingress == null || egress == null) {
+ print("Invalid connect points: %s, %s", ingressStr, egressStr);
+ return;
+ }
+
+ Bandwidth bandwidth = (bandwidthStr == null || bandwidthStr.isEmpty()) ? null :
+ Bandwidth.bps(Long.valueOf(bandwidthStr));
+
+ print("Trying to setup connectivity between %s and %s.", ingress, egress);
+ OpticalConnectivityId id = opticalPathService.setupConnectivity(ingress, egress, bandwidth, null);
+ if (id == null) {
+ print("Failed.");
+ return;
+ }
+ print("Optical path ID : %s", id.id());
+ }
+
+ private ConnectPoint readConnectPoint(String str) {
+ String[] strings = str.split("/");
+ if (strings.length != 2) {
+ return null;
+ }
+
+ DeviceId devId = DeviceId.deviceId(strings[0]);
+ PortNumber port = PortNumber.portNumber(strings[1]);
+
+ return new ConnectPoint(devId, port);
+ }
+
+}
diff --git a/apps/newoptical/src/main/java/org/onosproject/newoptical/cli/RemoveOpticalConnectivityCommand.java b/apps/newoptical/src/main/java/org/onosproject/newoptical/cli/RemoveOpticalConnectivityCommand.java
new file mode 100644
index 0000000..fff807e
--- /dev/null
+++ b/apps/newoptical/src/main/java/org/onosproject/newoptical/cli/RemoveOpticalConnectivityCommand.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016 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.newoptical.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.newoptical.api.OpticalConnectivityId;
+import org.onosproject.newoptical.api.OpticalPathService;
+
+@Command(scope = "onos", name = "remove-optical-connectivity",
+ description = "Remove optical domain connectivity")
+public class RemoveOpticalConnectivityCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "id", description = "ID of optical connectivity",
+ required = true, multiValued = false)
+ String idStr = null;
+
+ @Override
+ protected void execute() {
+ OpticalPathService opticalPathService = get(OpticalPathService.class);
+
+ OpticalConnectivityId id = OpticalConnectivityId.of(Long.valueOf(idStr));
+
+ print("Trying to remove connectivity with id %s.", idStr);
+ if (opticalPathService.removeConnectivity(id)) {
+ print(" -- success");
+ } else {
+ print(" -- failed");
+ }
+
+ }
+}
diff --git a/apps/newoptical/src/main/java/org/onosproject/newoptical/cli/package-info.java b/apps/newoptical/src/main/java/org/onosproject/newoptical/cli/package-info.java
new file mode 100644
index 0000000..a4e4360
--- /dev/null
+++ b/apps/newoptical/src/main/java/org/onosproject/newoptical/cli/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 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.
+ */
+/**
+ * CLI to control optical path service.
+ */
+package org.onosproject.newoptical.cli;
\ No newline at end of file
diff --git a/apps/newoptical/src/main/java/org/onosproject/newoptical/package-info.java b/apps/newoptical/src/main/java/org/onosproject/newoptical/package-info.java
new file mode 100644
index 0000000..ea32e69
--- /dev/null
+++ b/apps/newoptical/src/main/java/org/onosproject/newoptical/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016 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.
+ */
+
+/**
+ * Module to control optical path.
+ */
+package org.onosproject.newoptical;
\ No newline at end of file
diff --git a/apps/newoptical/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/newoptical/src/main/resources/OSGI-INF/blueprint/shell-config.xml
new file mode 100644
index 0000000..93d369a
--- /dev/null
+++ b/apps/newoptical/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -0,0 +1,27 @@
+<!--
+ ~ Copyright 2016 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.onosproject.newoptical.cli.AddOpticalConnectivityCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.newoptical.cli.RemoveOpticalConnectivityCommand"/>
+ </command>
+ </command-bundle>
+
+</blueprint>
diff --git a/apps/optical/src/main/java/org/onosproject/optical/OpticalPathProvisioner.java b/apps/optical/src/main/java/org/onosproject/optical/OpticalPathProvisioner.java
index de1b28d..e2674b6 100644
--- a/apps/optical/src/main/java/org/onosproject/optical/OpticalPathProvisioner.java
+++ b/apps/optical/src/main/java/org/onosproject/optical/OpticalPathProvisioner.java
@@ -66,8 +66,11 @@
* OpticalPathProvisioner listens for event notifications from the Intent F/W.
* It generates one or more opticalConnectivityIntent(s) and submits (or withdraws) to Intent F/W
* for adding/releasing capacity at the packet layer.
+ *
+ * @deprecated in Goldeneye (1.6.0)
*/
+@Deprecated
@Component(immediate = true)
public class OpticalPathProvisioner {
diff --git a/apps/pom.xml b/apps/pom.xml
index b72a220..24e53c1 100644
--- a/apps/pom.xml
+++ b/apps/pom.xml
@@ -37,6 +37,7 @@
<module>proxyarp</module>
<module>sdnip</module>
<module>optical</module>
+ <module>newoptical</module>
<module>metrics</module>
<module>routing</module>
<module>routing-api</module>