blob: 9f041e6115a307cffeafdd7e48e22a270787a315 [file] [log] [blame]
Thomas Vachuska96d55b12015-05-11 08:52:03 -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 Vachuska96d55b12015-05-11 08:52:03 -070017
Thomas Vachuska0a400ea2015-09-04 11:25:03 -070018import com.fasterxml.jackson.databind.JsonNode;
Thomas Vachuska96d55b12015-05-11 08:52:03 -070019import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Maps;
21import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.apache.felix.scr.annotations.Service;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070027import org.onosproject.event.AbstractListenerManager;
Ray Milkeya4122362015-08-18 15:19:08 -070028import org.onosproject.net.config.Config;
29import org.onosproject.net.config.ConfigFactory;
30import org.onosproject.net.config.NetworkConfigEvent;
31import org.onosproject.net.config.NetworkConfigListener;
32import org.onosproject.net.config.NetworkConfigRegistry;
33import org.onosproject.net.config.NetworkConfigService;
34import org.onosproject.net.config.NetworkConfigStore;
35import org.onosproject.net.config.NetworkConfigStoreDelegate;
36import org.onosproject.net.config.SubjectFactory;
Thomas Vachuska96d55b12015-05-11 08:52:03 -070037import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
40import java.util.Map;
41import java.util.Objects;
42import java.util.Set;
43
44import static com.google.common.base.Preconditions.checkNotNull;
45
46/**
47 * Implementation of the network configuration subsystem.
48 */
49@Component(immediate = true)
50@Service
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070051public class NetworkConfigManager
52 extends AbstractListenerManager<NetworkConfigEvent, NetworkConfigListener>
53 implements NetworkConfigRegistry, NetworkConfigService {
Thomas Vachuska96d55b12015-05-11 08:52:03 -070054
55 private final Logger log = LoggerFactory.getLogger(getClass());
56
57 private static final String NULL_FACTORY_MSG = "Factory cannot be null";
58 private static final String NULL_SCLASS_MSG = "Subject class cannot be null";
Simon Hunt3da1a182016-02-08 16:42:54 -080059 private static final String NULL_SCKEY_MSG = "Subject class key cannot be null";
Thomas Vachuska96d55b12015-05-11 08:52:03 -070060 private static final String NULL_CCLASS_MSG = "Config class cannot be null";
Thomas Vachuska6f350ed2016-01-08 09:53:03 -080061 private static final String NULL_CKEY_MSG = "Config key cannot be null";
Thomas Vachuska96d55b12015-05-11 08:52:03 -070062 private static final String NULL_SUBJECT_MSG = "Subject cannot be null";
Thomas Vachuska6f350ed2016-01-08 09:53:03 -080063 private static final String NULL_JSON_MSG = "JSON cannot be null";
Thomas Vachuska96d55b12015-05-11 08:52:03 -070064
65 // Inventory of configuration factories
66 private final Map<ConfigKey, ConfigFactory> factories = Maps.newConcurrentMap();
67
Ray Milkey0a4f6c32015-08-03 11:22:01 -070068 // Secondary indices to retrieve subject and config classes by keys
Thomas Vachuska96d55b12015-05-11 08:52:03 -070069 private final Map<String, SubjectFactory> subjectClasses = Maps.newConcurrentMap();
70 private final Map<Class, SubjectFactory> subjectClassKeys = Maps.newConcurrentMap();
Jonathan Hart111b42b2015-07-14 13:28:05 -070071 private final Map<ConfigIdentifier, Class<? extends Config>> configClasses = Maps.newConcurrentMap();
Thomas Vachuska96d55b12015-05-11 08:52:03 -070072
Thomas Vachuska96d55b12015-05-11 08:52:03 -070073 private final NetworkConfigStoreDelegate storeDelegate = new InternalStoreDelegate();
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected NetworkConfigStore store;
77
Thomas Vachuska96d55b12015-05-11 08:52:03 -070078
79 @Activate
80 public void activate() {
81 eventDispatcher.addSink(NetworkConfigEvent.class, listenerRegistry);
82 store.setDelegate(storeDelegate);
83 log.info("Started");
84 }
85
86 @Deactivate
87 public void deactivate() {
88 eventDispatcher.removeSink(NetworkConfigEvent.class);
89 store.unsetDelegate(storeDelegate);
90 log.info("Stopped");
91 }
92
93
94 @Override
95 @SuppressWarnings("unchecked")
96 public void registerConfigFactory(ConfigFactory configFactory) {
97 checkNotNull(configFactory, NULL_FACTORY_MSG);
98 factories.put(key(configFactory), configFactory);
Jonathan Hart111b42b2015-07-14 13:28:05 -070099 configClasses.put(identifier(configFactory), configFactory.configClass());
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700100
101 SubjectFactory subjectFactory = configFactory.subjectFactory();
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700102 subjectClasses.putIfAbsent(subjectFactory.subjectClassKey(), subjectFactory);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700103 subjectClassKeys.putIfAbsent(subjectFactory.subjectClass(), subjectFactory);
104
105 store.addConfigFactory(configFactory);
106 }
107
108 @Override
109 public void unregisterConfigFactory(ConfigFactory configFactory) {
110 checkNotNull(configFactory, NULL_FACTORY_MSG);
111 factories.remove(key(configFactory));
Ray Milkey0a4f6c32015-08-03 11:22:01 -0700112 configClasses.remove(identifier(configFactory));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700113
114 // Note that we are deliberately not removing subject factory key bindings.
115 store.removeConfigFactory(configFactory);
116 }
117
118 @Override
119 public Set<ConfigFactory> getConfigFactories() {
120 return ImmutableSet.copyOf(factories.values());
121 }
122
123
124 @Override
125 @SuppressWarnings("unchecked")
126 public <S, C extends Config<S>> Set<ConfigFactory<S, C>> getConfigFactories(Class<S> subjectClass) {
127 ImmutableSet.Builder<ConfigFactory<S, C>> builder = ImmutableSet.builder();
128 factories.forEach((key, factory) -> {
129 if (factory.subjectFactory().subjectClass().equals(subjectClass)) {
130 builder.add(factory);
131 }
132 });
133 return builder.build();
134 }
135
136 @Override
137 public <S, C extends Config<S>> ConfigFactory<S, C> getConfigFactory(Class<C> configClass) {
138 checkNotNull(configClass, NULL_CCLASS_MSG);
139 return store.getConfigFactory(configClass);
140 }
141
142
143 @Override
144 public Set<Class> getSubjectClasses() {
145 ImmutableSet.Builder<Class> builder = ImmutableSet.builder();
146 factories.forEach((k, v) -> builder.add(k.subjectClass));
147 return builder.build();
148 }
149
150 @Override
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700151 public SubjectFactory getSubjectFactory(String subjectClassKey) {
152 return subjectClasses.get(subjectClassKey);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700153 }
154
155 @Override
156 public SubjectFactory getSubjectFactory(Class subjectClass) {
157 return subjectClassKeys.get(subjectClass);
158 }
159
160 @Override
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700161 public Class<? extends Config> getConfigClass(String subjectClassKey, String configKey) {
Simon Hunt3da1a182016-02-08 16:42:54 -0800162 checkNotNull(subjectClassKey, NULL_SCKEY_MSG);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800163 checkNotNull(configKey, NULL_CKEY_MSG);
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700164 return configClasses.get(new ConfigIdentifier(subjectClassKey, configKey));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700165 }
166
167 @Override
168 public <S> Set<S> getSubjects(Class<S> subjectClass) {
169 checkNotNull(subjectClass, NULL_SCLASS_MSG);
170 return store.getSubjects(subjectClass);
171 }
172
173 @Override
174 public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass) {
175 checkNotNull(subjectClass, NULL_SCLASS_MSG);
176 checkNotNull(configClass, NULL_CCLASS_MSG);
177 return store.getSubjects(subjectClass, configClass);
178 }
179
180 @Override
181 public <S> Set<Config<S>> getConfigs(S subject) {
182 checkNotNull(subject, NULL_SUBJECT_MSG);
183 Set<Class<? extends Config<S>>> configClasses = store.getConfigClasses(subject);
184 ImmutableSet.Builder<Config<S>> cfg = ImmutableSet.builder();
185 configClasses.forEach(cc -> cfg.add(store.getConfig(subject, cc)));
186 return cfg.build();
187 }
188
189 @Override
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800190 public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700191 checkNotNull(subject, NULL_SUBJECT_MSG);
192 checkNotNull(configClass, NULL_CCLASS_MSG);
193 return store.getConfig(subject, configClass);
194 }
195
196
197 @Override
198 public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
199 checkNotNull(subject, NULL_SUBJECT_MSG);
200 checkNotNull(configClass, NULL_CCLASS_MSG);
201 return store.createConfig(subject, configClass);
202 }
203
204 @Override
Thomas Vachuska0a400ea2015-09-04 11:25:03 -0700205 public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) {
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700206 checkNotNull(subject, NULL_SUBJECT_MSG);
207 checkNotNull(configClass, NULL_CCLASS_MSG);
Simon Hunt3da1a182016-02-08 16:42:54 -0800208 checkNotNull(json, NULL_JSON_MSG);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700209 return store.applyConfig(subject, configClass, json);
210 }
211
212 @Override
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800213 @SuppressWarnings("unchecked")
214 public <S, C extends Config<S>> C applyConfig(String subjectClassKey, S subject,
215 String configKey, JsonNode json) {
Simon Hunt3da1a182016-02-08 16:42:54 -0800216 checkNotNull(subjectClassKey, NULL_SCKEY_MSG);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800217 checkNotNull(subject, NULL_SUBJECT_MSG);
218 checkNotNull(configKey, NULL_CKEY_MSG);
Simon Hunt3da1a182016-02-08 16:42:54 -0800219 checkNotNull(json, NULL_JSON_MSG);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800220 Class<? extends Config> configClass = configClasses.get(new ConfigIdentifier(subjectClassKey, configKey));
221 if (configClass != null) {
222 return store.applyConfig(subject, (Class<C>) configClass, json);
223 } else {
Andrea Campanelladcb5e932016-01-11 17:32:23 -0800224 log.info("Configuration \'{}\' queued for subject {}", configKey, subject);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800225 store.queueConfig(subject, configKey, json);
226 return null;
227 }
228 }
229
230 @Override
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700231 public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) {
232 checkNotNull(subject, NULL_SUBJECT_MSG);
233 checkNotNull(configClass, NULL_CCLASS_MSG);
234 store.clearConfig(subject, configClass);
235 }
236
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800237 @Override
238 public <S> void removeConfig(String subjectClassKey, S subject, String configKey) {
Simon Hunt3da1a182016-02-08 16:42:54 -0800239 checkNotNull(subjectClassKey, NULL_SCKEY_MSG);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800240 checkNotNull(subject, NULL_SUBJECT_MSG);
Simon Hunt3da1a182016-02-08 16:42:54 -0800241 checkNotNull(configKey, NULL_CKEY_MSG);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800242 Class<? extends Config> configClass = configClasses.get(new ConfigIdentifier(subjectClassKey, configKey));
243 if (configClass != null) {
244 store.clearConfig(subject, configClass);
245 } else {
246 store.clearQueuedConfig(subject, configKey);
247 }
248 }
249
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700250 // Auxiliary store delegate to receive notification about changes in
251 // the network configuration store state - by the store itself.
252 private class InternalStoreDelegate implements NetworkConfigStoreDelegate {
253 @Override
254 public void notify(NetworkConfigEvent event) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700255 post(event);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700256 }
257 }
258
259
260 // Produces a key for uniquely tracking a config factory.
261 private static ConfigKey key(ConfigFactory factory) {
262 return new ConfigKey(factory.subjectFactory().subjectClass(), factory.configClass());
263 }
264
265 // Auxiliary key to track config factories.
Ray Milkeyae9faf12015-08-03 15:52:26 -0700266 protected static final class ConfigKey {
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700267 final Class subjectClass;
268 final Class configClass;
269
Ray Milkeyae9faf12015-08-03 15:52:26 -0700270 protected ConfigKey(Class subjectClass, Class configClass) {
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700271 this.subjectClass = subjectClass;
272 this.configClass = configClass;
273 }
274
275 @Override
276 public int hashCode() {
277 return Objects.hash(subjectClass, configClass);
278 }
279
280 @Override
281 public boolean equals(Object obj) {
282 if (this == obj) {
283 return true;
284 }
285 if (obj instanceof ConfigKey) {
286 final ConfigKey other = (ConfigKey) obj;
287 return Objects.equals(this.subjectClass, other.subjectClass)
288 && Objects.equals(this.configClass, other.configClass);
289 }
290 return false;
291 }
292 }
293
Jonathan Hart111b42b2015-07-14 13:28:05 -0700294 private static ConfigIdentifier identifier(ConfigFactory factory) {
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700295 return new ConfigIdentifier(factory.subjectFactory().subjectClassKey(), factory.configKey());
Jonathan Hart111b42b2015-07-14 13:28:05 -0700296 }
297
Thomas Vachuska4998caa2015-08-26 13:28:38 -0700298 static final class ConfigIdentifier {
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800299 final String subjectClassKey;
Jonathan Hart111b42b2015-07-14 13:28:05 -0700300 final String configKey;
301
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800302 protected ConfigIdentifier(String subjectClassKey, String configKey) {
303 this.subjectClassKey = subjectClassKey;
Jonathan Hart111b42b2015-07-14 13:28:05 -0700304 this.configKey = configKey;
305 }
306
307 @Override
308 public int hashCode() {
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800309 return Objects.hash(subjectClassKey, configKey);
Jonathan Hart111b42b2015-07-14 13:28:05 -0700310 }
311
312 @Override
313 public boolean equals(Object obj) {
314 if (this == obj) {
315 return true;
316 }
317 if (obj instanceof ConfigIdentifier) {
318 final ConfigIdentifier other = (ConfigIdentifier) obj;
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800319 return Objects.equals(this.subjectClassKey, other.subjectClassKey)
Jonathan Hart111b42b2015-07-14 13:28:05 -0700320 && Objects.equals(this.configKey, other.configKey);
321 }
322 return false;
323 }
324 }
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800325
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700326}