blob: 15e8183ba147e7471b5ea3dca161166f7c0fbe5d [file] [log] [blame]
Hyunsun Mooncb799442016-01-15 20:03:18 -08001/*
Brian O'Connor80dff972017-08-03 22:46:30 -07002 * Copyright 2016-present Open Networking Foundation
Hyunsun Mooncb799442016-01-15 20:03:18 -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 */
alshabibb4d31712016-06-01 18:51:03 -070016package org.opencord.cordvtn.impl;
Hyunsun Mooncb799442016-01-15 20:03:18 -080017
Hyunsun Moon81a13562016-08-04 13:48:08 -070018import com.google.common.base.Strings;
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090019import com.google.common.collect.ImmutableSet;
Hyunsun Mooncb799442016-01-15 20:03:18 -080020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.apache.felix.scr.annotations.Service;
Hyunsun Mooncb799442016-01-15 20:03:18 -080026import org.onosproject.cluster.ClusterService;
Hyunsun Moon7004fcf2016-03-08 04:36:02 -080027import org.onosproject.cluster.LeadershipService;
28import org.onosproject.cluster.NodeId;
Hyunsun Mooncb799442016-01-15 20:03:18 -080029import org.onosproject.core.ApplicationId;
30import org.onosproject.core.CoreService;
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090031import org.onosproject.event.ListenerRegistry;
Hyunsun Mooncb799442016-01-15 20:03:18 -080032import org.onosproject.net.DeviceId;
Hyunsun Mooncb799442016-01-15 20:03:18 -080033import org.onosproject.net.config.NetworkConfigEvent;
34import org.onosproject.net.config.NetworkConfigListener;
Hyunsun Mooncb799442016-01-15 20:03:18 -080035import org.onosproject.net.config.NetworkConfigService;
Hyunsun Moon187bf532017-01-19 10:57:40 +090036import org.opencord.cordvtn.api.CordVtnConfig;
Hyunsun Moon0984cbd2016-12-01 17:34:11 -080037import org.opencord.cordvtn.api.node.CordVtnNode;
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090038import org.opencord.cordvtn.api.node.CordVtnNodeAdminService;
39import org.opencord.cordvtn.api.node.CordVtnNodeEvent;
40import org.opencord.cordvtn.api.node.CordVtnNodeListener;
41import org.opencord.cordvtn.api.node.CordVtnNodeService;
42import org.opencord.cordvtn.api.node.CordVtnNodeStore;
43import org.opencord.cordvtn.api.node.CordVtnNodeStoreDelegate;
Hyunsun Mooncb799442016-01-15 20:03:18 -080044import org.slf4j.Logger;
45
Hyunsun Moon7004fcf2016-03-08 04:36:02 -080046import java.util.Objects;
Hyunsun Moon126171d2016-02-09 01:55:48 -080047import java.util.Set;
Hyunsun Mooncb799442016-01-15 20:03:18 -080048import java.util.concurrent.ExecutorService;
Hyunsun Moon58ddbdc2016-03-07 16:37:17 -080049import java.util.stream.Collectors;
Hyunsun Mooncb799442016-01-15 20:03:18 -080050
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090051import static com.google.common.base.Preconditions.checkArgument;
Hyunsun Mooncb799442016-01-15 20:03:18 -080052import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090053import static java.lang.String.format;
Hyunsun Moon537018f2016-07-27 18:51:00 -070054import static java.util.concurrent.Executors.newSingleThreadExecutor;
Hyunsun Mooncb799442016-01-15 20:03:18 -080055import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moon5401aaa2016-06-12 17:40:34 -070056import static org.opencord.cordvtn.api.Constants.*;
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090057import static org.opencord.cordvtn.api.node.CordVtnNodeState.*;
Hyunsun Mooncb799442016-01-15 20:03:18 -080058import static org.slf4j.LoggerFactory.getLogger;
59
60/**
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090061 * Manages the inventory of the cordvtn nodes provided via network configuration.
Hyunsun Mooncb799442016-01-15 20:03:18 -080062 */
63@Component(immediate = true)
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090064@Service
65public class CordVtnNodeManager extends ListenerRegistry<CordVtnNodeEvent, CordVtnNodeListener>
66 implements CordVtnNodeAdminService, CordVtnNodeService {
Hyunsun Mooncb799442016-01-15 20:03:18 -080067
68 protected final Logger log = getLogger(getClass());
69
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090070 private static final String MSG_NODE = "Node %s %s";
71 private static final String MSG_CREATED = "created";
72 private static final String MSG_UPDATED = "updated";
73 private static final String MSG_REMOVED = "removed";
Hyunsun Mooncb799442016-01-15 20:03:18 -080074
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090075 private static final String ERR_NULL_NODE = "CordVtn node cannot be null";
76 private static final String ERR_NULL_HOSTNAME = "CordVtn node hostname cannot be null";
77 private static final String ERR_NULL_DEVICE_ID = "Device ID cannot be null";
78 private static final String ERR_NOT_FOUND = "does not exist";
Hyunsun Mooncb799442016-01-15 20:03:18 -080079
80 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 protected CoreService coreService;
82
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Mooncb799442016-01-15 20:03:18 -080084 protected NetworkConfigService configService;
85
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090087 protected LeadershipService leadershipService;
Hyunsun Mooncb799442016-01-15 20:03:18 -080088
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected ClusterService clusterService;
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090093 protected CordVtnNodeStore nodeStore;
Hyunsun Mooncb799442016-01-15 20:03:18 -080094
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090095 private final ExecutorService eventExecutor = newSingleThreadExecutor(
96 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
Hyunsun Mooncb799442016-01-15 20:03:18 -080097
98 private final NetworkConfigListener configListener = new InternalConfigListener();
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090099 private final CordVtnNodeStoreDelegate delegate = new InternalCordVtnNodeStoreDelegate();
Hyunsun Mooncb799442016-01-15 20:03:18 -0800100
Hyunsun Mooncb799442016-01-15 20:03:18 -0800101 private ApplicationId appId;
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800102 private NodeId localNodeId;
Hyunsun Mooncb799442016-01-15 20:03:18 -0800103
Hyunsun Mooncb799442016-01-15 20:03:18 -0800104 @Activate
Hyunsun Moon479b7752016-05-06 20:13:28 -0700105 protected void activate() {
Hyunsun Mooneaf75e62016-09-27 16:40:23 -0700106 appId = coreService.registerApplication(CORDVTN_APP_ID);
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800107 leadershipService.runForLeadership(appId.name());
Hyunsun Moon3fc0cbc2016-11-22 18:29:12 -0800108 localNodeId = clusterService.getLocalNode().id();
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800109
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900110 nodeStore.setDelegate(delegate);
Hyunsun Mooncb799442016-01-15 20:03:18 -0800111 configService.addListener(configListener);
Hyunsun Moon479b7752016-05-06 20:13:28 -0700112
Hyunsun Moon96207312017-03-20 16:17:07 +0900113 readNodes();
Hyunsun Moon479b7752016-05-06 20:13:28 -0700114 log.info("Started");
Hyunsun Mooncb799442016-01-15 20:03:18 -0800115 }
116
117 @Deactivate
118 protected void deactivate() {
Hyunsun Mooncb799442016-01-15 20:03:18 -0800119 configService.removeListener(configListener);
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900120 nodeStore.unsetDelegate(delegate);
Hyunsun Moonff55e812016-03-10 12:40:16 -0800121
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800122 leadershipService.withdraw(appId.name());
Hyunsun Moonff55e812016-03-10 12:40:16 -0800123 eventExecutor.shutdown();
Hyunsun Moon479b7752016-05-06 20:13:28 -0700124
125 log.info("Stopped");
Hyunsun Mooncb799442016-01-15 20:03:18 -0800126 }
127
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900128 @Override
129 public void createNode(CordVtnNode node) {
130 checkNotNull(node, ERR_NULL_NODE);
131 nodeStore.createNode(node);
132 log.info(format(MSG_NODE, node.hostname(), MSG_CREATED));
Hyunsun Mooncb799442016-01-15 20:03:18 -0800133 }
134
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900135 @Override
136 public void updateNode(CordVtnNode node) {
137 checkNotNull(node, ERR_NULL_NODE);
138 nodeStore.updateNode(node);
139 log.debug(format(MSG_NODE, node.hostname(), MSG_UPDATED));
140 }
141
142 @Override
143 public CordVtnNode removeNode(String hostname) {
144 checkArgument(!Strings.isNullOrEmpty(hostname), ERR_NULL_HOSTNAME);
145 CordVtnNode removed = nodeStore.removeNode(hostname);
146 if (removed == null) {
147 log.warn(format(MSG_NODE, hostname, ERR_NOT_FOUND));
148 return null;
Hyunsun Mooncb799442016-01-15 20:03:18 -0800149 }
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900150 log.info(format(MSG_NODE, hostname, MSG_REMOVED));
151 return removed;
Hyunsun Mooncb799442016-01-15 20:03:18 -0800152 }
153
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900154 @Override
155 public Set<CordVtnNode> nodes() {
156 return nodeStore.nodes();
Hyunsun Mooncb799442016-01-15 20:03:18 -0800157 }
158
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900159 @Override
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700160 public Set<CordVtnNode> completeNodes() {
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700161 // the state saved in nodeStore can be wrong if IP address settings are changed
162 // after the node init has been completed since there's no way to detect it
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900163 Set<CordVtnNode> nodes = nodes().stream()
164 .filter(node -> node.state() == COMPLETE)
165 .collect(Collectors.toSet());
166 return ImmutableSet.copyOf(nodes);
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700167 }
168
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900169 @Override
170 public CordVtnNode node(String hostname) {
171 checkArgument(!Strings.isNullOrEmpty(hostname), ERR_NULL_HOSTNAME);
172 return nodeStore.node(hostname);
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700173 }
174
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900175 @Override
176 public CordVtnNode node(DeviceId deviceId) {
177 checkNotNull(deviceId, ERR_NULL_DEVICE_ID);
178 return nodes().stream()
179 .filter(node -> node.integrationBridgeId().equals(deviceId) ||
180 node.ovsdbId().equals(deviceId))
181 .findAny().orElse(null);
Hyunsun Mooncb799442016-01-15 20:03:18 -0800182 }
183
184 /**
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800185 * Reads cordvtn nodes from config file.
Hyunsun Mooncb799442016-01-15 20:03:18 -0800186 */
Hyunsun Moon3fc0cbc2016-11-22 18:29:12 -0800187 private void readNodes() {
188 NodeId leaderNodeId = leadershipService.getLeader(appId.name());
189 if (!Objects.equals(localNodeId, leaderNodeId)) {
190 // do not allow to proceed without leadership
191 return;
192 }
193
Hyunsun Moon0984cbd2016-12-01 17:34:11 -0800194 CordVtnConfig config = configService.getConfig(appId, CordVtnConfig.class);
Hyunsun Mooncb799442016-01-15 20:03:18 -0800195 if (config == null) {
Hyunsun Mooncb799442016-01-15 20:03:18 -0800196 return;
197 }
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900198 config.cordVtnNodes().forEach(node -> {
199 log.info("Read node from network config: {}", node.hostname());
200 CordVtnNode existing = node(node.hostname());
201 if (existing == null) {
202 createNode(node);
203 } else if (!existing.equals(node)) {
204 // FIXME maybe we need to re-check node states
205 updateNode(node);
206 }
Hyunsun Moon3fc0cbc2016-11-22 18:29:12 -0800207 });
208 }
209
Hyunsun Mooncb799442016-01-15 20:03:18 -0800210 private class InternalConfigListener implements NetworkConfigListener {
211
212 @Override
213 public void event(NetworkConfigEvent event) {
214 if (!event.configClass().equals(CordVtnConfig.class)) {
215 return;
216 }
217
218 switch (event.type()) {
219 case CONFIG_ADDED:
Hyunsun Mooncb799442016-01-15 20:03:18 -0800220 case CONFIG_UPDATED:
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900221 eventExecutor.execute(CordVtnNodeManager.this::readNodes);
Hyunsun Mooncb799442016-01-15 20:03:18 -0800222 break;
223 default:
224 break;
225 }
226 }
227 }
Hyunsun Moonff55e812016-03-10 12:40:16 -0800228
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900229 private class InternalCordVtnNodeStoreDelegate implements CordVtnNodeStoreDelegate {
Hyunsun Moonff55e812016-03-10 12:40:16 -0800230
231 @Override
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900232 public void notify(CordVtnNodeEvent event) {
233 if (event != null) {
234 process(event);
Hyunsun Moonff55e812016-03-10 12:40:16 -0800235 }
236 }
237 }
Hyunsun Mooncb799442016-01-15 20:03:18 -0800238}