blob: 01348c15824f95b8ac59d61b8548a3afd9780922 [file] [log] [blame]
Thomas Vachuskae6360222015-07-21 10:10:36 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Thomas Vachuska4998caa2015-08-26 13:28:38 -070016package org.onosproject.net.config.impl;
Thomas Vachuskae6360222015-07-21 10:10:36 -070017
Jonathan Harted4fdcd2015-09-08 14:13:37 -070018import com.fasterxml.jackson.databind.JsonNode;
Thomas Vachuskae6360222015-07-21 10:10:36 -070019import com.fasterxml.jackson.databind.ObjectMapper;
20import com.fasterxml.jackson.databind.node.ObjectNode;
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070021import com.google.common.collect.Maps;
Thomas Vachuskae6360222015-07-21 10:10:36 -070022import org.apache.felix.scr.annotations.Activate;
23import org.apache.felix.scr.annotations.Component;
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070024import org.apache.felix.scr.annotations.Deactivate;
Thomas Vachuskae6360222015-07-21 10:10:36 -070025import org.apache.felix.scr.annotations.Reference;
26import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Hart4cb39882015-08-12 23:50:55 -040027import org.onosproject.net.config.Config;
Ray Milkeya4122362015-08-18 15:19:08 -070028import org.onosproject.net.config.NetworkConfigEvent;
29import org.onosproject.net.config.NetworkConfigListener;
30import org.onosproject.net.config.NetworkConfigService;
Thomas Vachuskae6360222015-07-21 10:10:36 -070031import org.slf4j.Logger;
32import org.slf4j.LoggerFactory;
33
34import java.io.File;
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070035import java.util.Iterator;
36import java.util.Map;
37import java.util.Objects;
Thomas Vachuskae6360222015-07-21 10:10:36 -070038
39/**
40 * Component for loading the initial network configuration.
41 */
42@Component(immediate = true)
43public class NetworkConfigLoader {
44
45 private static final File CFG_FILE = new File("../config/network-cfg.json");
46
47 private final Logger log = LoggerFactory.getLogger(getClass());
48
49 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
50 protected NetworkConfigService networkConfigService;
51
52 // FIXME: Add mutual exclusion to make sure this happens only once per startup.
53
Jonathan Harted4fdcd2015-09-08 14:13:37 -070054 private final Map<InnerConfigPosition, JsonNode> jsons = Maps.newConcurrentMap();
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070055
56 private final NetworkConfigListener configListener = new InnerConfigListener();
57
Jonathan Hart4cb39882015-08-12 23:50:55 -040058 private ObjectNode root;
Thomas Vachuskae6360222015-07-21 10:10:36 -070059
60 @Activate
61 public void activate() {
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070062 //TODO Maybe this should be at the bottom to avoid a potential race
63 networkConfigService.addListener(configListener);
Thomas Vachuskae6360222015-07-21 10:10:36 -070064 try {
65 if (CFG_FILE.exists()) {
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070066 root = (ObjectNode) new ObjectMapper().readTree(CFG_FILE);
Thomas Vachuskae6360222015-07-21 10:10:36 -070067
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070068 populateConfigurations();
Thomas Vachuskae6360222015-07-21 10:10:36 -070069
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070070 applyConfigurations();
71
Thomas Vachuskae6360222015-07-21 10:10:36 -070072 log.info("Loaded initial network configuration from {}", CFG_FILE);
73 }
74 } catch (Exception e) {
75 log.warn("Unable to load initial network configuration from {}",
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070076 CFG_FILE, e);
Thomas Vachuskae6360222015-07-21 10:10:36 -070077 }
78 }
79
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070080 @Deactivate
81 public void deactivate() {
82 networkConfigService.removeListener(configListener);
83 }
Thomas Vachuskae6360222015-07-21 10:10:36 -070084 // sweep through pending config jsons and try to add them
85
86 /**
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070087 * Inner class that allows for handling of newly added NetConfig types.
Thomas Vachuskae6360222015-07-21 10:10:36 -070088 */
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070089 private final class InnerConfigListener implements NetworkConfigListener {
90
91 @Override
92 public void event(NetworkConfigEvent event) {
93 //TODO should this be done for other types of NetworkConfigEvents?
94 if (event.type() == NetworkConfigEvent.Type.CONFIG_REGISTERED ||
95 event.type() == NetworkConfigEvent.Type.CONFIG_ADDED) {
96 applyConfigurations();
97 }
98
99 }
Thomas Vachuskae6360222015-07-21 10:10:36 -0700100 }
101
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700102 /**
103 * Inner class that allows for tracking of JSON class configurations.
104 */
105 private final class InnerConfigPosition {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400106 private final String subjectKey, subject, configKey;
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700107
Jonathan Hart4cb39882015-08-12 23:50:55 -0400108 private String subjectKey() {
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700109 return subjectKey;
110 }
111
Jonathan Hart4cb39882015-08-12 23:50:55 -0400112 private String subject() {
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700113 return subject;
114 }
115
Jonathan Hart4cb39882015-08-12 23:50:55 -0400116 private String configKey() {
117 return configKey;
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700118 }
119
Jonathan Hart4cb39882015-08-12 23:50:55 -0400120 private InnerConfigPosition(String subjectKey, String subject, String configKey) {
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700121 this.subjectKey = subjectKey;
122 this.subject = subject;
Jonathan Hart4cb39882015-08-12 23:50:55 -0400123 this.configKey = configKey;
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700124 }
125
126 @Override
127 public boolean equals(Object obj) {
128 if (this == obj) {
129 return true;
130 }
131 if (obj instanceof InnerConfigPosition) {
132 final InnerConfigPosition that = (InnerConfigPosition) obj;
Jonathan Hart4cb39882015-08-12 23:50:55 -0400133 return Objects.equals(this.subjectKey, that.subjectKey)
134 && Objects.equals(this.subject, that.subject)
135 && Objects.equals(this.configKey, that.configKey);
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700136 }
137 return false;
138 }
139
140 @Override
141 public int hashCode() {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400142 return Objects.hash(subjectKey, subject, configKey);
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700143 }
144 }
145
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700146 /**
147 * Save the JSON leaves associated with a specific subject key.
148 *
149 * @param sk the subject key string.
150 * @param node the node associated with the subject key.
151 */
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700152 private void saveJson(String sk, ObjectNode node) {
153 node.fieldNames().forEachRemaining(s ->
154 saveSubjectJson(sk, s, (ObjectNode) node.path(s)));
155 }
156
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700157 /**
158 * Save the JSON leaves of the tree rooted as the node 'node' with subject key 'sk'.
159 *
160 * @param sk the string of the subject key.
161 * @param s the subject name.
162 * @param node the node rooting this subtree.
163 */
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700164 private void saveSubjectJson(String sk,
165 String s, ObjectNode node) {
166 node.fieldNames().forEachRemaining(c ->
Jonathan Harted4fdcd2015-09-08 14:13:37 -0700167 this.jsons.put(new InnerConfigPosition(sk, s, c), node.path(c)));
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700168 }
169
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700170 /**
171 * Iterate through the JSON and populate a list of the leaf nodes of the structure.
172 */
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700173 private void populateConfigurations() {
174 root.fieldNames().forEachRemaining(sk ->
175 saveJson(sk, (ObjectNode) root.path(sk)));
176
177 }
178
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700179 /**
Jonathan Hart4cb39882015-08-12 23:50:55 -0400180 * Apply the configurations associated with all of the config classes that
181 * are imported and have not yet been applied.
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700182 */
Jonathan Hart4cb39882015-08-12 23:50:55 -0400183 private void applyConfigurations() {
Jonathan Harted4fdcd2015-09-08 14:13:37 -0700184 Iterator<Map.Entry<InnerConfigPosition, JsonNode>> iter = jsons.entrySet().iterator();
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700185
Jonathan Harted4fdcd2015-09-08 14:13:37 -0700186 Map.Entry<InnerConfigPosition, JsonNode> entry;
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700187 InnerConfigPosition key;
Jonathan Harted4fdcd2015-09-08 14:13:37 -0700188 JsonNode node;
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700189 String subjectKey;
Jonathan Hart4cb39882015-08-12 23:50:55 -0400190 String subjectString;
191 String configKey;
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700192
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700193 while (iter.hasNext()) {
194 entry = iter.next();
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700195 node = entry.getValue();
196 key = entry.getKey();
Jonathan Hart4cb39882015-08-12 23:50:55 -0400197 subjectKey = key.subjectKey();
198 subjectString = key.subject();
199 configKey = key.configKey();
200
201 Class<? extends Config> configClass =
202 networkConfigService.getConfigClass(subjectKey, configKey);
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700203 //Check that the config class has been imported
Jonathan Hart4cb39882015-08-12 23:50:55 -0400204 if (configClass != null) {
205
206 Object subject = networkConfigService.getSubjectFactory(subjectKey).
207 createSubject(subjectString);
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700208
209 //Apply the configuration
Jonathan Hart4cb39882015-08-12 23:50:55 -0400210 networkConfigService.applyConfig(subject, configClass, node);
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700211
212 //Now that it has been applied the corresponding JSON entry is no longer needed
Jonathan Hart4cb39882015-08-12 23:50:55 -0400213 iter.remove();
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700214 }
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700215 }
Thomas Vachuskae6360222015-07-21 10:10:36 -0700216 }
217
218}