blob: 074f8d42399366ac9b0c8cce106cd7d0b5bf96b5 [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
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080018import org.onosproject.config.DynamicConfigEvent;
19import org.onosproject.config.DynamicConfigListener;
20import org.onosproject.config.DynamicConfigService;
21import org.onosproject.config.DynamicConfigStore;
22import org.onosproject.config.DynamicConfigStoreDelegate;
23import org.onosproject.config.FailedException;
24import org.onosproject.config.Filter;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070025import org.onosproject.config.RpcExecutor;
26import org.onosproject.config.RpcMessageId;
27import org.onosproject.d.config.DeviceResourceIds;
28import org.onosproject.d.config.ResourceIds;
29import org.onosproject.event.AbstractListenerManager;
Sithara Punnassery4b091dc2017-03-02 17:22:40 -080030import org.onosproject.yang.model.DataNode;
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070031import org.onosproject.yang.model.DataNode.Type;
32import org.onosproject.yang.model.InnerNode;
Sithara Punnassery4b091dc2017-03-02 17:22:40 -080033import org.onosproject.yang.model.ResourceId;
Gaurav Agrawal00321332017-12-01 17:06:34 +053034import org.onosproject.yang.model.RpcContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070035import org.onosproject.yang.model.RpcInput;
36import org.onosproject.yang.model.RpcOutput;
Sithara Punnassery9d464a32017-07-23 16:14:02 -070037import org.onosproject.yang.model.RpcRegistry;
38import org.onosproject.yang.model.RpcService;
Gaurav Agrawal00321332017-12-01 17:06:34 +053039import org.onosproject.yang.model.SchemaContextProvider;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070040import org.osgi.service.component.annotations.Activate;
41import org.osgi.service.component.annotations.Component;
42import org.osgi.service.component.annotations.Deactivate;
43import org.osgi.service.component.annotations.Reference;
44import org.osgi.service.component.annotations.ReferenceCardinality;
45import org.slf4j.Logger;
Gaurav Agrawal00321332017-12-01 17:06:34 +053046
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;
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070052
Gaurav Agrawal142ceb02018-02-16 12:19:08 +053053import static com.google.common.base.Preconditions.checkNotNull;
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070054import 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 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070061@Component(immediate = true, service = { DynamicConfigService.class, RpcRegistry.class })
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080062public class DynamicConfigManager
63 extends AbstractListenerManager<DynamicConfigEvent, DynamicConfigListener>
Sithara Punnassery9d464a32017-07-23 16:14:02 -070064 implements DynamicConfigService, RpcRegistry {
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070065
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080066 private final Logger log = getLogger(getClass());
67 private final DynamicConfigStoreDelegate storeDelegate = new InternalStoreDelegate();
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070068
Ray Milkeyd84f89b2018-08-17 14:54:17 -070069 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080070 protected DynamicConfigStore store;
Gaurav Agrawal00321332017-12-01 17:06:34 +053071
Ray Milkeyd84f89b2018-08-17 14:54:17 -070072 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Gaurav Agrawal00321332017-12-01 17:06:34 +053073 protected SchemaContextProvider contextProvider;
74
75 // FIXME is it OK this is not using the Store?
Sithara Punnassery9d464a32017-07-23 16:14:02 -070076 private ConcurrentHashMap<String, RpcService> handlerRegistry = new ConcurrentHashMap<>();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080077
78 @Activate
79 public void activate() {
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070080 initStore();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080081 store.setDelegate(storeDelegate);
Sithara Punnassery43833e12017-03-14 16:29:19 -070082 eventDispatcher.addSink(DynamicConfigEvent.class, listenerRegistry);
Sithara Punnassery644a2662017-06-09 02:02:57 -070083 log.info("Started");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -080084 }
85
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070086 /**
87 * Ensure built-in tree nodes exists.
88 */
89 private void initStore() {
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -070090 store.nodeExist(DeviceResourceIds.DEVICES_ID)
91 .thenAccept(exists -> {
92 if (!exists) {
93 log.info("devices node does not exist!, creating...");
94 store.addNode(ResourceIds.ROOT_ID,
95 InnerNode.builder(DeviceResourceIds.DEVICES_NAME, DCS_NAMESPACE)
96 .type(Type.SINGLE_INSTANCE_NODE).build());
97 }
98 }).join();
99 }
100
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800101 @Deactivate
102 public void deactivate() {
103 store.unsetDelegate(storeDelegate);
Sithara Punnassery43833e12017-03-14 16:29:19 -0700104 eventDispatcher.removeSink(DynamicConfigEvent.class);
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700105 handlerRegistry.clear();
Sithara Punnassery644a2662017-06-09 02:02:57 -0700106 log.info("Stopped");
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800107 }
108
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700109 @Override
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -0700110 public void createNode(ResourceId path, DataNode node) {
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700111 store.addNode(path, node).join();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800112 }
113
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700114 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800115 public DataNode readNode(ResourceId path, Filter filter) {
116 return store.readNode(path, filter).join();
117 }
118
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700119 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800120 public void updateNode(ResourceId path, DataNode node) {
Sithara Punnassery0da1a9c2017-05-17 16:16:22 -0700121 store.updateNode(path, node).join();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800122 }
123
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700124 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800125 public void deleteNode(ResourceId path) {
Sithara Punnassery4b091dc2017-03-02 17:22:40 -0800126 store.deleteNodeRecursive(path).join();
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800127 }
128
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700129 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800130 public void replaceNode(ResourceId path, DataNode node) {
131 throw new FailedException("Not yet implemented");
132 }
Sithara Punnassery43833e12017-03-14 16:29:19 -0700133
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700134 @Override
Sithara Punnassery18ffcc72017-05-18 14:24:30 -0700135 public Boolean nodeExist(ResourceId path) {
136 return store.nodeExist(path).join();
137 }
138
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700139 @Override
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700140 public Set<RpcService> getRpcServices() {
141 Set<RpcService> res = new HashSet();
142 for (Map.Entry<String, RpcService> e : handlerRegistry.entrySet()) {
143 res.add(e.getValue());
144 }
145 return res;
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800146 }
147
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700148 @Override
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700149 public RpcService getRpcService(Class<? extends RpcService> intfc) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530150 return handlerRegistry.get(intfc.getName());
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700151 }
152
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700153 @Override
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700154 public void registerRpcService(RpcService handler) {
155 for (Class<?> intfc : handler.getClass().getInterfaces()) {
156 if (RpcService.class.isAssignableFrom(intfc)) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530157 handlerRegistry.put(intfc.getName(), handler);
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700158 }
Sithara Punnassery644a2662017-06-09 02:02:57 -0700159 }
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700160 }
161
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700162 @Override
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700163 public void unregisterRpcService(RpcService handler) {
164 for (Class<?> intfc : handler.getClass().getInterfaces()) {
165 if (RpcService.class.isAssignableFrom(intfc)) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530166 String key = intfc.getName();
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700167 if (handlerRegistry.get(key) == null) {
168 throw new FailedException("No registered handler found, cannot unregister");
169 }
170 handlerRegistry.remove(key);
171 }
172 }
173 }
174
175 private int getSvcId(RpcService handler, String srvc) {
176 Class<?>[] intfcs = handler.getClass().getInterfaces();
177 for (int i = 0; i < intfcs.length; i++) {
Gaurav Agrawal00321332017-12-01 17:06:34 +0530178 if (intfcs[i].getName().compareTo(srvc) == 0) {
Sithara Punnassery9d464a32017-07-23 16:14:02 -0700179 return i;
180 }
181 }
182 throw new FailedException("No handler found, cannot invoke");
183 }
Sithara Punnassery7b0c15e2017-07-07 15:08:19 -0700184
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700185 @Override
Gaurav Agrawal142ceb02018-02-16 12:19:08 +0530186 public CompletableFuture<RpcOutput> invokeRpc(RpcInput input) {
187 checkNotNull(input);
188 checkNotNull(input.id());
189 RpcContext context = contextProvider.getRpcContext(input.id());
190 String srvcIntf = context.serviceIntf().getName();
191 RpcService handler = handlerRegistry.get(srvcIntf);
192 if (handler == null) {
193 throw new FailedException("No registered handler found, cannot invoke");
194 }
195 return CompletableFuture.supplyAsync(
196 new RpcExecutor(handler, getSvcId(handler, srvcIntf),
197 context.rpcName(), RpcMessageId.generate(), input));
198 }
199
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800200 /**
Sithara Punnassery44e2a702017-03-06 15:38:10 -0800201 * Auxiliary store delegate to receive notification about changes in the store.
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800202 */
203 private class InternalStoreDelegate implements DynamicConfigStoreDelegate {
Yuta HIGUCHI289f45c2017-11-01 17:49:45 -0700204 @Override
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800205 public void notify(DynamicConfigEvent event) {
Sithara Punnassery43833e12017-03-14 16:29:19 -0700206 post(event);
Sithara Punnassery9306e6b2017-02-06 15:38:19 -0800207 }
208 }
209}