aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java')
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java218
1 files changed, 218 insertions, 0 deletions
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java
new file mode 100644
index 00000000..01348c15
--- /dev/null
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2015 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.impl;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Maps;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Component for loading the initial network configuration.
+ */
+@Component(immediate = true)
+public class NetworkConfigLoader {
+
+ private static final File CFG_FILE = new File("../config/network-cfg.json");
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigService networkConfigService;
+
+ // FIXME: Add mutual exclusion to make sure this happens only once per startup.
+
+ private final Map<InnerConfigPosition, JsonNode> jsons = Maps.newConcurrentMap();
+
+ private final NetworkConfigListener configListener = new InnerConfigListener();
+
+ private ObjectNode root;
+
+ @Activate
+ public void activate() {
+ //TODO Maybe this should be at the bottom to avoid a potential race
+ networkConfigService.addListener(configListener);
+ try {
+ if (CFG_FILE.exists()) {
+ root = (ObjectNode) new ObjectMapper().readTree(CFG_FILE);
+
+ populateConfigurations();
+
+ applyConfigurations();
+
+ log.info("Loaded initial network configuration from {}", CFG_FILE);
+ }
+ } catch (Exception e) {
+ log.warn("Unable to load initial network configuration from {}",
+ CFG_FILE, e);
+ }
+ }
+
+ @Deactivate
+ public void deactivate() {
+ networkConfigService.removeListener(configListener);
+ }
+ // sweep through pending config jsons and try to add them
+
+ /**
+ * Inner class that allows for handling of newly added NetConfig types.
+ */
+ private final class InnerConfigListener implements NetworkConfigListener {
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ //TODO should this be done for other types of NetworkConfigEvents?
+ if (event.type() == NetworkConfigEvent.Type.CONFIG_REGISTERED ||
+ event.type() == NetworkConfigEvent.Type.CONFIG_ADDED) {
+ applyConfigurations();
+ }
+
+ }
+ }
+
+ /**
+ * Inner class that allows for tracking of JSON class configurations.
+ */
+ private final class InnerConfigPosition {
+ private final String subjectKey, subject, configKey;
+
+ private String subjectKey() {
+ return subjectKey;
+ }
+
+ private String subject() {
+ return subject;
+ }
+
+ private String configKey() {
+ return configKey;
+ }
+
+ private InnerConfigPosition(String subjectKey, String subject, String configKey) {
+ this.subjectKey = subjectKey;
+ this.subject = subject;
+ this.configKey = configKey;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof InnerConfigPosition) {
+ final InnerConfigPosition that = (InnerConfigPosition) obj;
+ return Objects.equals(this.subjectKey, that.subjectKey)
+ && Objects.equals(this.subject, that.subject)
+ && Objects.equals(this.configKey, that.configKey);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(subjectKey, subject, configKey);
+ }
+ }
+
+ /**
+ * Save the JSON leaves associated with a specific subject key.
+ *
+ * @param sk the subject key string.
+ * @param node the node associated with the subject key.
+ */
+ private void saveJson(String sk, ObjectNode node) {
+ node.fieldNames().forEachRemaining(s ->
+ saveSubjectJson(sk, s, (ObjectNode) node.path(s)));
+ }
+
+ /**
+ * Save the JSON leaves of the tree rooted as the node 'node' with subject key 'sk'.
+ *
+ * @param sk the string of the subject key.
+ * @param s the subject name.
+ * @param node the node rooting this subtree.
+ */
+ private void saveSubjectJson(String sk,
+ String s, ObjectNode node) {
+ node.fieldNames().forEachRemaining(c ->
+ this.jsons.put(new InnerConfigPosition(sk, s, c), node.path(c)));
+ }
+
+ /**
+ * Iterate through the JSON and populate a list of the leaf nodes of the structure.
+ */
+ private void populateConfigurations() {
+ root.fieldNames().forEachRemaining(sk ->
+ saveJson(sk, (ObjectNode) root.path(sk)));
+
+ }
+
+ /**
+ * Apply the configurations associated with all of the config classes that
+ * are imported and have not yet been applied.
+ */
+ private void applyConfigurations() {
+ Iterator<Map.Entry<InnerConfigPosition, JsonNode>> iter = jsons.entrySet().iterator();
+
+ Map.Entry<InnerConfigPosition, JsonNode> entry;
+ InnerConfigPosition key;
+ JsonNode node;
+ String subjectKey;
+ String subjectString;
+ String configKey;
+
+ while (iter.hasNext()) {
+ entry = iter.next();
+ node = entry.getValue();
+ key = entry.getKey();
+ subjectKey = key.subjectKey();
+ subjectString = key.subject();
+ configKey = key.configKey();
+
+ Class<? extends Config> configClass =
+ networkConfigService.getConfigClass(subjectKey, configKey);
+ //Check that the config class has been imported
+ if (configClass != null) {
+
+ Object subject = networkConfigService.getSubjectFactory(subjectKey).
+ createSubject(subjectString);
+
+ //Apply the configuration
+ networkConfigService.applyConfig(subject, configClass, node);
+
+ //Now that it has been applied the corresponding JSON entry is no longer needed
+ iter.remove();
+ }
+ }
+ }
+
+}