blob: bf33a25457411883c90b29cdf786a9d7ff639d18 [file] [log] [blame]
Thomas Vachuska96d55b12015-05-11 08:52:03 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuska96d55b12015-05-11 08:52:03 -07003 *
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;
Heedo Kang4a47a302016-02-29 17:40:23 +090045import static org.onosproject.security.AppGuard.checkPermission;
46import static org.onosproject.security.AppPermission.Type.*;
Thomas Vachuska96d55b12015-05-11 08:52:03 -070047
48/**
49 * Implementation of the network configuration subsystem.
50 */
51@Component(immediate = true)
52@Service
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070053public class NetworkConfigManager
54 extends AbstractListenerManager<NetworkConfigEvent, NetworkConfigListener>
55 implements NetworkConfigRegistry, NetworkConfigService {
Thomas Vachuska96d55b12015-05-11 08:52:03 -070056
57 private final Logger log = LoggerFactory.getLogger(getClass());
58
59 private static final String NULL_FACTORY_MSG = "Factory cannot be null";
60 private static final String NULL_SCLASS_MSG = "Subject class cannot be null";
Simon Hunt3da1a182016-02-08 16:42:54 -080061 private static final String NULL_SCKEY_MSG = "Subject class key cannot be null";
Thomas Vachuska96d55b12015-05-11 08:52:03 -070062 private static final String NULL_CCLASS_MSG = "Config class cannot be null";
Thomas Vachuska6f350ed2016-01-08 09:53:03 -080063 private static final String NULL_CKEY_MSG = "Config key cannot be null";
Thomas Vachuska96d55b12015-05-11 08:52:03 -070064 private static final String NULL_SUBJECT_MSG = "Subject cannot be null";
Thomas Vachuska6f350ed2016-01-08 09:53:03 -080065 private static final String NULL_JSON_MSG = "JSON cannot be null";
Thomas Vachuska96d55b12015-05-11 08:52:03 -070066
67 // Inventory of configuration factories
68 private final Map<ConfigKey, ConfigFactory> factories = Maps.newConcurrentMap();
69
Ray Milkey0a4f6c32015-08-03 11:22:01 -070070 // Secondary indices to retrieve subject and config classes by keys
Thomas Vachuska96d55b12015-05-11 08:52:03 -070071 private final Map<String, SubjectFactory> subjectClasses = Maps.newConcurrentMap();
72 private final Map<Class, SubjectFactory> subjectClassKeys = Maps.newConcurrentMap();
Jonathan Hart111b42b2015-07-14 13:28:05 -070073 private final Map<ConfigIdentifier, Class<? extends Config>> configClasses = Maps.newConcurrentMap();
Thomas Vachuska96d55b12015-05-11 08:52:03 -070074
Thomas Vachuska96d55b12015-05-11 08:52:03 -070075 private final NetworkConfigStoreDelegate storeDelegate = new InternalStoreDelegate();
76
77 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78 protected NetworkConfigStore store;
79
Thomas Vachuska96d55b12015-05-11 08:52:03 -070080
81 @Activate
82 public void activate() {
83 eventDispatcher.addSink(NetworkConfigEvent.class, listenerRegistry);
84 store.setDelegate(storeDelegate);
85 log.info("Started");
86 }
87
88 @Deactivate
89 public void deactivate() {
90 eventDispatcher.removeSink(NetworkConfigEvent.class);
91 store.unsetDelegate(storeDelegate);
92 log.info("Stopped");
93 }
94
95
96 @Override
97 @SuppressWarnings("unchecked")
98 public void registerConfigFactory(ConfigFactory configFactory) {
99 checkNotNull(configFactory, NULL_FACTORY_MSG);
100 factories.put(key(configFactory), configFactory);
Jonathan Hart111b42b2015-07-14 13:28:05 -0700101 configClasses.put(identifier(configFactory), configFactory.configClass());
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700102
103 SubjectFactory subjectFactory = configFactory.subjectFactory();
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700104 subjectClasses.putIfAbsent(subjectFactory.subjectClassKey(), subjectFactory);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700105 subjectClassKeys.putIfAbsent(subjectFactory.subjectClass(), subjectFactory);
106
107 store.addConfigFactory(configFactory);
108 }
109
110 @Override
111 public void unregisterConfigFactory(ConfigFactory configFactory) {
112 checkNotNull(configFactory, NULL_FACTORY_MSG);
113 factories.remove(key(configFactory));
Ray Milkey0a4f6c32015-08-03 11:22:01 -0700114 configClasses.remove(identifier(configFactory));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700115
116 // Note that we are deliberately not removing subject factory key bindings.
117 store.removeConfigFactory(configFactory);
118 }
119
120 @Override
121 public Set<ConfigFactory> getConfigFactories() {
122 return ImmutableSet.copyOf(factories.values());
123 }
124
125
126 @Override
127 @SuppressWarnings("unchecked")
128 public <S, C extends Config<S>> Set<ConfigFactory<S, C>> getConfigFactories(Class<S> subjectClass) {
129 ImmutableSet.Builder<ConfigFactory<S, C>> builder = ImmutableSet.builder();
130 factories.forEach((key, factory) -> {
131 if (factory.subjectFactory().subjectClass().equals(subjectClass)) {
132 builder.add(factory);
133 }
134 });
135 return builder.build();
136 }
137
138 @Override
139 public <S, C extends Config<S>> ConfigFactory<S, C> getConfigFactory(Class<C> configClass) {
140 checkNotNull(configClass, NULL_CCLASS_MSG);
141 return store.getConfigFactory(configClass);
142 }
143
144
145 @Override
146 public Set<Class> getSubjectClasses() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900147 checkPermission(CONFIG_READ);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700148 ImmutableSet.Builder<Class> builder = ImmutableSet.builder();
149 factories.forEach((k, v) -> builder.add(k.subjectClass));
150 return builder.build();
151 }
152
153 @Override
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700154 public SubjectFactory getSubjectFactory(String subjectClassKey) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900155 checkPermission(CONFIG_READ);
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700156 return subjectClasses.get(subjectClassKey);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700157 }
158
159 @Override
160 public SubjectFactory getSubjectFactory(Class subjectClass) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900161 checkPermission(CONFIG_READ);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700162 return subjectClassKeys.get(subjectClass);
163 }
164
165 @Override
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700166 public Class<? extends Config> getConfigClass(String subjectClassKey, String configKey) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900167 checkPermission(CONFIG_READ);
Simon Hunt3da1a182016-02-08 16:42:54 -0800168 checkNotNull(subjectClassKey, NULL_SCKEY_MSG);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800169 checkNotNull(configKey, NULL_CKEY_MSG);
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700170 return configClasses.get(new ConfigIdentifier(subjectClassKey, configKey));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700171 }
172
173 @Override
174 public <S> Set<S> getSubjects(Class<S> subjectClass) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900175 checkPermission(CONFIG_READ);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700176 checkNotNull(subjectClass, NULL_SCLASS_MSG);
177 return store.getSubjects(subjectClass);
178 }
179
180 @Override
181 public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900182 checkPermission(CONFIG_READ);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700183 checkNotNull(subjectClass, NULL_SCLASS_MSG);
184 checkNotNull(configClass, NULL_CCLASS_MSG);
185 return store.getSubjects(subjectClass, configClass);
186 }
187
188 @Override
189 public <S> Set<Config<S>> getConfigs(S subject) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900190 checkPermission(CONFIG_READ);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700191 checkNotNull(subject, NULL_SUBJECT_MSG);
192 Set<Class<? extends Config<S>>> configClasses = store.getConfigClasses(subject);
193 ImmutableSet.Builder<Config<S>> cfg = ImmutableSet.builder();
194 configClasses.forEach(cc -> cfg.add(store.getConfig(subject, cc)));
195 return cfg.build();
196 }
197
198 @Override
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800199 public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900200 checkPermission(CONFIG_READ);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700201 checkNotNull(subject, NULL_SUBJECT_MSG);
202 checkNotNull(configClass, NULL_CCLASS_MSG);
203 return store.getConfig(subject, configClass);
204 }
205
206
207 @Override
208 public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900209 checkPermission(CONFIG_WRITE);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700210 checkNotNull(subject, NULL_SUBJECT_MSG);
211 checkNotNull(configClass, NULL_CCLASS_MSG);
212 return store.createConfig(subject, configClass);
213 }
214
215 @Override
Thomas Vachuska0a400ea2015-09-04 11:25:03 -0700216 public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900217 checkPermission(CONFIG_WRITE);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700218 checkNotNull(subject, NULL_SUBJECT_MSG);
219 checkNotNull(configClass, NULL_CCLASS_MSG);
Simon Hunt3da1a182016-02-08 16:42:54 -0800220 checkNotNull(json, NULL_JSON_MSG);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700221 return store.applyConfig(subject, configClass, json);
222 }
223
224 @Override
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800225 @SuppressWarnings("unchecked")
226 public <S, C extends Config<S>> C applyConfig(String subjectClassKey, S subject,
227 String configKey, JsonNode json) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900228 checkPermission(CONFIG_WRITE);
Simon Hunt3da1a182016-02-08 16:42:54 -0800229 checkNotNull(subjectClassKey, NULL_SCKEY_MSG);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800230 checkNotNull(subject, NULL_SUBJECT_MSG);
231 checkNotNull(configKey, NULL_CKEY_MSG);
Simon Hunt3da1a182016-02-08 16:42:54 -0800232 checkNotNull(json, NULL_JSON_MSG);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800233 Class<? extends Config> configClass = configClasses.get(new ConfigIdentifier(subjectClassKey, configKey));
234 if (configClass != null) {
235 return store.applyConfig(subject, (Class<C>) configClass, json);
236 } else {
Andrea Campanelladcb5e932016-01-11 17:32:23 -0800237 log.info("Configuration \'{}\' queued for subject {}", configKey, subject);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800238 store.queueConfig(subject, configKey, json);
239 return null;
240 }
241 }
242
243 @Override
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700244 public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900245 checkPermission(CONFIG_WRITE);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700246 checkNotNull(subject, NULL_SUBJECT_MSG);
247 checkNotNull(configClass, NULL_CCLASS_MSG);
248 store.clearConfig(subject, configClass);
249 }
250
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800251 @Override
252 public <S> void removeConfig(String subjectClassKey, S subject, String configKey) {
Simon Hunt3da1a182016-02-08 16:42:54 -0800253 checkNotNull(subjectClassKey, NULL_SCKEY_MSG);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800254 checkNotNull(subject, NULL_SUBJECT_MSG);
Simon Hunt3da1a182016-02-08 16:42:54 -0800255 checkNotNull(configKey, NULL_CKEY_MSG);
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800256 Class<? extends Config> configClass = configClasses.get(new ConfigIdentifier(subjectClassKey, configKey));
257 if (configClass != null) {
258 store.clearConfig(subject, configClass);
259 } else {
260 store.clearQueuedConfig(subject, configKey);
261 }
262 }
263
Deepa Vaddireddy0c49b602016-06-02 12:19:07 +0530264 @Override
265 public <S> void removeConfig(S subject) {
266 checkPermission(CONFIG_WRITE);
267 store.clearConfig(subject);
268 }
269
270 @Override
271 public <S> void removeConfig() {
272 checkPermission(CONFIG_WRITE);
273 store.clearConfig();
274 }
275
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700276 // Auxiliary store delegate to receive notification about changes in
277 // the network configuration store state - by the store itself.
278 private class InternalStoreDelegate implements NetworkConfigStoreDelegate {
279 @Override
280 public void notify(NetworkConfigEvent event) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700281 post(event);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700282 }
283 }
284
285
286 // Produces a key for uniquely tracking a config factory.
287 private static ConfigKey key(ConfigFactory factory) {
288 return new ConfigKey(factory.subjectFactory().subjectClass(), factory.configClass());
289 }
290
291 // Auxiliary key to track config factories.
Ray Milkeyae9faf12015-08-03 15:52:26 -0700292 protected static final class ConfigKey {
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700293 final Class subjectClass;
294 final Class configClass;
295
Ray Milkeyae9faf12015-08-03 15:52:26 -0700296 protected ConfigKey(Class subjectClass, Class configClass) {
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700297 this.subjectClass = subjectClass;
298 this.configClass = configClass;
299 }
300
301 @Override
302 public int hashCode() {
303 return Objects.hash(subjectClass, configClass);
304 }
305
306 @Override
307 public boolean equals(Object obj) {
308 if (this == obj) {
309 return true;
310 }
311 if (obj instanceof ConfigKey) {
312 final ConfigKey other = (ConfigKey) obj;
313 return Objects.equals(this.subjectClass, other.subjectClass)
314 && Objects.equals(this.configClass, other.configClass);
315 }
316 return false;
317 }
318 }
319
Jonathan Hart111b42b2015-07-14 13:28:05 -0700320 private static ConfigIdentifier identifier(ConfigFactory factory) {
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700321 return new ConfigIdentifier(factory.subjectFactory().subjectClassKey(), factory.configKey());
Jonathan Hart111b42b2015-07-14 13:28:05 -0700322 }
323
Thomas Vachuska4998caa2015-08-26 13:28:38 -0700324 static final class ConfigIdentifier {
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800325 final String subjectClassKey;
Jonathan Hart111b42b2015-07-14 13:28:05 -0700326 final String configKey;
327
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800328 protected ConfigIdentifier(String subjectClassKey, String configKey) {
329 this.subjectClassKey = subjectClassKey;
Jonathan Hart111b42b2015-07-14 13:28:05 -0700330 this.configKey = configKey;
331 }
332
333 @Override
334 public int hashCode() {
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800335 return Objects.hash(subjectClassKey, configKey);
Jonathan Hart111b42b2015-07-14 13:28:05 -0700336 }
337
338 @Override
339 public boolean equals(Object obj) {
340 if (this == obj) {
341 return true;
342 }
343 if (obj instanceof ConfigIdentifier) {
344 final ConfigIdentifier other = (ConfigIdentifier) obj;
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800345 return Objects.equals(this.subjectClassKey, other.subjectClassKey)
Jonathan Hart111b42b2015-07-14 13:28:05 -0700346 && Objects.equals(this.configKey, other.configKey);
347 }
348 return false;
349 }
350 }
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800351
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700352}