blob: cb8acab21d3b4be0b7a0f7139cf3fcce5d180731 [file] [log] [blame]
Hyunsun Moond0e932a2015-09-15 22:39:16 -07001/*
2 * Copyright 2014-2015 Open Networking Laboratory
3 *
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.cordvtn;
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;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070024import org.onlab.util.KryoNamespace;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070025import org.onosproject.core.CoreService;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070026import org.onosproject.net.Device;
27import org.onosproject.net.DeviceId;
28import org.onosproject.net.Host;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070029import org.onosproject.net.device.DeviceEvent;
30import org.onosproject.net.device.DeviceListener;
31import org.onosproject.net.device.DeviceService;
32import org.onosproject.net.host.HostEvent;
33import org.onosproject.net.host.HostListener;
34import org.onosproject.net.host.HostService;
35import org.onosproject.store.serializers.KryoNamespaces;
36import org.onosproject.store.service.EventuallyConsistentMap;
37import org.onosproject.store.service.LogicalClockService;
38import org.onosproject.store.service.StorageService;
39import org.slf4j.Logger;
40
41import java.util.List;
42import java.util.concurrent.ExecutorService;
43import java.util.concurrent.Executors;
44import java.util.stream.Collectors;
45
46import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moon2b530322015-09-23 13:24:35 -070047import static org.onosproject.cordvtn.OvsdbNode.State;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070048import static org.onosproject.cordvtn.OvsdbNode.State.INIT;
Hyunsun Moon2b530322015-09-23 13:24:35 -070049import static org.onosproject.cordvtn.OvsdbNode.State.DISCONNECT;
50import static org.onosproject.net.Device.Type.SWITCH;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070051import static org.slf4j.LoggerFactory.getLogger;
52
53/**
Hyunsun Moon2b530322015-09-23 13:24:35 -070054 * Provides initial setup or cleanup for provisioning virtual tenant networks
55 * on ovsdb, integration bridge and vm when they are added or deleted.
Hyunsun Moond0e932a2015-09-15 22:39:16 -070056 */
57@Component(immediate = true)
58@Service
59public class CordVtn implements CordVtnService {
60
61 protected final Logger log = getLogger(getClass());
62
Hyunsun Moon2b530322015-09-23 13:24:35 -070063 private static final int NUM_THREADS = 1;
64 private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder()
65 .register(KryoNamespaces.API)
66 .register(OvsdbNode.class);
67
Hyunsun Moond0e932a2015-09-15 22:39:16 -070068 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
69 protected CoreService coreService;
70
71 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
72 protected StorageService storageService;
73
74 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 protected LogicalClockService clockService;
76
77 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond0e932a2015-09-15 22:39:16 -070078 protected DeviceService deviceService;
79
80 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 protected HostService hostService;
82
Hyunsun Moon2b530322015-09-23 13:24:35 -070083 private final ExecutorService eventExecutor = Executors
84 .newFixedThreadPool(NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler"));
Hyunsun Moond0e932a2015-09-15 22:39:16 -070085
Hyunsun Moond0e932a2015-09-15 22:39:16 -070086 private final DeviceListener deviceListener = new InternalDeviceListener();
87 private final HostListener hostListener = new InternalHostListener();
Hyunsun Moon2b530322015-09-23 13:24:35 -070088
89 private final OvsdbHandler ovsdbHandler = new OvsdbHandler();
Hyunsun Moond0e932a2015-09-15 22:39:16 -070090 private final BridgeHandler bridgeHandler = new BridgeHandler();
Hyunsun Moon2b530322015-09-23 13:24:35 -070091 private final VmHandler vmHandler = new VmHandler();
Hyunsun Moond0e932a2015-09-15 22:39:16 -070092
Hyunsun Moond0e932a2015-09-15 22:39:16 -070093 private EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070094
95 @Activate
96 protected void activate() {
Hyunsun Moon2b530322015-09-23 13:24:35 -070097 coreService.registerApplication("org.onosproject.cordvtn");
Hyunsun Moond0e932a2015-09-15 22:39:16 -070098 nodeStore = storageService.<DeviceId, OvsdbNode>eventuallyConsistentMapBuilder()
99 .withName("cordvtn-nodestore")
100 .withSerializer(NODE_SERIALIZER)
101 .withTimestampProvider((k, v) -> clockService.getTimestamp())
102 .build();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700103
104 deviceService.addListener(deviceListener);
105 hostService.addListener(hostListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700106
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700107 log.info("Started");
108 }
109
110 @Deactivate
111 protected void deactivate() {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700112 deviceService.removeListener(deviceListener);
113 hostService.removeListener(hostListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700114
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700115 eventExecutor.shutdown();
116 nodeStore.destroy();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700117
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700118 log.info("Stopped");
119 }
120
121 @Override
Hyunsun Moon2b530322015-09-23 13:24:35 -0700122 public void addNode(OvsdbNode ovsdbNode) {
123 if (nodeStore.containsKey(ovsdbNode.deviceId())) {
124 log.warn("Node {} already exists", ovsdbNode.host());
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700125 return;
126 }
Hyunsun Moon2b530322015-09-23 13:24:35 -0700127 nodeStore.put(ovsdbNode.deviceId(), ovsdbNode);
128 if (ovsdbNode.state() != INIT) {
129 updateNode(ovsdbNode, INIT);
130 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700131 }
132
133 @Override
Hyunsun Moon2b530322015-09-23 13:24:35 -0700134 public void deleteNode(OvsdbNode ovsdbNode) {
135 if (!nodeStore.containsKey(ovsdbNode.deviceId())) {
136 log.warn("Node {} does not exist", ovsdbNode.host());
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700137 return;
138 }
Hyunsun Moon2b530322015-09-23 13:24:35 -0700139 updateNode(ovsdbNode, DISCONNECT);
140 }
141
142 @Override
143 public void updateNode(OvsdbNode ovsdbNode, State state) {
144 if (!nodeStore.containsKey(ovsdbNode.deviceId())) {
145 log.warn("Node {} does not exist", ovsdbNode.host());
146 return;
147 }
148 DefaultOvsdbNode updatedNode = new DefaultOvsdbNode(ovsdbNode.host(),
149 ovsdbNode.ip(),
150 ovsdbNode.port(),
151 state);
152 nodeStore.put(ovsdbNode.deviceId(), updatedNode);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700153 }
154
155 @Override
156 public int getNodeCount() {
157 return nodeStore.size();
158 }
159
160 @Override
Hyunsun Moon2b530322015-09-23 13:24:35 -0700161 public OvsdbNode getNode(DeviceId deviceId) {
162 return nodeStore.get(deviceId);
163 }
164
165 @Override
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700166 public List<OvsdbNode> getNodes() {
167 return nodeStore.values()
168 .stream()
169 .collect(Collectors.toList());
170 }
171
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700172 private class InternalDeviceListener implements DeviceListener {
173
174 @Override
175 public void event(DeviceEvent event) {
176 Device device = event.subject();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700177 ConnectionHandler handler = (device.type() == SWITCH ? bridgeHandler : ovsdbHandler);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700178
179 switch (event.type()) {
Hyunsun Moon2b530322015-09-23 13:24:35 -0700180 case DEVICE_ADDED:
181 eventExecutor.submit(() -> handler.connected(device));
182 break;
183 case DEVICE_AVAILABILITY_CHANGED:
184 eventExecutor.submit(() -> handler.disconnected(device));
185 break;
186 default:
187 break;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700188 }
189 }
190 }
191
192 private class InternalHostListener implements HostListener {
193
194 @Override
195 public void event(HostEvent event) {
196 Host vm = event.subject();
197
198 switch (event.type()) {
199 case HOST_ADDED:
200 eventExecutor.submit(() -> vmHandler.connected(vm));
201 break;
202 case HOST_REMOVED:
203 eventExecutor.submit(() -> vmHandler.disconnected(vm));
204 break;
205 default:
206 break;
207 }
208 }
209 }
210
Hyunsun Moon2b530322015-09-23 13:24:35 -0700211 private class OvsdbHandler implements ConnectionHandler<Device> {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700212
213 @Override
214 public void connected(Device device) {
215 // create bridge and set bridgeId
216 // set node state connected
217 }
218
219 @Override
220 public void disconnected(Device device) {
221 // set node state disconnected if the node exists
222 // which means that the node is not deleted explicitly
223 }
224 }
225
226 private class BridgeHandler implements ConnectionHandler<Device> {
227
228 @Override
229 public void connected(Device device) {
230 // create vxlan port
231 }
232
233 @Override
234 public void disconnected(Device device) {
235
236 }
237 }
238
Hyunsun Moon2b530322015-09-23 13:24:35 -0700239 private class VmHandler implements ConnectionHandler<Host> {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700240
241 @Override
242 public void connected(Host host) {
243 // install flow rules for this vm
244 }
245
246 @Override
247 public void disconnected(Host host) {
248 // uninstall flow rules associated with this vm
249 }
250 }
251}