[ONOS-4691] Refactoring OpticalPortOperator (2/3)
- Define ConfigOperator for a Port
- Refactor OpticalPortOperator as PortConfigOperator
- Add plug-in mechanism for PortConfigOperator on DeviceManager
- Move OpticalPortConfig, OpticalPortOperator to optical-model bundle
Change-Id: I5d416305b0c1b0e31e0ad64baa92d126303548bc
diff --git a/apps/optical-model/BUCK b/apps/optical-model/BUCK
index cf06443..e311eb3 100644
--- a/apps/optical-model/BUCK
+++ b/apps/optical-model/BUCK
@@ -4,7 +4,7 @@
]
TEST_DEPS = [
- '//lib:TEST',
+ '//lib:TEST_ADAPTERS',
]
diff --git a/apps/optical-model/pom.xml b/apps/optical-model/pom.xml
index 90fd800..a76d0d7 100644
--- a/apps/optical-model/pom.xml
+++ b/apps/optical-model/pom.xml
@@ -47,6 +47,13 @@
<dependency>
<groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
<artifactId>onlab-junit</artifactId>
<scope>test</scope>
</dependency>
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/OpticalPortConfig.java b/apps/optical-model/src/main/java/org/onosproject/net/optical/config/OpticalPortConfig.java
similarity index 98%
rename from core/api/src/main/java/org/onosproject/net/config/basics/OpticalPortConfig.java
rename to apps/optical-model/src/main/java/org/onosproject/net/optical/config/OpticalPortConfig.java
index 0509dfb..bd008a0 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/OpticalPortConfig.java
+++ b/apps/optical-model/src/main/java/org/onosproject/net/optical/config/OpticalPortConfig.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.net.config.basics;
+package org.onosproject.net.optical.config;
import java.util.Optional;
@@ -30,6 +30,7 @@
* Configurations for an optical port on a device.
*/
public final class OpticalPortConfig extends Config<ConnectPoint> {
+
// optical type {OMS, OCH, ODUClt, fiber}
public static final String TYPE = "type";
diff --git a/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java b/apps/optical-model/src/main/java/org/onosproject/net/optical/config/OpticalPortOperator.java
similarity index 65%
rename from core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java
rename to apps/optical-model/src/main/java/org/onosproject/net/optical/config/OpticalPortOperator.java
index b07780b..f6dc912 100644
--- a/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java
+++ b/apps/optical-model/src/main/java/org/onosproject/net/optical/config/OpticalPortOperator.java
@@ -13,17 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.net.device.impl;
+package org.onosproject.net.optical.config;
import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
import static org.onosproject.net.optical.device.OduCltPortHelper.oduCltPortDescription;
import static org.onosproject.net.optical.device.OmsPortHelper.omsPortDescription;
import static org.onosproject.net.optical.device.OtuPortHelper.otuPortDescription;
import static org.slf4j.LoggerFactory.getLogger;
-import org.onosproject.net.config.ConfigOperator;
-import org.onosproject.net.config.basics.OpticalPortConfig;
+
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.firstNonNull;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.PortConfigOperator;
import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.Port;
+import org.onosproject.net.Port.Type;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.device.DefaultPortDescription;
@@ -34,63 +43,85 @@
import org.onosproject.net.device.PortDescription;
import org.slf4j.Logger;
+import com.google.common.collect.Sets;
+
/**
* Implementations of merge policies for various sources of optical port
* configuration information. This includes applications, provides, and network
* configurations.
*/
-public final class OpticalPortOperator implements ConfigOperator {
+public final class OpticalPortOperator implements PortConfigOperator {
private static final Logger log = getLogger(OpticalPortOperator.class);
- private OpticalPortOperator() {
+ /**
+ * Port.Type this PortConfigOperator reacts on.
+ */
+ private final Set<Port.Type> optical = Sets.immutableEnumSet(Port.Type.ODUCLT,
+ Port.Type.OMS,
+ Port.Type.OCH,
+ Port.Type.OTU,
+ Port.Type.FIBER,
+ Port.Type.PACKET);
+
+ private NetworkConfigService networkConfigService;
+
+
+ public OpticalPortOperator() {
+ }
+
+ @Override
+ public void bindService(NetworkConfigService networkConfigService) {
+ this.networkConfigService = networkConfigService;
+ }
+
+ private OpticalPortConfig lookupConfig(ConnectPoint cp) {
+ if (networkConfigService == null) {
+ return null;
+ }
+ return networkConfigService.getConfig(cp, OpticalPortConfig.class);
}
/**
* Generates a PortDescription containing fields from a PortDescription and
* an OpticalPortConfig.
*
- * @param opc the port config entity from network config
- * @param descr a PortDescription
- * @return PortDescription based on both sources
+ * @param cp {@link ConnectPoint} representing the port.
+ * @param descr input {@link PortDescription}
+ * @return Combined {@link PortDescription}
*/
- public static PortDescription combine(OpticalPortConfig opc, PortDescription descr) {
+ @Override
+ public PortDescription combine(ConnectPoint cp, PortDescription descr) {
+ checkNotNull(cp);
+
+ // short-circuit for non-optical ports
+ // must be removed if we need type override
+ if (descr != null && !optical.contains(descr.type())) {
+ return descr;
+ }
+
+ OpticalPortConfig opc = lookupConfig(cp);
if (opc == null) {
return descr;
}
- PortNumber port = descr.portNumber();
- final String name = opc.name();
- final String numName = opc.numberName();
- // if the description is null, or the current description port name != config name,
- // create a new PortNumber.
- PortNumber newPort = null;
- if (port == null) {
- // try to get the portNumber from the numName.
- if (!numName.isEmpty()) {
- final long pn = Long.parseLong(numName);
- newPort = (!name.isEmpty()) ? PortNumber.portNumber(pn, name) : PortNumber.portNumber(pn);
- } else {
- // we don't have defining info (a port number value)
- throw new RuntimeException("Possible misconfig, bailing on handling for: \n\t" + descr);
- }
- } else if ((!name.isEmpty()) && !name.equals(port.name())) {
- final long pn = (numName.isEmpty()) ? port.toLong() : Long.parseLong(numName);
- newPort = PortNumber.portNumber(pn, name);
+ PortNumber number = descr.portNumber();
+ // handle PortNumber "name" portion
+ if (!opc.name().isEmpty()) {
+ number = PortNumber.portNumber(descr.portNumber().toLong(), opc.name());
}
- // Port type won't change unless we're overwriting a port completely.
- // Watch out for overwrites to avoid class cast craziness.
- boolean noOwrite = opc.type() == descr.type();
+ // handle additional annotations
+ SparseAnnotations annotations = combine(opc, descr.annotations());
- SparseAnnotations sa = combine(opc, descr.annotations());
- if (noOwrite) {
- return updateDescription((newPort == null) ? port : newPort, sa, descr);
- } else {
- // TODO: must reconstruct a different type of PortDescription.
- log.info("Type rewrite from {} to {} required", descr.type(), opc.type());
+ // (Future work) handle type overwrite?
+ Type type = firstNonNull(opc.type(), descr.type());
+ if (type != descr.type()) {
+ // TODO: Do we need to be able to overwrite Port.Type?
+ log.warn("Port type overwrite requested for {}. Ignoring.", cp);
}
- return descr;
+
+ return updateDescription(number, annotations, descr);
}
// updates a port description whose port type has not changed.
@@ -161,8 +192,9 @@
* @param an the annotation
* @return annotation combining both sources
*/
- public static SparseAnnotations combine(OpticalPortConfig opc, SparseAnnotations an) {
+ private static SparseAnnotations combine(OpticalPortConfig opc, SparseAnnotations an) {
DefaultAnnotations.Builder b = DefaultAnnotations.builder();
+ b.putAll(an);
if (!opc.staticPort().isEmpty()) {
b.set(AnnotationKeys.STATIC_PORT, opc.staticPort());
}
@@ -173,7 +205,8 @@
if (!opc.name().isEmpty()) {
b.set(AnnotationKeys.PORT_NAME, opc.name());
}
- return DefaultAnnotations.union(an, b.build());
+ return b.build();
}
+
}
diff --git a/apps/optical-model/src/main/java/org/onosproject/net/optical/config/package-info.java b/apps/optical-model/src/main/java/org/onosproject/net/optical/config/package-info.java
new file mode 100644
index 0000000..2deb1f7
--- /dev/null
+++ b/apps/optical-model/src/main/java/org/onosproject/net/optical/config/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+/**
+ * Various optical model related configurations.
+ */
+package org.onosproject.net.optical.config;
diff --git a/apps/optical-model/src/main/java/org/onosproject/net/optical/internal/OpticalModelLoader.java b/apps/optical-model/src/main/java/org/onosproject/net/optical/internal/OpticalModelLoader.java
new file mode 100644
index 0000000..494fc24
--- /dev/null
+++ b/apps/optical-model/src/main/java/org/onosproject/net/optical/internal/OpticalModelLoader.java
@@ -0,0 +1,79 @@
+/*
+ * 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.net.optical.internal;
+
+import static org.onosproject.net.config.basics.SubjectFactories.CONNECT_POINT_SUBJECT_FACTORY;
+
+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.onosproject.net.ConnectPoint;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.PortConfigOperatorRegistry;
+import org.onosproject.net.optical.config.OpticalPortConfig;
+import org.onosproject.net.optical.config.OpticalPortOperator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Loader which registers optical model related config, etc.
+ */
+@Component(immediate = true)
+public class OpticalModelLoader {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PortConfigOperatorRegistry portOperatorRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry netcfgRegistry;
+
+
+ private OpticalPortOperator opticalPortOp;
+
+ private ConfigFactory<ConnectPoint, OpticalPortConfig>
+ opticalPortConfigFactory = new ConfigFactory<ConnectPoint, OpticalPortConfig>(CONNECT_POINT_SUBJECT_FACTORY,
+ OpticalPortConfig.class,
+ "optical") {
+ @Override
+ public OpticalPortConfig createConfig() {
+ return new OpticalPortConfig();
+ }
+ };
+
+ @Activate
+ protected void activate() {
+ netcfgRegistry.registerConfigFactory(opticalPortConfigFactory);
+
+ opticalPortOp = new OpticalPortOperator();
+ portOperatorRegistry.registerPortConfigOperator(opticalPortOp,
+ OpticalPortConfig.class);
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ portOperatorRegistry.unregisterPortConfigOperator(opticalPortOp);
+
+ netcfgRegistry.unregisterConfigFactory(opticalPortConfigFactory);
+ log.info("Stopped");
+ }
+}
diff --git a/apps/optical-model/src/main/java/org/onosproject/net/optical/internal/package-info.java b/apps/optical-model/src/main/java/org/onosproject/net/optical/internal/package-info.java
new file mode 100644
index 0000000..8707ad5
--- /dev/null
+++ b/apps/optical-model/src/main/java/org/onosproject/net/optical/internal/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+/**
+ * Internal tools for optical model.
+ */
+package org.onosproject.net.optical.internal;
diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/config/basics/OpticalPortConfigTest.java b/apps/optical-model/src/test/java/org/onosproject/net/optical/config/OpticalPortConfigTest.java
similarity index 91%
rename from incubator/api/src/test/java/org/onosproject/incubator/net/config/basics/OpticalPortConfigTest.java
rename to apps/optical-model/src/test/java/org/onosproject/net/optical/config/OpticalPortConfigTest.java
index d0b3060..56338d8 100644
--- a/incubator/api/src/test/java/org/onosproject/incubator/net/config/basics/OpticalPortConfigTest.java
+++ b/apps/optical-model/src/test/java/org/onosproject/net/optical/config/OpticalPortConfigTest.java
@@ -13,15 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.incubator.net.config.basics;
+package org.onosproject.net.optical.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.onosproject.net.config.basics.OpticalPortConfig.TYPE;
-import static org.onosproject.net.config.basics.OpticalPortConfig.NAME;
-import static org.onosproject.net.config.basics.OpticalPortConfig.PORT;
-import static org.onosproject.net.config.basics.OpticalPortConfig.STATIC_LAMBDA;
-import static org.onosproject.net.config.basics.OpticalPortConfig.STATIC_PORT;
+import static org.onosproject.net.optical.config.OpticalPortConfig.NAME;
+import static org.onosproject.net.optical.config.OpticalPortConfig.PORT;
+import static org.onosproject.net.optical.config.OpticalPortConfig.STATIC_LAMBDA;
+import static org.onosproject.net.optical.config.OpticalPortConfig.STATIC_PORT;
+import static org.onosproject.net.optical.config.OpticalPortConfig.TYPE;
import java.io.IOException;
import java.util.Iterator;
@@ -41,7 +41,6 @@
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
-import org.onosproject.net.config.basics.OpticalPortConfig;
public class OpticalPortConfigTest {
private static final String FIELD = "ports";
diff --git a/core/net/src/test/java/org/onosproject/net/device/impl/OpticalPortOperatorTest.java b/apps/optical-model/src/test/java/org/onosproject/net/optical/config/OpticalPortOperatorTest.java
similarity index 80%
rename from core/net/src/test/java/org/onosproject/net/device/impl/OpticalPortOperatorTest.java
rename to apps/optical-model/src/test/java/org/onosproject/net/optical/config/OpticalPortOperatorTest.java
index 6d257e4..d08e019 100644
--- a/core/net/src/test/java/org/onosproject/net/device/impl/OpticalPortOperatorTest.java
+++ b/apps/optical-model/src/test/java/org/onosproject/net/optical/config/OpticalPortOperatorTest.java
@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.net.device.impl;
+package org.onosproject.net.optical.config;
import org.junit.Before;
import org.junit.Test;
import org.onosproject.net.CltSignalType;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.ConfigApplyDelegate;
-import org.onosproject.net.config.basics.OpticalPortConfig;
+import org.onosproject.net.config.NetworkConfigServiceAdapter;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
@@ -29,6 +29,7 @@
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.device.PortDescription;
+
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
@@ -62,27 +63,33 @@
private static final ConnectPoint CP = new ConnectPoint(DID, UNNAMED);
- private static final OpticalPortConfig OPC = new OpticalPortConfig();
+ private OpticalPortConfig opc;
+
+ private OpticalPortOperator oper;
@Before
public void setUp() {
- OPC.init(CP, CFG_KEY, JsonNodeFactory.instance.objectNode(), mapper, delegate);
+ opc = new OpticalPortConfig();
+ opc.init(CP, CFG_KEY, JsonNodeFactory.instance.objectNode(), mapper, delegate);
+
+ oper = new OpticalPortOperator();
+ oper.bindService(new MockNetworkConfigService());
}
@Test
public void testConfigPortName() {
- OPC.portType(Port.Type.ODUCLT)
+ opc.portType(Port.Type.ODUCLT)
.portNumberName(PORT_NUMBER)
.portName(CFG_PORT_NAME);
PortDescription res;
// full desc + opc with name
- res = OpticalPortOperator.combine(OPC, N_DESC);
+ res = oper.combine(CP, N_DESC);
assertEquals("Configured port name expected",
CFG_PORT_NAME, res.portNumber().name());
assertEquals(DESC_STATIC_PORT, res.annotations().value(AnnotationKeys.STATIC_PORT));
- res = OpticalPortOperator.combine(OPC, U_DESC);
+ res = oper.combine(CP, U_DESC);
assertEquals("Configured port name expected",
CFG_PORT_NAME, res.portNumber().name());
assertEquals(DESC_STATIC_PORT, res.annotations().value(AnnotationKeys.STATIC_PORT));
@@ -90,12 +97,12 @@
@Test
public void testConfigAddStaticLambda() {
- OPC.portType(Port.Type.ODUCLT)
+ opc.portType(Port.Type.ODUCLT)
.portNumberName(PORT_NUMBER)
.staticLambda(CFG_STATIC_LAMBDA);
PortDescription res;
- res = OpticalPortOperator.combine(OPC, N_DESC);
+ res = oper.combine(CP, N_DESC);
assertEquals("Original port name expected",
DESC_PORT_NAME, res.portNumber().name());
assertEquals(DESC_STATIC_PORT, res.annotations().value(AnnotationKeys.STATIC_PORT));
@@ -105,17 +112,31 @@
@Test
public void testEmptyConfig() {
- OPC.portType(Port.Type.ODUCLT)
+ opc.portType(Port.Type.ODUCLT)
.portNumberName(PORT_NUMBER);
PortDescription res;
- res = OpticalPortOperator.combine(OPC, N_DESC);
+ res = oper.combine(CP, N_DESC);
assertEquals("Configured port name expected",
DESC_PORT_NAME, res.portNumber().name());
assertEquals(DESC_STATIC_PORT, res.annotations().value(AnnotationKeys.STATIC_PORT));
}
+ private class MockNetworkConfigService
+ extends NetworkConfigServiceAdapter {
+
+ @Override
+ public <S, C extends Config<S>> C getConfig(S subject,
+ Class<C> configClass) {
+ if (configClass == OpticalPortConfig.class) {
+ return (C) opc;
+ }
+ return null;
+ }
+ }
+
+
private class MockCfgDelegate implements ConfigApplyDelegate {
@Override
diff --git a/core/api/src/main/java/org/onosproject/net/config/PortConfigOperator.java b/core/api/src/main/java/org/onosproject/net/config/PortConfigOperator.java
new file mode 100644
index 0000000..47886b2
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/config/PortConfigOperator.java
@@ -0,0 +1,62 @@
+/*
+ * 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.net.config;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.PortDescription;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * {@link ConfigOperator} for Port.
+ * <p>
+ * Note: We currently assumes {@link PortConfigOperator}s are commutative.
+ */
+@Beta
+public interface PortConfigOperator extends ConfigOperator {
+
+ /**
+ * Binds {@link NetworkConfigService} to use for retrieving configuration.
+ *
+ * @param networkConfigService the service to use
+ */
+ void bindService(NetworkConfigService networkConfigService);
+
+
+ /**
+ * Generates a PortDescription containing fields from a PortDescription and
+ * configuration.
+ *
+ * @param cp {@link ConnectPoint} representing the port.
+ * @param descr input {@link PortDescription}
+ * @return Combined {@link PortDescription}
+ */
+ PortDescription combine(ConnectPoint cp, PortDescription descr);
+
+ /**
+ * Generates a PortDescription containing fields from a PortDescription and
+ * configuration.
+ *
+ * @param did DeviceId which the port described by {@code descr} resides.
+ * @param descr input {@link PortDescription}
+ * @return Combined {@link PortDescription}
+ */
+ default PortDescription combine(DeviceId did, PortDescription descr) {
+ return combine(new ConnectPoint(did, descr.portNumber()), descr);
+ }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/config/PortConfigOperatorRegistry.java b/core/api/src/main/java/org/onosproject/net/config/PortConfigOperatorRegistry.java
new file mode 100644
index 0000000..dce315c
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/config/PortConfigOperatorRegistry.java
@@ -0,0 +1,44 @@
+/*
+ * 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.net.config;
+
+import org.onosproject.net.ConnectPoint;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Abstraction of a port operator registry.
+ */
+@Beta
+public interface PortConfigOperatorRegistry {
+
+ /**
+ * Registers {@link PortConfigOperator} instance.
+ *
+ * @param portOp {@link PortConfigOperator} instance.
+ * @param configs {@link Config} class for a Port referred by {@code portOp}
+ */
+ void registerPortConfigOperator(PortConfigOperator portOp,
+ Class<? extends Config<ConnectPoint>>... configs);
+
+ /**
+ * Unregisters {@link PortConfigOperator} instance.
+ *
+ * @param portOp {@link PortConfigOperator} instance.
+ */
+ void unregisterPortConfigOperator(PortConfigOperator portOp);
+
+}
diff --git a/core/net/pom.xml b/core/net/pom.xml
index 428ec4d..32b4ab5 100644
--- a/core/net/pom.xml
+++ b/core/net/pom.xml
@@ -105,9 +105,7 @@
</dependency>
<!-- TODO Remove after decoupling optical -->
- <!-- - DeviceManager.InternalDeviceProviderService#ensureGeneric -->
<!-- - OpticalCompilers x4 -->
- <!-- - OpticalPortOperator -->
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-optical-model</artifactId>
diff --git a/core/net/src/main/java/org/onosproject/net/config/impl/BasicNetworkConfigs.java b/core/net/src/main/java/org/onosproject/net/config/impl/BasicNetworkConfigs.java
index a40f86a..d02b4cb 100644
--- a/core/net/src/main/java/org/onosproject/net/config/impl/BasicNetworkConfigs.java
+++ b/core/net/src/main/java/org/onosproject/net/config/impl/BasicNetworkConfigs.java
@@ -34,7 +34,6 @@
import org.onosproject.net.config.basics.BasicDeviceConfig;
import org.onosproject.net.config.basics.BasicHostConfig;
import org.onosproject.net.config.basics.BasicLinkConfig;
-import org.onosproject.net.config.basics.OpticalPortConfig;
import org.onosproject.net.config.basics.SubjectFactories;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -85,15 +84,6 @@
public BasicLinkConfig createConfig() {
return new BasicLinkConfig();
}
- },
- // TODO move this optical specific configuration out to optical app
- new ConfigFactory<ConnectPoint, OpticalPortConfig>(CONNECT_POINT_SUBJECT_FACTORY,
- OpticalPortConfig.class,
- "optical") {
- @Override
- public OpticalPortConfig createConfig() {
- return new OpticalPortConfig();
- }
}
);
diff --git a/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java b/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java
index 23aba6a..cd3c543 100644
--- a/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java
+++ b/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java
@@ -19,19 +19,22 @@
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
-
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.Tools;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.NodeId;
import org.onosproject.mastership.MastershipEvent;
@@ -46,11 +49,13 @@
import org.onosproject.net.MastershipRole;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.PortConfigOperator;
+import org.onosproject.net.config.PortConfigOperatorRegistry;
import org.onosproject.net.config.basics.BasicDeviceConfig;
-import org.onosproject.net.config.basics.OpticalPortConfig;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceAdminService;
import org.onosproject.net.device.DeviceDescription;
@@ -62,29 +67,23 @@
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.DeviceStore;
import org.onosproject.net.device.DeviceStoreDelegate;
-import org.onosproject.net.device.OchPortDescription;
-import org.onosproject.net.device.OduCltPortDescription;
-import org.onosproject.net.device.OmsPortDescription;
-import org.onosproject.net.device.OtuPortDescription;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.device.PortStatistics;
-import org.onosproject.net.optical.device.OmsPortHelper;
-import org.onosproject.net.optical.device.OtuPortHelper;
import org.onosproject.net.provider.AbstractListenerProviderRegistry;
import org.onosproject.net.provider.AbstractProviderService;
-import org.onosproject.net.provider.Provider;
import org.slf4j.Logger;
+import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.Futures;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Multimaps.newListMultimap;
+import static com.google.common.collect.Multimaps.synchronizedListMultimap;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.MastershipRole.MASTER;
import static org.onosproject.net.MastershipRole.NONE;
import static org.onosproject.net.MastershipRole.STANDBY;
-import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
-import static org.onosproject.net.optical.device.OduCltPortHelper.oduCltPortDescription;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.onosproject.security.AppPermission.Type.DEVICE_READ;
import static org.slf4j.LoggerFactory.getLogger;
@@ -96,7 +95,7 @@
@Service
public class DeviceManager
extends AbstractListenerProviderRegistry<DeviceEvent, DeviceListener, DeviceProvider, DeviceProviderService>
- implements DeviceService, DeviceAdminService, DeviceProviderRegistry {
+ implements DeviceService, DeviceAdminService, DeviceProviderRegistry, PortConfigOperatorRegistry {
private static final String DEVICE_ID_NULL = "Device ID cannot be null";
private static final String PORT_NUMBER_NULL = "Port number cannot be null";
@@ -130,6 +129,20 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigService networkConfigService;
+
+ /**
+ * List of all registered PortConfigOperator.
+ */
+ private final List<PortConfigOperator> portOps = new CopyOnWriteArrayList<>();
+
+ /**
+ * Index to look up PortConfigOperator from Config each PortConfigOperator uses.
+ */
+ private final Multimap<Class<? extends Config<ConnectPoint>>, PortConfigOperator> portOpsIndex
+ = synchronizedListMultimap(
+ newListMultimap(new ConcurrentHashMap<>(), CopyOnWriteArrayList::new));
+
+
@Activate
public void activate() {
backgroundService = newSingleThreadScheduledExecutor(
@@ -445,60 +458,6 @@
}
}
- /**
- * Transforms optical specific PortDescription to generic PortDescription.
- *
- * @param descr PortDescription
- * @return generic PortDescription
- * @deprecated in Goldeneye (1.6.0)
- */
- @Deprecated
- private PortDescription ensureGeneric(PortDescription descr) {
- switch (descr.type()) {
- case OCH:
- if (descr instanceof OchPortDescription) {
- OchPortDescription och = (OchPortDescription) descr;
- return ochPortDescription(och,
- och.signalType(),
- och.isTunable(),
- och.lambda(),
- och.annotations());
- }
- break;
- case ODUCLT:
- if (descr instanceof OduCltPortDescription) {
- OduCltPortDescription clt = (OduCltPortDescription) descr;
- return oduCltPortDescription(clt,
- clt.signalType(),
- clt.annotations());
- }
- break;
- case OMS:
- if (descr instanceof OmsPortDescription) {
- OmsPortDescription oms = (OmsPortDescription) descr;
- return OmsPortHelper.omsPortDescription(oms,
- oms.minFrequency(),
- oms.maxFrequency(),
- oms.grid(),
- oms.annotations());
- }
- break;
- case OTU:
- if (descr instanceof OtuPortDescription) {
- OtuPortDescription otu = (OtuPortDescription) descr;
- return OtuPortHelper.otuPortDescription(otu,
- otu.signalType(),
- otu.annotations());
- }
- break;
-
- default:
- // no-op
- break;
- }
- return descr;
- }
-
@Override
public void updatePorts(DeviceId deviceId,
List<PortDescription> portDescriptions) {
@@ -512,8 +471,7 @@
return;
}
portDescriptions = portDescriptions.stream()
- .map(e -> consolidate(deviceId, e))
- .map(this::ensureGeneric)
+ .map(e -> applyAllPortOps(deviceId, e))
.collect(Collectors.toList());
List<DeviceEvent> events = store.updatePorts(this.provider().id(),
deviceId, portDescriptions);
@@ -552,30 +510,16 @@
portDescription.isEnabled());
}
- portDescription = consolidate(deviceId, portDescription);
+ portDescription = applyAllPortOps(deviceId, portDescription);
final DeviceEvent event = store.updatePortStatus(this.provider().id(),
deviceId,
- ensureGeneric(portDescription));
+ portDescription);
if (event != null) {
log.info("Device {} port {} status changed", deviceId, event.port().number());
post(event);
}
}
- // merges the appropriate PortConfig with the description.
- private PortDescription consolidate(DeviceId did, PortDescription desc) {
- switch (desc.type()) {
- case COPPER:
- case VIRTUAL:
- return desc;
- default:
- // TODO: add plugin mechanism in order to decouple this
- OpticalPortConfig opc = networkConfigService.getConfig(
- new ConnectPoint(did, desc.portNumber()), OpticalPortConfig.class);
- return OpticalPortOperator.combine(opc, desc);
- }
- }
-
@Override
public void receivedRoleReply(DeviceId deviceId, MastershipRole requested,
MastershipRole response) {
@@ -835,7 +779,7 @@
return (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED
|| event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)
&& (event.configClass().equals(BasicDeviceConfig.class)
- || event.configClass().equals(OpticalPortConfig.class));
+ || portOpsIndex.containsKey(event.configClass()));
}
@Override
@@ -857,20 +801,17 @@
}
}
}
- if (event.configClass().equals(OpticalPortConfig.class)) {
+ if (portOpsIndex.containsKey(event.configClass())) {
ConnectPoint cpt = (ConnectPoint) event.subject();
DeviceId did = cpt.deviceId();
- Provider provider = getProvider(did);
- Port dpt = getPort(did, cpt.port());
- if (dpt != null && provider != null) {
- OpticalPortConfig opc = networkConfigService.getConfig(cpt, OpticalPortConfig.class);
- PortDescription desc = store.getPortDescription(provider.id(), did, cpt.port());
- desc = OpticalPortOperator.combine(opc, desc);
- if (desc != null) {
- de = store.updatePortStatus(getProvider(did).id(), did, desc);
- }
- }
+ // Note: assuming PortOperator can modify existing port,
+ // but cannot add new port purely from Config.
+ de = Optional.ofNullable(getProvider(did))
+ .map(provider -> store.getPortDescription(provider.id(), did, cpt.port()))
+ .map(desc -> applyAllPortOps(cpt, desc))
+ .map(desc -> store.updatePortStatus(getProvider(did).id(), did, desc))
+ .orElse(null);
}
if (de != null) {
@@ -888,4 +829,78 @@
}
}
+ @Override
+ @SafeVarargs
+ public final void registerPortConfigOperator(PortConfigOperator portOp,
+ Class<? extends Config<ConnectPoint>>...configs) {
+ checkNotNull(portOp);
+
+ portOp.bindService(networkConfigService);
+
+ // update both portOpsIndex and portOps
+ synchronized (portOpsIndex) {
+ for (Class<? extends Config<ConnectPoint>> config : configs) {
+ portOpsIndex.put(config, portOp);
+ }
+
+ portOps.add(portOp);
+ }
+
+ // TODO: Should we be applying to all existing Ports?
+ Tools.stream(store.getAvailableDevices())
+ .map(Device::id)
+ .filter(mastershipService::isLocalMaster)
+ // for each locally managed Device, update all port descriptions
+ .map(did -> {
+ List<PortDescription> pds
+ = store.getPortDescriptions(getProvider(did).id(), did)
+ .map(pdesc -> applyAllPortOps(did, pdesc))
+ .collect(Collectors.toList());
+ return store.updatePorts(getProvider(did).id(), did, pds);
+ })
+ // ..and port port update event if necessary
+ .forEach(evts -> evts.forEach(this::post));
+ }
+
+ @Override
+ public void unregisterPortConfigOperator(PortConfigOperator portOp) {
+ checkNotNull(portOp);
+
+
+ // remove all portOp
+ synchronized (portOpsIndex) {
+ portOps.remove(portOp);
+
+ // had to do this since COWArrayList iterator doesn't support remove
+ portOpsIndex.keySet().forEach(key -> portOpsIndex.remove(key, portOp));
+ }
+
+ }
+
+ /**
+ * Merges the appropriate PortConfig with the description.
+ *
+ * @param did ID of the Device where the port is attached
+ * @param desc {@link PortDescription}
+ * @return merged {@link PortDescription}
+ */
+ private PortDescription applyAllPortOps(DeviceId did, PortDescription desc) {
+ return applyAllPortOps(new ConnectPoint(did, desc.portNumber()), desc);
+ }
+
+ /**
+ * Merges the appropriate PortConfig with the description.
+ *
+ * @param cpt ConnectPoint where the port is attached
+ * @param desc {@link PortDescription}
+ * @return merged {@link PortDescription}
+ */
+ private PortDescription applyAllPortOps(ConnectPoint cpt, PortDescription desc) {
+ PortDescription work = desc;
+ for (PortConfigOperator portOp : portOps) {
+ work = portOp.combine(cpt, work);
+ }
+ return work;
+ }
+
}