blob: d976a40c9f9aa8814dac85438fb735955441ecba [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
54import static org.onosproject.d.config.DeviceResourceIds.DCS_NAMESPACE;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080055import static org.slf4j.LoggerFactory.getLogger;
56
57/**
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -070058 * Implementation of the Dynamic Config Service.
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080059 *
60 */
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080061@Component(immediate = true)
62@Service
63public class DynamicConfigManager
64 extends AbstractListenerManager<DynamicConfigEvent, DynamicConfigListener>
Sithara Punnassery9d464a32017-07-23 16:14:02 -070065 implements DynamicConfigService, RpcRegistry {
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070066
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080067 private final Logger log = getLogger(getClass());
68 private final DynamicConfigStoreDelegate storeDelegate = new InternalStoreDelegate();
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070069
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080070 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080071 protected DynamicConfigStore store;
Gaurav Agrawal00321332017-12-01 17:06:34 +053072
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected SchemaContextProvider contextProvider;
75
76 // FIXME is it OK this is not using the Store?
Sithara Punnassery9d464a32017-07-23 16:14:02 -070077 private ConcurrentHashMap<String, RpcService> handlerRegistry = new ConcurrentHashMap<>();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080078
79 @Activate
80 public void activate() {
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070081 initStore();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080082 store.setDelegate(storeDelegate);
Sithara Punnassery43833e12017-03-14 16:29:19 -070083 eventDispatcher.addSink(DynamicConfigEvent.class, listenerRegistry);
Sithara Punnassery644a2662017-06-09 02:02:57 -070084 log.info("Started");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080085 }
86
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070087 /**
88 * Ensure built-in tree nodes exists.
89 */
90 private void initStore() {
91 store.nodeExist(ResourceIds.ROOT_ID)
92 .thenAccept(exists -> {
93 if (!exists) {
94 log.info("Root node does not exist!, creating...");
95 store.addNode(null,
96 InnerNode.builder(DeviceResourceIds.ROOT_NAME, DCS_NAMESPACE)
97 .type(Type.SINGLE_INSTANCE_NODE).build());
98 }
99 }).join();
100
101 store.nodeExist(DeviceResourceIds.DEVICES_ID)
102 .thenAccept(exists -> {
103 if (!exists) {
104 log.info("devices node does not exist!, creating...");
105 store.addNode(ResourceIds.ROOT_ID,
106 InnerNode.builder(DeviceResourceIds.DEVICES_NAME, DCS_NAMESPACE)
107 .type(Type.SINGLE_INSTANCE_NODE).build());
108 }
109 }).join();
110 }
111
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800112 @Deactivate
113 public void deactivate() {
114 store.unsetDelegate(storeDelegate);
Sithara Punnassery43833e12017-03-14 16:29:19 -0700115 eventDispatcher.removeSink(DynamicConfigEvent.class);
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700116 handlerRegistry.clear();
Sithara Punnassery644a2662017-06-09 02:02:57 -0700117 log.info("Stopped");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800118 }
119
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700120 @Override
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -0700121 public void createNode(ResourceId path, DataNode node) {
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700122 store.addNode(path, node).join();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800123 }
124
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700125 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800126 public DataNode readNode(ResourceId path, Filter filter) {
127 return store.readNode(path, filter).join();
128 }
129
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700130 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800131 public void updateNode(ResourceId path, DataNode node) {
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700132 store.updateNode(path, node).join();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800133 }
134
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700135 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800136 public void deleteNode(ResourceId path) {
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800137 store.deleteNodeRecursive(path).join();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800138 }
139
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700140 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800141 public void replaceNode(ResourceId path, DataNode node) {
142 throw new FailedException("Not yet implemented");
143 }
Sithara Punnassery43833e12017-03-14 16:29:19 -0700144
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700145 @Override
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700146 public Boolean nodeExist(ResourceId path) {
147 return store.nodeExist(path).join();
148 }
149
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700150 @Override
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700151 public Set<RpcService> getRpcServices() {
152 Set<RpcService> res = new HashSet();
153 for (Map.Entry<String, RpcService> e : handlerRegistry.entrySet()) {
154 res.add(e.getValue());
155 }
156 return res;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800157 }
158
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700159 @Override
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700160 public RpcService getRpcService(Class<? extends RpcService> intfc) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530161 return handlerRegistry.get(intfc.getName());
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 registerRpcService(RpcService handler) {
166 for (Class<?> intfc : handler.getClass().getInterfaces()) {
167 if (RpcService.class.isAssignableFrom(intfc)) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530168 handlerRegistry.put(intfc.getName(), handler);
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700169 }
Sithara Punnassery644a2662017-06-09 02:02:57 -0700170 }
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700171 }
172
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700173 @Override
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700174 public void unregisterRpcService(RpcService handler) {
175 for (Class<?> intfc : handler.getClass().getInterfaces()) {
176 if (RpcService.class.isAssignableFrom(intfc)) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530177 String key = intfc.getName();
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700178 if (handlerRegistry.get(key) == null) {
179 throw new FailedException("No registered handler found, cannot unregister");
180 }
181 handlerRegistry.remove(key);
182 }
183 }
184 }
185
186 private int getSvcId(RpcService handler, String srvc) {
187 Class<?>[] intfcs = handler.getClass().getInterfaces();
188 for (int i = 0; i < intfcs.length; i++) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530189 if (intfcs[i].getName().compareTo(srvc) == 0) {
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700190 return i;
191 }
192 }
193 throw new FailedException("No handler found, cannot invoke");
194 }
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -0700195
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700196 @Override
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -0700197 public CompletableFuture<RpcOutput> invokeRpc(ResourceId id, RpcInput input) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530198 RpcContext context = contextProvider.getRpcContext(id);
199 String srvcIntf = context.serviceIntf().getName();
200 RpcService handler = handlerRegistry.get(srvcIntf);
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700201 if (handler == null) {
202 throw new FailedException("No registered handler found, cannot invoke");
203 }
204 return CompletableFuture.supplyAsync(
Gaurav Agrawal00321332017-12-01 17:06:34 +0530205 new RpcExecutor(handler, getSvcId(handler, srvcIntf),
206 context.rpcName(), RpcMessageId.generate(), input));
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800207 }
208
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800209 /**
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800210 * Auxiliary store delegate to receive notification about changes in the store.
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800211 */
212 private class InternalStoreDelegate implements DynamicConfigStoreDelegate {
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700213 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800214 public void notify(DynamicConfigEvent event) {
Sithara Punnassery43833e12017-03-14 16:29:19 -0700215 post(event);
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800216 }
217 }
218}