blob: 944cd029f93f767aa2c05f1755ceb9b6e71e7e55 [file] [log] [blame]
Sithara Punnassery9306e6b2017-02-06 15:38:19 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Sithara Punnassery9306e6b2017-02-06 15:38:19 -08003 *
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 */
16package org.onosproject.config.impl;
17
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
Sithara Punnassery9d464a32017-07-23 16:14:02 -070024import org.onosproject.config.RpcExecutor;
25import org.onosproject.config.RpcMessageId;
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070026import org.onosproject.d.config.DeviceResourceIds;
27import org.onosproject.d.config.ResourceIds;
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -070028import org.onosproject.event.AbstractListenerManager;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080029import org.onosproject.config.DynamicConfigEvent;
30import org.onosproject.config.DynamicConfigListener;
31import org.onosproject.config.DynamicConfigService;
32import org.onosproject.config.DynamicConfigStore;
33import org.onosproject.config.DynamicConfigStoreDelegate;
34import org.onosproject.config.FailedException;
35import org.onosproject.config.Filter;
Gaurav Agrawal02dbee32017-05-11 19:04:52 +053036import org.onosproject.yang.model.RpcInput;
37import org.onosproject.yang.model.RpcOutput;
Sithara Punnassery4b091dc2017-03-02 17:22:40 -080038import org.onosproject.yang.model.DataNode;
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070039import org.onosproject.yang.model.DataNode.Type;
40import org.onosproject.yang.model.InnerNode;
Sithara Punnassery4b091dc2017-03-02 17:22:40 -080041import org.onosproject.yang.model.ResourceId;
Gaurav Agrawal00321332017-12-01 17:06:34 +053042import org.onosproject.yang.model.RpcContext;
Sithara Punnassery9d464a32017-07-23 16:14:02 -070043import org.onosproject.yang.model.RpcRegistry;
44import org.onosproject.yang.model.RpcService;
Gaurav Agrawal00321332017-12-01 17:06:34 +053045import org.onosproject.yang.model.SchemaContextProvider;
46
Sithara Punnassery9d464a32017-07-23 16:14:02 -070047import java.util.HashSet;
48import java.util.Map;
49import java.util.Set;
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -070050import java.util.concurrent.CompletableFuture;
Sithara Punnassery9d464a32017-07-23 16:14:02 -070051import java.util.concurrent.ConcurrentHashMap;
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -070052import org.slf4j.Logger;
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070053
Gaurav Agrawal142ceb02018-02-16 12:19:08 +053054import static com.google.common.base.Preconditions.checkNotNull;
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070055import static org.onosproject.d.config.DeviceResourceIds.DCS_NAMESPACE;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080056import static org.slf4j.LoggerFactory.getLogger;
57
58/**
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -070059 * Implementation of the Dynamic Config Service.
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080060 *
61 */
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080062@Component(immediate = true)
63@Service
64public class DynamicConfigManager
65 extends AbstractListenerManager<DynamicConfigEvent, DynamicConfigListener>
Sithara Punnassery9d464a32017-07-23 16:14:02 -070066 implements DynamicConfigService, RpcRegistry {
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070067
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080068 private final Logger log = getLogger(getClass());
69 private final DynamicConfigStoreDelegate storeDelegate = new InternalStoreDelegate();
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070070
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080071 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080072 protected DynamicConfigStore store;
Gaurav Agrawal00321332017-12-01 17:06:34 +053073
74 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 protected SchemaContextProvider contextProvider;
76
77 // FIXME is it OK this is not using the Store?
Sithara Punnassery9d464a32017-07-23 16:14:02 -070078 private ConcurrentHashMap<String, RpcService> handlerRegistry = new ConcurrentHashMap<>();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080079
80 @Activate
81 public void activate() {
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070082 initStore();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080083 store.setDelegate(storeDelegate);
Sithara Punnassery43833e12017-03-14 16:29:19 -070084 eventDispatcher.addSink(DynamicConfigEvent.class, listenerRegistry);
Sithara Punnassery644a2662017-06-09 02:02:57 -070085 log.info("Started");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080086 }
87
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070088 /**
89 * Ensure built-in tree nodes exists.
90 */
91 private void initStore() {
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070092 store.nodeExist(DeviceResourceIds.DEVICES_ID)
93 .thenAccept(exists -> {
94 if (!exists) {
95 log.info("devices node does not exist!, creating...");
96 store.addNode(ResourceIds.ROOT_ID,
97 InnerNode.builder(DeviceResourceIds.DEVICES_NAME, DCS_NAMESPACE)
98 .type(Type.SINGLE_INSTANCE_NODE).build());
99 }
100 }).join();
101 }
102
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800103 @Deactivate
104 public void deactivate() {
105 store.unsetDelegate(storeDelegate);
Sithara Punnassery43833e12017-03-14 16:29:19 -0700106 eventDispatcher.removeSink(DynamicConfigEvent.class);
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700107 handlerRegistry.clear();
Sithara Punnassery644a2662017-06-09 02:02:57 -0700108 log.info("Stopped");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800109 }
110
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700111 @Override
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -0700112 public void createNode(ResourceId path, DataNode node) {
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700113 store.addNode(path, node).join();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800114 }
115
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700116 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800117 public DataNode readNode(ResourceId path, Filter filter) {
118 return store.readNode(path, filter).join();
119 }
120
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700121 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800122 public void updateNode(ResourceId path, DataNode node) {
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700123 store.updateNode(path, node).join();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800124 }
125
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700126 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800127 public void deleteNode(ResourceId path) {
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800128 store.deleteNodeRecursive(path).join();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800129 }
130
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700131 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800132 public void replaceNode(ResourceId path, DataNode node) {
133 throw new FailedException("Not yet implemented");
134 }
Sithara Punnassery43833e12017-03-14 16:29:19 -0700135
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700136 @Override
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700137 public Boolean nodeExist(ResourceId path) {
138 return store.nodeExist(path).join();
139 }
140
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700141 @Override
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700142 public Set<RpcService> getRpcServices() {
143 Set<RpcService> res = new HashSet();
144 for (Map.Entry<String, RpcService> e : handlerRegistry.entrySet()) {
145 res.add(e.getValue());
146 }
147 return res;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800148 }
149
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700150 @Override
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700151 public RpcService getRpcService(Class<? extends RpcService> intfc) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530152 return handlerRegistry.get(intfc.getName());
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700153 }
154
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700155 @Override
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700156 public void registerRpcService(RpcService handler) {
157 for (Class<?> intfc : handler.getClass().getInterfaces()) {
158 if (RpcService.class.isAssignableFrom(intfc)) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530159 handlerRegistry.put(intfc.getName(), handler);
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700160 }
Sithara Punnassery644a2662017-06-09 02:02:57 -0700161 }
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700162 }
163
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700164 @Override
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700165 public void unregisterRpcService(RpcService handler) {
166 for (Class<?> intfc : handler.getClass().getInterfaces()) {
167 if (RpcService.class.isAssignableFrom(intfc)) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530168 String key = intfc.getName();
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700169 if (handlerRegistry.get(key) == null) {
170 throw new FailedException("No registered handler found, cannot unregister");
171 }
172 handlerRegistry.remove(key);
173 }
174 }
175 }
176
177 private int getSvcId(RpcService handler, String srvc) {
178 Class<?>[] intfcs = handler.getClass().getInterfaces();
179 for (int i = 0; i < intfcs.length; i++) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530180 if (intfcs[i].getName().compareTo(srvc) == 0) {
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700181 return i;
182 }
183 }
184 throw new FailedException("No handler found, cannot invoke");
185 }
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -0700186
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700187 @Override
Gaurav Agrawal142ceb02018-02-16 12:19:08 +0530188 public CompletableFuture<RpcOutput> invokeRpc(RpcInput input) {
189 checkNotNull(input);
190 checkNotNull(input.id());
191 RpcContext context = contextProvider.getRpcContext(input.id());
192 String srvcIntf = context.serviceIntf().getName();
193 RpcService handler = handlerRegistry.get(srvcIntf);
194 if (handler == null) {
195 throw new FailedException("No registered handler found, cannot invoke");
196 }
197 return CompletableFuture.supplyAsync(
198 new RpcExecutor(handler, getSvcId(handler, srvcIntf),
199 context.rpcName(), RpcMessageId.generate(), input));
200 }
201
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800202 /**
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800203 * Auxiliary store delegate to receive notification about changes in the store.
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800204 */
205 private class InternalStoreDelegate implements DynamicConfigStoreDelegate {
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700206 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800207 public void notify(DynamicConfigEvent event) {
Sithara Punnassery43833e12017-03-14 16:29:19 -0700208 post(event);
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800209 }
210 }
211}