blob: e3e52e93e63b14da18184223f6e64d8b1187279e [file] [log] [blame]
jiangrui9c6db862015-11-27 14:50:46 +08001/*
2 * Copyright 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.vtnrsc.floatingip.impl;
17
18import static com.google.common.base.Preconditions.checkNotNull;
19import static org.slf4j.LoggerFactory.getLogger;
20
21import java.util.Collection;
22import java.util.Collections;
23import java.util.Set;
24
25import org.apache.felix.scr.annotations.Activate;
26import org.apache.felix.scr.annotations.Component;
27import org.apache.felix.scr.annotations.Deactivate;
28import org.apache.felix.scr.annotations.Reference;
29import org.apache.felix.scr.annotations.ReferenceCardinality;
30import org.apache.felix.scr.annotations.Service;
31import org.onlab.packet.IpAddress;
32import org.onlab.util.KryoNamespace;
33import org.onosproject.core.ApplicationId;
34import org.onosproject.core.CoreService;
35import org.onosproject.store.serializers.KryoNamespaces;
36import org.onosproject.store.service.EventuallyConsistentMap;
37import org.onosproject.store.service.EventuallyConsistentMapEvent;
38import org.onosproject.store.service.EventuallyConsistentMapListener;
39import org.onosproject.store.service.StorageService;
40import org.onosproject.store.service.WallClockTimestamp;
41import org.onosproject.vtnrsc.DefaultFloatingIp;
42import org.onosproject.vtnrsc.FloatingIp;
43import org.onosproject.vtnrsc.FloatingIpId;
44import org.onosproject.vtnrsc.TenantId;
45import org.onosproject.vtnrsc.TenantNetworkId;
46import org.onosproject.vtnrsc.VirtualPortId;
47import org.onosproject.vtnrsc.RouterId;
48import org.onosproject.vtnrsc.floatingip.FloatingIpEvent;
49import org.onosproject.vtnrsc.floatingip.FloatingIpListener;
50import org.onosproject.vtnrsc.floatingip.FloatingIpService;
51import org.onosproject.vtnrsc.router.RouterService;
52import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
53import org.onosproject.vtnrsc.virtualport.VirtualPortService;
54import org.slf4j.Logger;
55
56import com.google.common.collect.Sets;
57
58/**
59 * Provides implementation of the FloatingIp service.
60 */
61@Component(immediate = true)
62@Service
63public class FloatingIpManager implements FloatingIpService {
64 private static final String FLOATINGIP_ID_NOT_NULL = "Floatingip ID cannot be null";
65 private static final String FLOATINGIP_NOT_NULL = "Floatingip cannot be null";
lishuai762df812016-01-08 11:51:15 +080066 private static final String FLOATINGIPSTORE = "vtn-floatingip-store";
67 private static final String FLOATINGIPBINDSTORE = "vtn-floatingip-bind-store";
jiangrui9c6db862015-11-27 14:50:46 +080068 private static final String VTNRSC_APP = "org.onosproject.vtnrsc";
69 private static final String LISTENER_NOT_NULL = "Listener cannot be null";
70 private static final String EVENT_NOT_NULL = "event cannot be null";
71
72 private final Logger log = getLogger(getClass());
73 private final Set<FloatingIpListener> listeners = Sets
74 .newCopyOnWriteArraySet();
75 private EventuallyConsistentMapListener<FloatingIpId, FloatingIp> floatingIpListener =
76 new InnerFloatingIpStoreListener();
77 protected EventuallyConsistentMap<FloatingIpId, FloatingIp> floatingIpStore;
lishuai762df812016-01-08 11:51:15 +080078 protected EventuallyConsistentMap<FloatingIpId, FloatingIp> floatingIpBindStore;
jiangrui9c6db862015-11-27 14:50:46 +080079 protected ApplicationId appId;
80
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected StorageService storageService;
83
84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected CoreService coreService;
86
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 protected TenantNetworkService tenantNetworkService;
89
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 protected VirtualPortService virtualPortService;
92
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected RouterService routerService;
95
96 @Activate
97 public void activate() {
98 appId = coreService.registerApplication(VTNRSC_APP);
99 KryoNamespace.Builder serializer = KryoNamespace
100 .newBuilder()
101 .register(KryoNamespaces.API)
102 .register(FloatingIp.class, FloatingIpId.class,
103 TenantNetworkId.class, TenantId.class,
104 FloatingIp.Status.class, RouterId.class,
105 VirtualPortId.class, DefaultFloatingIp.class);
106 floatingIpStore = storageService
107 .<FloatingIpId, FloatingIp>eventuallyConsistentMapBuilder()
lishuai762df812016-01-08 11:51:15 +0800108 .withName(FLOATINGIPSTORE).withSerializer(serializer)
109 .withTimestampProvider((k, v) -> new WallClockTimestamp())
110 .build();
111 floatingIpBindStore = storageService
112 .<FloatingIpId, FloatingIp>eventuallyConsistentMapBuilder()
113 .withName(FLOATINGIPBINDSTORE).withSerializer(serializer)
jiangrui9c6db862015-11-27 14:50:46 +0800114 .withTimestampProvider((k, v) -> new WallClockTimestamp())
115 .build();
116 floatingIpStore.addListener(floatingIpListener);
117 log.info("Started");
118 }
119
120 @Deactivate
121 public void deactivate() {
122 floatingIpStore.removeListener(floatingIpListener);
123 floatingIpStore.destroy();
lishuai762df812016-01-08 11:51:15 +0800124 floatingIpBindStore.destroy();
jiangrui9c6db862015-11-27 14:50:46 +0800125 listeners.clear();
126 log.info("Stopped");
127 }
128
129 @Override
130 public Collection<FloatingIp> getFloatingIps() {
131 return Collections.unmodifiableCollection(floatingIpStore.values());
132 }
133
134 @Override
135 public FloatingIp getFloatingIp(FloatingIpId floatingIpId) {
136 checkNotNull(floatingIpId, FLOATINGIP_ID_NOT_NULL);
137 return floatingIpStore.get(floatingIpId);
138 }
139
140 @Override
141 public boolean exists(FloatingIpId floatingIpId) {
142 checkNotNull(floatingIpId, FLOATINGIP_ID_NOT_NULL);
143 return floatingIpStore.containsKey(floatingIpId);
144 }
145
146 @Override
147 public boolean floatingIpIsUsed(IpAddress floatingIpAddr,
148 FloatingIpId floatingIpId) {
149 checkNotNull(floatingIpAddr, "Floating IP address cannot be null");
150 checkNotNull(floatingIpId, "Floating IP Id cannot be null");
151 Collection<FloatingIp> floatingIps = getFloatingIps();
152 for (FloatingIp floatingIp : floatingIps) {
153 if (floatingIp.floatingIp().equals(floatingIpAddr)
154 && !floatingIp.id().equals(floatingIpId)) {
155 return true;
156 }
157 }
158 return false;
159 }
160
161 @Override
162 public boolean fixedIpIsUsed(IpAddress fixedIpAddr, TenantId tenantId,
163 FloatingIpId floatingIpId) {
164 checkNotNull(fixedIpAddr, "Fixed IP address cannot be null");
165 checkNotNull(tenantId, "Tenant Id cannot be null");
166 checkNotNull(floatingIpId, "Floating IP Id cannot be null");
167 Collection<FloatingIp> floatingIps = getFloatingIps();
168 for (FloatingIp floatingIp : floatingIps) {
169 IpAddress fixedIp = floatingIp.fixedIp();
170 if (fixedIp != null) {
171 if (fixedIp.equals(fixedIpAddr)
172 && floatingIp.tenantId().equals(tenantId)
173 && !floatingIp.id().equals(floatingIpId)) {
174 return true;
175 }
176 }
177 }
178 return false;
179 }
180
181 @Override
182 public boolean createFloatingIps(Collection<FloatingIp> floatingIps) {
183 checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
184 boolean result = true;
185 for (FloatingIp floatingIp : floatingIps) {
186 verifyFloatingIpData(floatingIp);
lishuaib43dbf72016-01-06 11:11:35 +0800187 floatingIpStore.put(floatingIp.id(), floatingIp);
188 if (!floatingIpStore.containsKey(floatingIp.id())) {
189 log.debug("The floating Ip is created failed whose identifier is {}",
190 floatingIp.id().toString());
191 result = false;
jiangrui9c6db862015-11-27 14:50:46 +0800192 }
193 }
194 return result;
195 }
196
197 @Override
198 public boolean updateFloatingIps(Collection<FloatingIp> floatingIps) {
199 checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
200 boolean result = true;
Satish Ke3005812015-11-28 15:35:56 +0530201 for (FloatingIp floatingIp : floatingIps) {
202 verifyFloatingIpData(floatingIp);
lishuai762df812016-01-08 11:51:15 +0800203 FloatingIp oldFloatingIp = floatingIpStore.get(floatingIp.id());
204 floatingIpBindStore.put(floatingIp.id(), oldFloatingIp);
lishuaib43dbf72016-01-06 11:11:35 +0800205 floatingIpStore.put(floatingIp.id(), floatingIp);
206 if (!floatingIpStore.containsKey(floatingIp.id())) {
207 log.debug("The floating Ip is updated failed whose identifier is {}",
208 floatingIp.id().toString());
209 result = false;
jiangrui9c6db862015-11-27 14:50:46 +0800210 }
211 }
212 return result;
213 }
214
215 @Override
216 public boolean removeFloatingIps(Collection<FloatingIpId> floatingIpIds) {
217 checkNotNull(floatingIpIds, FLOATINGIP_ID_NOT_NULL);
218 boolean result = true;
Satish Ke3005812015-11-28 15:35:56 +0530219 for (FloatingIpId floatingIpId : floatingIpIds) {
220 if (!floatingIpStore.containsKey(floatingIpId)) {
221 log.debug("The floatingIp is not exist whose identifier is {}",
222 floatingIpId.toString());
223 throw new IllegalArgumentException(
224 "FloatingIP ID doesn't exist");
225 }
226 FloatingIp floatingIp = floatingIpStore.get(floatingIpId);
227 floatingIpStore.remove(floatingIpId, floatingIp);
lishuai762df812016-01-08 11:51:15 +0800228 floatingIpBindStore.remove(floatingIpId);
Satish Ke3005812015-11-28 15:35:56 +0530229 if (floatingIpStore.containsKey(floatingIpId)) {
230 log.debug("The floating Ip is deleted failed whose identifier is {}",
231 floatingIpId.toString());
232 result = false;
jiangrui9c6db862015-11-27 14:50:46 +0800233 }
234 }
235 return result;
236 }
237
238 @Override
239 public void addListener(FloatingIpListener listener) {
240 checkNotNull(listener, LISTENER_NOT_NULL);
241 listeners.add(listener);
242 }
243
244 @Override
245 public void removeListener(FloatingIpListener listener) {
246 checkNotNull(listener, LISTENER_NOT_NULL);
247 listeners.add(listener);
248 }
249
250 /**
251 * Verifies validity of FloatingIp data.
252 *
253 * @param floatingIps floatingIp instance
254 */
255 private void verifyFloatingIpData(FloatingIp floatingIps) {
256 checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
257 if (!tenantNetworkService.exists(floatingIps.networkId())) {
258 log.debug("The network identifier {} that the floating Ip {} create for is not exist",
259 floatingIps.networkId().toString(), floatingIps.id()
260 .toString());
261 throw new IllegalArgumentException(
262 "Floating network ID doesn't exist");
263 }
264
265 VirtualPortId portId = floatingIps.portId();
266 if (portId != null && !virtualPortService.exists(portId)) {
267 log.debug("The port identifier {} that the floating Ip {} create for is not exist",
268 floatingIps.portId().toString(), floatingIps.id()
269 .toString());
270 throw new IllegalArgumentException("Port ID doesn't exist");
271 }
272
273 RouterId routerId = floatingIps.routerId();
274 if (routerId != null && !routerService.exists(routerId)) {
275 log.debug("The router identifier {} that the floating Ip {} create for is not exist",
276 floatingIps.routerId().toString(), floatingIps.id()
277 .toString());
278 throw new IllegalArgumentException("Router ID doesn't exist");
279 }
280
281 if (floatingIpIsUsed(floatingIps.floatingIp(), floatingIps.id())) {
282 log.debug("The floaing Ip {} that the floating Ip {} create for is used",
283 floatingIps.floatingIp().toString(), floatingIps.id()
284 .toString());
285 throw new IllegalArgumentException(
286 "The floating IP address is used");
287 }
288
289 IpAddress fixedIp = floatingIps.fixedIp();
290 if (fixedIp != null
291 && fixedIpIsUsed(fixedIp, floatingIps.tenantId(),
292 floatingIps.id())) {
293 log.debug("The fixed Ip {} that the floating Ip {} create for is used",
294 floatingIps.fixedIp().toString(), floatingIps.id()
295 .toString());
296 throw new IllegalArgumentException("The fixed IP address is used");
297 }
298 }
299
300 private class InnerFloatingIpStoreListener
301 implements
302 EventuallyConsistentMapListener<FloatingIpId, FloatingIp> {
303
304 @Override
305 public void event(EventuallyConsistentMapEvent<FloatingIpId, FloatingIp> event) {
306 checkNotNull(event, EVENT_NOT_NULL);
307 FloatingIp floatingIp = event.value();
308 if (EventuallyConsistentMapEvent.Type.PUT == event.type()) {
309 notifyListeners(new FloatingIpEvent(
310 FloatingIpEvent.Type.FLOATINGIP_PUT,
311 floatingIp));
lishuai762df812016-01-08 11:51:15 +0800312 if (floatingIp.portId() != null) {
313 notifyListeners(new FloatingIpEvent(
314 FloatingIpEvent.Type.FLOATINGIP_BIND,
315 floatingIp));
316 } else {
317 FloatingIp oldFloatingIp = floatingIpBindStore.get(floatingIp.id());
318 if (oldFloatingIp != null) {
319 notifyListeners(new FloatingIpEvent(
320 FloatingIpEvent.Type.FLOATINGIP_UNBIND,
321 oldFloatingIp));
322 }
323 }
jiangrui9c6db862015-11-27 14:50:46 +0800324 }
325 if (EventuallyConsistentMapEvent.Type.REMOVE == event.type()) {
326 notifyListeners(new FloatingIpEvent(
327 FloatingIpEvent.Type.FLOATINGIP_DELETE,
328 floatingIp));
lishuai16c05af2016-01-21 18:39:05 +0800329 if (floatingIp.portId() != null) {
330 notifyListeners(new FloatingIpEvent(
331 FloatingIpEvent.Type.FLOATINGIP_UNBIND,
332 floatingIp));
333 }
jiangrui9c6db862015-11-27 14:50:46 +0800334 }
335 }
336 }
337
338 /**
339 * Notifies specify event to all listeners.
340 *
341 * @param event Floating IP event
342 */
343 private void notifyListeners(FloatingIpEvent event) {
344 checkNotNull(event, EVENT_NOT_NULL);
345 listeners.forEach(listener -> listener.event(event));
346 }
347}