blob: 810ca6ca3faf0dc778ca8c19844562e810a004c2 [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
18import com.fasterxml.jackson.databind.ObjectMapper;
19import com.fasterxml.jackson.databind.node.ObjectNode;
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070020import com.google.common.collect.Maps;
Thomas Vachuskae6360222015-07-21 10:10:36 -070021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070023import org.apache.felix.scr.annotations.Deactivate;
Thomas Vachuskae6360222015-07-21 10:10:36 -070024import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Hart4cb39882015-08-12 23:50:55 -040026import org.onosproject.net.config.Config;
Ray Milkeya4122362015-08-18 15:19:08 -070027import org.onosproject.net.config.NetworkConfigEvent;
28import org.onosproject.net.config.NetworkConfigListener;
29import org.onosproject.net.config.NetworkConfigService;
Thomas Vachuskae6360222015-07-21 10:10:36 -070030import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
33import java.io.File;
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070034import java.util.Iterator;
35import java.util.Map;
36import java.util.Objects;
Thomas Vachuskae6360222015-07-21 10:10:36 -070037
38/**
39 * Component for loading the initial network configuration.
40 */
41@Component(immediate = true)
42public class NetworkConfigLoader {
43
44 private static final File CFG_FILE = new File("../config/network-cfg.json");
45
46 private final Logger log = LoggerFactory.getLogger(getClass());
47
48 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
49 protected NetworkConfigService networkConfigService;
50
51 // FIXME: Add mutual exclusion to make sure this happens only once per startup.
52
Jonathan Hart4cb39882015-08-12 23:50:55 -040053 private final Map<InnerConfigPosition, ObjectNode> jsons = Maps.newConcurrentMap();
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070054
55 private final NetworkConfigListener configListener = new InnerConfigListener();
56
Jonathan Hart4cb39882015-08-12 23:50:55 -040057 private ObjectNode root;
Thomas Vachuskae6360222015-07-21 10:10:36 -070058
59 @Activate
60 public void activate() {
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070061 //TODO Maybe this should be at the bottom to avoid a potential race
62 networkConfigService.addListener(configListener);
Thomas Vachuskae6360222015-07-21 10:10:36 -070063 try {
64 if (CFG_FILE.exists()) {
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070065 root = (ObjectNode) new ObjectMapper().readTree(CFG_FILE);
Thomas Vachuskae6360222015-07-21 10:10:36 -070066
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070067 populateConfigurations();
Thomas Vachuskae6360222015-07-21 10:10:36 -070068
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070069 applyConfigurations();
70
Thomas Vachuskae6360222015-07-21 10:10:36 -070071 log.info("Loaded initial network configuration from {}", CFG_FILE);
72 }
73 } catch (Exception e) {
74 log.warn("Unable to load initial network configuration from {}",
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070075 CFG_FILE, e);
Thomas Vachuskae6360222015-07-21 10:10:36 -070076 }
77 }
78
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070079 @Deactivate
80 public void deactivate() {
81 networkConfigService.removeListener(configListener);
82 }
Thomas Vachuskae6360222015-07-21 10:10:36 -070083 // sweep through pending config jsons and try to add them
84
85 /**
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070086 * Inner class that allows for handling of newly added NetConfig types.
Thomas Vachuskae6360222015-07-21 10:10:36 -070087 */
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -070088 private final class InnerConfigListener implements NetworkConfigListener {
89
90 @Override
91 public void event(NetworkConfigEvent event) {
92 //TODO should this be done for other types of NetworkConfigEvents?
93 if (event.type() == NetworkConfigEvent.Type.CONFIG_REGISTERED ||
94 event.type() == NetworkConfigEvent.Type.CONFIG_ADDED) {
95 applyConfigurations();
96 }
97
98 }
Thomas Vachuskae6360222015-07-21 10:10:36 -070099 }
100
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700101 /**
102 * Inner class that allows for tracking of JSON class configurations.
103 */
104 private final class InnerConfigPosition {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400105 private final String subjectKey, subject, configKey;
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700106
Jonathan Hart4cb39882015-08-12 23:50:55 -0400107 private String subjectKey() {
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700108 return subjectKey;
109 }
110
Jonathan Hart4cb39882015-08-12 23:50:55 -0400111 private String subject() {
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700112 return subject;
113 }
114
Jonathan Hart4cb39882015-08-12 23:50:55 -0400115 private String configKey() {
116 return configKey;
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700117 }
118
Jonathan Hart4cb39882015-08-12 23:50:55 -0400119 private InnerConfigPosition(String subjectKey, String subject, String configKey) {
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700120 this.subjectKey = subjectKey;
121 this.subject = subject;
Jonathan Hart4cb39882015-08-12 23:50:55 -0400122 this.configKey = configKey;
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700123 }
124
125 @Override
126 public boolean equals(Object obj) {
127 if (this == obj) {
128 return true;
129 }
130 if (obj instanceof InnerConfigPosition) {
131 final InnerConfigPosition that = (InnerConfigPosition) obj;
Jonathan Hart4cb39882015-08-12 23:50:55 -0400132 return Objects.equals(this.subjectKey, that.subjectKey)
133 && Objects.equals(this.subject, that.subject)
134 && Objects.equals(this.configKey, that.configKey);
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700135 }
136 return false;
137 }
138
139 @Override
140 public int hashCode() {
Jonathan Hart4cb39882015-08-12 23:50:55 -0400141 return Objects.hash(subjectKey, subject, configKey);
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700142 }
143 }
144
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700145 /**
146 * Save the JSON leaves associated with a specific subject key.
147 *
148 * @param sk the subject key string.
149 * @param node the node associated with the subject key.
150 */
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700151 private void saveJson(String sk, ObjectNode node) {
152 node.fieldNames().forEachRemaining(s ->
153 saveSubjectJson(sk, s, (ObjectNode) node.path(s)));
154 }
155
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700156 /**
157 * Save the JSON leaves of the tree rooted as the node 'node' with subject key 'sk'.
158 *
159 * @param sk the string of the subject key.
160 * @param s the subject name.
161 * @param node the node rooting this subtree.
162 */
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700163 private void saveSubjectJson(String sk,
164 String s, ObjectNode node) {
165 node.fieldNames().forEachRemaining(c ->
166 this.jsons.put(new InnerConfigPosition(sk, s, c), (ObjectNode) node.path(c)));
167 }
168
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700169 /**
170 * Iterate through the JSON and populate a list of the leaf nodes of the structure.
171 */
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700172 private void populateConfigurations() {
173 root.fieldNames().forEachRemaining(sk ->
174 saveJson(sk, (ObjectNode) root.path(sk)));
175
176 }
177
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700178 /**
Jonathan Hart4cb39882015-08-12 23:50:55 -0400179 * Apply the configurations associated with all of the config classes that
180 * are imported and have not yet been applied.
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700181 */
Jonathan Hart4cb39882015-08-12 23:50:55 -0400182 private void applyConfigurations() {
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700183 Iterator<Map.Entry<InnerConfigPosition, ObjectNode>> iter = jsons.entrySet().iterator();
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700184
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700185 Map.Entry<InnerConfigPosition, ObjectNode> entry;
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700186 InnerConfigPosition key;
187 ObjectNode node;
188 String subjectKey;
Jonathan Hart4cb39882015-08-12 23:50:55 -0400189 String subjectString;
190 String configKey;
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700191
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700192 while (iter.hasNext()) {
193 entry = iter.next();
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700194 node = entry.getValue();
195 key = entry.getKey();
Jonathan Hart4cb39882015-08-12 23:50:55 -0400196 subjectKey = key.subjectKey();
197 subjectString = key.subject();
198 configKey = key.configKey();
199
200 Class<? extends Config> configClass =
201 networkConfigService.getConfigClass(subjectKey, configKey);
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700202 //Check that the config class has been imported
Jonathan Hart4cb39882015-08-12 23:50:55 -0400203 if (configClass != null) {
204
205 Object subject = networkConfigService.getSubjectFactory(subjectKey).
206 createSubject(subjectString);
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700207
208 //Apply the configuration
Jonathan Hart4cb39882015-08-12 23:50:55 -0400209 networkConfigService.applyConfig(subject, configClass, node);
Aaron Kruglikova598c9e2015-07-23 16:56:27 -0700210
211 //Now that it has been applied the corresponding JSON entry is no longer needed
Jonathan Hart4cb39882015-08-12 23:50:55 -0400212 iter.remove();
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700213 }
Aaron Kruglikovbd1eb3f2015-07-21 10:39:06 -0700214 }
Thomas Vachuskae6360222015-07-21 10:10:36 -0700215 }
216
217}