blob: 196d889e488d4af878ae3f360c66165cfccc68fd [file] [log] [blame]
jiangrui9c6db862015-11-27 14:50:46 +08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
jiangrui9c6db862015-11-27 14:50:46 +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.vtnrsc.floatingip.impl;
17
Ray Milkeyd84f89b2018-08-17 14:54:17 -070018import com.google.common.collect.Sets;
jiangrui9c6db862015-11-27 14:50:46 +080019import org.onlab.packet.IpAddress;
20import org.onlab.util.KryoNamespace;
21import org.onosproject.core.ApplicationId;
22import org.onosproject.core.CoreService;
23import org.onosproject.store.serializers.KryoNamespaces;
24import org.onosproject.store.service.EventuallyConsistentMap;
25import org.onosproject.store.service.EventuallyConsistentMapEvent;
26import org.onosproject.store.service.EventuallyConsistentMapListener;
27import org.onosproject.store.service.StorageService;
28import org.onosproject.store.service.WallClockTimestamp;
29import org.onosproject.vtnrsc.DefaultFloatingIp;
30import org.onosproject.vtnrsc.FloatingIp;
31import org.onosproject.vtnrsc.FloatingIpId;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070032import org.onosproject.vtnrsc.RouterId;
jiangrui9c6db862015-11-27 14:50:46 +080033import org.onosproject.vtnrsc.TenantId;
34import org.onosproject.vtnrsc.TenantNetworkId;
35import org.onosproject.vtnrsc.VirtualPortId;
jiangrui9c6db862015-11-27 14:50:46 +080036import org.onosproject.vtnrsc.floatingip.FloatingIpEvent;
37import org.onosproject.vtnrsc.floatingip.FloatingIpListener;
38import org.onosproject.vtnrsc.floatingip.FloatingIpService;
39import org.onosproject.vtnrsc.router.RouterService;
40import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
41import org.onosproject.vtnrsc.virtualport.VirtualPortService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070042import org.osgi.service.component.annotations.Activate;
43import org.osgi.service.component.annotations.Component;
44import org.osgi.service.component.annotations.Deactivate;
45import org.osgi.service.component.annotations.Reference;
46import org.osgi.service.component.annotations.ReferenceCardinality;
jiangrui9c6db862015-11-27 14:50:46 +080047import org.slf4j.Logger;
48
Ray Milkeyd84f89b2018-08-17 14:54:17 -070049import java.util.Collection;
50import java.util.Collections;
51import java.util.Set;
52import java.util.UUID;
53
54import static com.google.common.base.Preconditions.checkNotNull;
55import static org.slf4j.LoggerFactory.getLogger;
jiangrui9c6db862015-11-27 14:50:46 +080056
57/**
58 * Provides implementation of the FloatingIp service.
59 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070060@Component(immediate = true, service = FloatingIpService.class)
jiangrui9c6db862015-11-27 14:50:46 +080061public class FloatingIpManager implements FloatingIpService {
62 private static final String FLOATINGIP_ID_NOT_NULL = "Floatingip ID cannot be null";
63 private static final String FLOATINGIP_NOT_NULL = "Floatingip cannot be null";
lishuai762df812016-01-08 11:51:15 +080064 private static final String FLOATINGIPSTORE = "vtn-floatingip-store";
65 private static final String FLOATINGIPBINDSTORE = "vtn-floatingip-bind-store";
jiangrui9c6db862015-11-27 14:50:46 +080066 private static final String VTNRSC_APP = "org.onosproject.vtnrsc";
67 private static final String LISTENER_NOT_NULL = "Listener cannot be null";
68 private static final String EVENT_NOT_NULL = "event cannot be null";
69
70 private final Logger log = getLogger(getClass());
71 private final Set<FloatingIpListener> listeners = Sets
72 .newCopyOnWriteArraySet();
73 private EventuallyConsistentMapListener<FloatingIpId, FloatingIp> floatingIpListener =
74 new InnerFloatingIpStoreListener();
75 protected EventuallyConsistentMap<FloatingIpId, FloatingIp> floatingIpStore;
lishuai762df812016-01-08 11:51:15 +080076 protected EventuallyConsistentMap<FloatingIpId, FloatingIp> floatingIpBindStore;
jiangrui9c6db862015-11-27 14:50:46 +080077 protected ApplicationId appId;
78
Ray Milkeyd84f89b2018-08-17 14:54:17 -070079 @Reference(cardinality = ReferenceCardinality.MANDATORY)
jiangrui9c6db862015-11-27 14:50:46 +080080 protected StorageService storageService;
81
Ray Milkeyd84f89b2018-08-17 14:54:17 -070082 @Reference(cardinality = ReferenceCardinality.MANDATORY)
jiangrui9c6db862015-11-27 14:50:46 +080083 protected CoreService coreService;
84
Ray Milkeyd84f89b2018-08-17 14:54:17 -070085 @Reference(cardinality = ReferenceCardinality.MANDATORY)
jiangrui9c6db862015-11-27 14:50:46 +080086 protected TenantNetworkService tenantNetworkService;
87
Ray Milkeyd84f89b2018-08-17 14:54:17 -070088 @Reference(cardinality = ReferenceCardinality.MANDATORY)
jiangrui9c6db862015-11-27 14:50:46 +080089 protected VirtualPortService virtualPortService;
90
Ray Milkeyd84f89b2018-08-17 14:54:17 -070091 @Reference(cardinality = ReferenceCardinality.MANDATORY)
jiangrui9c6db862015-11-27 14:50:46 +080092 protected RouterService routerService;
93
94 @Activate
95 public void activate() {
96 appId = coreService.registerApplication(VTNRSC_APP);
97 KryoNamespace.Builder serializer = KryoNamespace
98 .newBuilder()
99 .register(KryoNamespaces.API)
100 .register(FloatingIp.class, FloatingIpId.class,
101 TenantNetworkId.class, TenantId.class,
102 FloatingIp.Status.class, RouterId.class,
yuanyoue2ed3862016-05-06 13:18:08 +0800103 VirtualPortId.class, DefaultFloatingIp.class,
104 UUID.class);
jiangrui9c6db862015-11-27 14:50:46 +0800105 floatingIpStore = storageService
106 .<FloatingIpId, FloatingIp>eventuallyConsistentMapBuilder()
lishuai762df812016-01-08 11:51:15 +0800107 .withName(FLOATINGIPSTORE).withSerializer(serializer)
108 .withTimestampProvider((k, v) -> new WallClockTimestamp())
109 .build();
110 floatingIpBindStore = storageService
111 .<FloatingIpId, FloatingIp>eventuallyConsistentMapBuilder()
112 .withName(FLOATINGIPBINDSTORE).withSerializer(serializer)
jiangrui9c6db862015-11-27 14:50:46 +0800113 .withTimestampProvider((k, v) -> new WallClockTimestamp())
114 .build();
115 floatingIpStore.addListener(floatingIpListener);
116 log.info("Started");
117 }
118
119 @Deactivate
120 public void deactivate() {
121 floatingIpStore.removeListener(floatingIpListener);
122 floatingIpStore.destroy();
lishuai762df812016-01-08 11:51:15 +0800123 floatingIpBindStore.destroy();
jiangrui9c6db862015-11-27 14:50:46 +0800124 listeners.clear();
125 log.info("Stopped");
126 }
127
128 @Override
129 public Collection<FloatingIp> getFloatingIps() {
130 return Collections.unmodifiableCollection(floatingIpStore.values());
131 }
132
133 @Override
134 public FloatingIp getFloatingIp(FloatingIpId floatingIpId) {
135 checkNotNull(floatingIpId, FLOATINGIP_ID_NOT_NULL);
136 return floatingIpStore.get(floatingIpId);
137 }
138
139 @Override
140 public boolean exists(FloatingIpId floatingIpId) {
141 checkNotNull(floatingIpId, FLOATINGIP_ID_NOT_NULL);
142 return floatingIpStore.containsKey(floatingIpId);
143 }
144
145 @Override
146 public boolean floatingIpIsUsed(IpAddress floatingIpAddr,
147 FloatingIpId floatingIpId) {
148 checkNotNull(floatingIpAddr, "Floating IP address cannot be null");
149 checkNotNull(floatingIpId, "Floating IP Id cannot be null");
150 Collection<FloatingIp> floatingIps = getFloatingIps();
151 for (FloatingIp floatingIp : floatingIps) {
152 if (floatingIp.floatingIp().equals(floatingIpAddr)
153 && !floatingIp.id().equals(floatingIpId)) {
154 return true;
155 }
156 }
157 return false;
158 }
159
160 @Override
161 public boolean fixedIpIsUsed(IpAddress fixedIpAddr, TenantId tenantId,
162 FloatingIpId floatingIpId) {
163 checkNotNull(fixedIpAddr, "Fixed IP address cannot be null");
164 checkNotNull(tenantId, "Tenant Id cannot be null");
165 checkNotNull(floatingIpId, "Floating IP Id cannot be null");
166 Collection<FloatingIp> floatingIps = getFloatingIps();
167 for (FloatingIp floatingIp : floatingIps) {
168 IpAddress fixedIp = floatingIp.fixedIp();
169 if (fixedIp != null) {
170 if (fixedIp.equals(fixedIpAddr)
171 && floatingIp.tenantId().equals(tenantId)
172 && !floatingIp.id().equals(floatingIpId)) {
173 return true;
174 }
175 }
176 }
177 return false;
178 }
179
180 @Override
181 public boolean createFloatingIps(Collection<FloatingIp> floatingIps) {
182 checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
183 boolean result = true;
184 for (FloatingIp floatingIp : floatingIps) {
185 verifyFloatingIpData(floatingIp);
lishuaib43dbf72016-01-06 11:11:35 +0800186 floatingIpStore.put(floatingIp.id(), floatingIp);
187 if (!floatingIpStore.containsKey(floatingIp.id())) {
188 log.debug("The floating Ip is created failed whose identifier is {}",
189 floatingIp.id().toString());
190 result = false;
jiangrui9c6db862015-11-27 14:50:46 +0800191 }
192 }
193 return result;
194 }
195
196 @Override
197 public boolean updateFloatingIps(Collection<FloatingIp> floatingIps) {
198 checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
199 boolean result = true;
Satish Ke3005812015-11-28 15:35:56 +0530200 for (FloatingIp floatingIp : floatingIps) {
201 verifyFloatingIpData(floatingIp);
lishuai762df812016-01-08 11:51:15 +0800202 FloatingIp oldFloatingIp = floatingIpStore.get(floatingIp.id());
203 floatingIpBindStore.put(floatingIp.id(), oldFloatingIp);
lishuaib43dbf72016-01-06 11:11:35 +0800204 floatingIpStore.put(floatingIp.id(), floatingIp);
205 if (!floatingIpStore.containsKey(floatingIp.id())) {
206 log.debug("The floating Ip is updated failed whose identifier is {}",
207 floatingIp.id().toString());
208 result = false;
jiangrui9c6db862015-11-27 14:50:46 +0800209 }
210 }
211 return result;
212 }
213
214 @Override
215 public boolean removeFloatingIps(Collection<FloatingIpId> floatingIpIds) {
216 checkNotNull(floatingIpIds, FLOATINGIP_ID_NOT_NULL);
217 boolean result = true;
Satish Ke3005812015-11-28 15:35:56 +0530218 for (FloatingIpId floatingIpId : floatingIpIds) {
219 if (!floatingIpStore.containsKey(floatingIpId)) {
220 log.debug("The floatingIp is not exist whose identifier is {}",
221 floatingIpId.toString());
222 throw new IllegalArgumentException(
223 "FloatingIP ID doesn't exist");
224 }
225 FloatingIp floatingIp = floatingIpStore.get(floatingIpId);
226 floatingIpStore.remove(floatingIpId, floatingIp);
lishuai762df812016-01-08 11:51:15 +0800227 floatingIpBindStore.remove(floatingIpId);
Satish Ke3005812015-11-28 15:35:56 +0530228 if (floatingIpStore.containsKey(floatingIpId)) {
229 log.debug("The floating Ip is deleted failed whose identifier is {}",
230 floatingIpId.toString());
231 result = false;
jiangrui9c6db862015-11-27 14:50:46 +0800232 }
233 }
234 return result;
235 }
236
237 @Override
238 public void addListener(FloatingIpListener listener) {
239 checkNotNull(listener, LISTENER_NOT_NULL);
240 listeners.add(listener);
241 }
242
243 @Override
244 public void removeListener(FloatingIpListener listener) {
245 checkNotNull(listener, LISTENER_NOT_NULL);
jaegonkim7d3120d2017-02-10 07:16:29 +0900246 listeners.remove(listener);
jiangrui9c6db862015-11-27 14:50:46 +0800247 }
248
249 /**
250 * Verifies validity of FloatingIp data.
251 *
252 * @param floatingIps floatingIp instance
253 */
254 private void verifyFloatingIpData(FloatingIp floatingIps) {
255 checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
256 if (!tenantNetworkService.exists(floatingIps.networkId())) {
257 log.debug("The network identifier {} that the floating Ip {} create for is not exist",
258 floatingIps.networkId().toString(), floatingIps.id()
259 .toString());
260 throw new IllegalArgumentException(
261 "Floating network ID doesn't exist");
262 }
263
264 VirtualPortId portId = floatingIps.portId();
265 if (portId != null && !virtualPortService.exists(portId)) {
266 log.debug("The port identifier {} that the floating Ip {} create for is not exist",
267 floatingIps.portId().toString(), floatingIps.id()
268 .toString());
269 throw new IllegalArgumentException("Port ID doesn't exist");
270 }
271
272 RouterId routerId = floatingIps.routerId();
273 if (routerId != null && !routerService.exists(routerId)) {
274 log.debug("The router identifier {} that the floating Ip {} create for is not exist",
275 floatingIps.routerId().toString(), floatingIps.id()
276 .toString());
277 throw new IllegalArgumentException("Router ID doesn't exist");
278 }
279
280 if (floatingIpIsUsed(floatingIps.floatingIp(), floatingIps.id())) {
281 log.debug("The floaing Ip {} that the floating Ip {} create for is used",
282 floatingIps.floatingIp().toString(), floatingIps.id()
283 .toString());
284 throw new IllegalArgumentException(
285 "The floating IP address is used");
286 }
287
288 IpAddress fixedIp = floatingIps.fixedIp();
289 if (fixedIp != null
290 && fixedIpIsUsed(fixedIp, floatingIps.tenantId(),
291 floatingIps.id())) {
292 log.debug("The fixed Ip {} that the floating Ip {} create for is used",
293 floatingIps.fixedIp().toString(), floatingIps.id()
294 .toString());
295 throw new IllegalArgumentException("The fixed IP address is used");
296 }
297 }
298
299 private class InnerFloatingIpStoreListener
300 implements
301 EventuallyConsistentMapListener<FloatingIpId, FloatingIp> {
302
303 @Override
304 public void event(EventuallyConsistentMapEvent<FloatingIpId, FloatingIp> event) {
305 checkNotNull(event, EVENT_NOT_NULL);
306 FloatingIp floatingIp = event.value();
307 if (EventuallyConsistentMapEvent.Type.PUT == event.type()) {
308 notifyListeners(new FloatingIpEvent(
309 FloatingIpEvent.Type.FLOATINGIP_PUT,
310 floatingIp));
lishuai762df812016-01-08 11:51:15 +0800311 if (floatingIp.portId() != null) {
312 notifyListeners(new FloatingIpEvent(
313 FloatingIpEvent.Type.FLOATINGIP_BIND,
314 floatingIp));
315 } else {
316 FloatingIp oldFloatingIp = floatingIpBindStore.get(floatingIp.id());
317 if (oldFloatingIp != null) {
318 notifyListeners(new FloatingIpEvent(
319 FloatingIpEvent.Type.FLOATINGIP_UNBIND,
320 oldFloatingIp));
321 }
322 }
jiangrui9c6db862015-11-27 14:50:46 +0800323 }
324 if (EventuallyConsistentMapEvent.Type.REMOVE == event.type()) {
325 notifyListeners(new FloatingIpEvent(
326 FloatingIpEvent.Type.FLOATINGIP_DELETE,
327 floatingIp));
lishuai16c05af2016-01-21 18:39:05 +0800328 if (floatingIp.portId() != null) {
329 notifyListeners(new FloatingIpEvent(
330 FloatingIpEvent.Type.FLOATINGIP_UNBIND,
331 floatingIp));
332 }
jiangrui9c6db862015-11-27 14:50:46 +0800333 }
334 }
335 }
336
337 /**
338 * Notifies specify event to all listeners.
339 *
340 * @param event Floating IP event
341 */
342 private void notifyListeners(FloatingIpEvent event) {
343 checkNotNull(event, EVENT_NOT_NULL);
344 listeners.forEach(listener -> listener.event(event));
345 }
346}