blob: ce9bb21fc640b9d8ffd3a7aa21ca12e2cf57fed2 [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";
66 private static final String FLOATINGIP = "vtn-floatingip-store";
67 private static final String VTNRSC_APP = "org.onosproject.vtnrsc";
68 private static final String LISTENER_NOT_NULL = "Listener cannot be null";
69 private static final String EVENT_NOT_NULL = "event cannot be null";
70
71 private final Logger log = getLogger(getClass());
72 private final Set<FloatingIpListener> listeners = Sets
73 .newCopyOnWriteArraySet();
74 private EventuallyConsistentMapListener<FloatingIpId, FloatingIp> floatingIpListener =
75 new InnerFloatingIpStoreListener();
76 protected EventuallyConsistentMap<FloatingIpId, FloatingIp> floatingIpStore;
77 protected ApplicationId appId;
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected StorageService storageService;
81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected CoreService coreService;
84
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected TenantNetworkService tenantNetworkService;
87
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected VirtualPortService virtualPortService;
90
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 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,
103 VirtualPortId.class, DefaultFloatingIp.class);
104 floatingIpStore = storageService
105 .<FloatingIpId, FloatingIp>eventuallyConsistentMapBuilder()
106 .withName(FLOATINGIP).withSerializer(serializer)
107 .withTimestampProvider((k, v) -> new WallClockTimestamp())
108 .build();
109 floatingIpStore.addListener(floatingIpListener);
110 log.info("Started");
111 }
112
113 @Deactivate
114 public void deactivate() {
115 floatingIpStore.removeListener(floatingIpListener);
116 floatingIpStore.destroy();
117 listeners.clear();
118 log.info("Stopped");
119 }
120
121 @Override
122 public Collection<FloatingIp> getFloatingIps() {
123 return Collections.unmodifiableCollection(floatingIpStore.values());
124 }
125
126 @Override
127 public FloatingIp getFloatingIp(FloatingIpId floatingIpId) {
128 checkNotNull(floatingIpId, FLOATINGIP_ID_NOT_NULL);
129 return floatingIpStore.get(floatingIpId);
130 }
131
132 @Override
133 public boolean exists(FloatingIpId floatingIpId) {
134 checkNotNull(floatingIpId, FLOATINGIP_ID_NOT_NULL);
135 return floatingIpStore.containsKey(floatingIpId);
136 }
137
138 @Override
139 public boolean floatingIpIsUsed(IpAddress floatingIpAddr,
140 FloatingIpId floatingIpId) {
141 checkNotNull(floatingIpAddr, "Floating IP address cannot be null");
142 checkNotNull(floatingIpId, "Floating IP Id cannot be null");
143 Collection<FloatingIp> floatingIps = getFloatingIps();
144 for (FloatingIp floatingIp : floatingIps) {
145 if (floatingIp.floatingIp().equals(floatingIpAddr)
146 && !floatingIp.id().equals(floatingIpId)) {
147 return true;
148 }
149 }
150 return false;
151 }
152
153 @Override
154 public boolean fixedIpIsUsed(IpAddress fixedIpAddr, TenantId tenantId,
155 FloatingIpId floatingIpId) {
156 checkNotNull(fixedIpAddr, "Fixed IP address cannot be null");
157 checkNotNull(tenantId, "Tenant Id cannot be null");
158 checkNotNull(floatingIpId, "Floating IP Id cannot be null");
159 Collection<FloatingIp> floatingIps = getFloatingIps();
160 for (FloatingIp floatingIp : floatingIps) {
161 IpAddress fixedIp = floatingIp.fixedIp();
162 if (fixedIp != null) {
163 if (fixedIp.equals(fixedIpAddr)
164 && floatingIp.tenantId().equals(tenantId)
165 && !floatingIp.id().equals(floatingIpId)) {
166 return true;
167 }
168 }
169 }
170 return false;
171 }
172
173 @Override
174 public boolean createFloatingIps(Collection<FloatingIp> floatingIps) {
175 checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
176 boolean result = true;
177 for (FloatingIp floatingIp : floatingIps) {
178 verifyFloatingIpData(floatingIp);
179 if (floatingIp.portId() != null) {
180 floatingIpStore.put(floatingIp.id(), floatingIp);
181 if (!floatingIpStore.containsKey(floatingIp.id())) {
182 log.debug("The floating Ip is created failed whose identifier is {}",
183 floatingIp.id().toString());
184 result = false;
185 }
186 } else {
187 FloatingIp oldFloatingIp = floatingIpStore.get(floatingIp.id());
188 if (oldFloatingIp != null) {
189 floatingIpStore.remove(floatingIp.id(), oldFloatingIp);
190 if (floatingIpStore.containsKey(floatingIp.id())) {
191 log.debug("The floating Ip is created failed whose identifier is {}",
192 floatingIp.id().toString());
193 result = false;
194 }
195 }
196 }
197 }
198 return result;
199 }
200
201 @Override
202 public boolean updateFloatingIps(Collection<FloatingIp> floatingIps) {
203 checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
204 boolean result = true;
Satish Ke3005812015-11-28 15:35:56 +0530205 for (FloatingIp floatingIp : floatingIps) {
206 verifyFloatingIpData(floatingIp);
207 if (floatingIp.portId() != null) {
208 floatingIpStore.put(floatingIp.id(), floatingIp);
209 if (!floatingIpStore.containsKey(floatingIp.id())) {
210 log.debug("The floating Ip is updated failed whose identifier is {}",
211 floatingIp.id().toString());
212 result = false;
213 }
214 } else {
215 FloatingIp oldFloatingIp = floatingIpStore.get(floatingIp.id());
216 if (oldFloatingIp != null) {
217 floatingIpStore.remove(floatingIp.id(), oldFloatingIp);
218 if (floatingIpStore.containsKey(floatingIp.id())) {
jiangrui9c6db862015-11-27 14:50:46 +0800219 log.debug("The floating Ip is updated failed whose identifier is {}",
220 floatingIp.id().toString());
221 result = false;
222 }
jiangrui9c6db862015-11-27 14:50:46 +0800223 }
224 }
225 }
226 return result;
227 }
228
229 @Override
230 public boolean removeFloatingIps(Collection<FloatingIpId> floatingIpIds) {
231 checkNotNull(floatingIpIds, FLOATINGIP_ID_NOT_NULL);
232 boolean result = true;
Satish Ke3005812015-11-28 15:35:56 +0530233 for (FloatingIpId floatingIpId : floatingIpIds) {
234 if (!floatingIpStore.containsKey(floatingIpId)) {
235 log.debug("The floatingIp is not exist whose identifier is {}",
236 floatingIpId.toString());
237 throw new IllegalArgumentException(
238 "FloatingIP ID doesn't exist");
239 }
240 FloatingIp floatingIp = floatingIpStore.get(floatingIpId);
241 floatingIpStore.remove(floatingIpId, floatingIp);
242 if (floatingIpStore.containsKey(floatingIpId)) {
243 log.debug("The floating Ip is deleted failed whose identifier is {}",
244 floatingIpId.toString());
245 result = false;
jiangrui9c6db862015-11-27 14:50:46 +0800246 }
247 }
248 return result;
249 }
250
251 @Override
252 public void addListener(FloatingIpListener listener) {
253 checkNotNull(listener, LISTENER_NOT_NULL);
254 listeners.add(listener);
255 }
256
257 @Override
258 public void removeListener(FloatingIpListener listener) {
259 checkNotNull(listener, LISTENER_NOT_NULL);
260 listeners.add(listener);
261 }
262
263 /**
264 * Verifies validity of FloatingIp data.
265 *
266 * @param floatingIps floatingIp instance
267 */
268 private void verifyFloatingIpData(FloatingIp floatingIps) {
269 checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
270 if (!tenantNetworkService.exists(floatingIps.networkId())) {
271 log.debug("The network identifier {} that the floating Ip {} create for is not exist",
272 floatingIps.networkId().toString(), floatingIps.id()
273 .toString());
274 throw new IllegalArgumentException(
275 "Floating network ID doesn't exist");
276 }
277
278 VirtualPortId portId = floatingIps.portId();
279 if (portId != null && !virtualPortService.exists(portId)) {
280 log.debug("The port identifier {} that the floating Ip {} create for is not exist",
281 floatingIps.portId().toString(), floatingIps.id()
282 .toString());
283 throw new IllegalArgumentException("Port ID doesn't exist");
284 }
285
286 RouterId routerId = floatingIps.routerId();
287 if (routerId != null && !routerService.exists(routerId)) {
288 log.debug("The router identifier {} that the floating Ip {} create for is not exist",
289 floatingIps.routerId().toString(), floatingIps.id()
290 .toString());
291 throw new IllegalArgumentException("Router ID doesn't exist");
292 }
293
294 if (floatingIpIsUsed(floatingIps.floatingIp(), floatingIps.id())) {
295 log.debug("The floaing Ip {} that the floating Ip {} create for is used",
296 floatingIps.floatingIp().toString(), floatingIps.id()
297 .toString());
298 throw new IllegalArgumentException(
299 "The floating IP address is used");
300 }
301
302 IpAddress fixedIp = floatingIps.fixedIp();
303 if (fixedIp != null
304 && fixedIpIsUsed(fixedIp, floatingIps.tenantId(),
305 floatingIps.id())) {
306 log.debug("The fixed Ip {} that the floating Ip {} create for is used",
307 floatingIps.fixedIp().toString(), floatingIps.id()
308 .toString());
309 throw new IllegalArgumentException("The fixed IP address is used");
310 }
311 }
312
313 private class InnerFloatingIpStoreListener
314 implements
315 EventuallyConsistentMapListener<FloatingIpId, FloatingIp> {
316
317 @Override
318 public void event(EventuallyConsistentMapEvent<FloatingIpId, FloatingIp> event) {
319 checkNotNull(event, EVENT_NOT_NULL);
320 FloatingIp floatingIp = event.value();
321 if (EventuallyConsistentMapEvent.Type.PUT == event.type()) {
322 notifyListeners(new FloatingIpEvent(
323 FloatingIpEvent.Type.FLOATINGIP_PUT,
324 floatingIp));
325 }
326 if (EventuallyConsistentMapEvent.Type.REMOVE == event.type()) {
327 notifyListeners(new FloatingIpEvent(
328 FloatingIpEvent.Type.FLOATINGIP_DELETE,
329 floatingIp));
330 }
331 }
332 }
333
334 /**
335 * Notifies specify event to all listeners.
336 *
337 * @param event Floating IP event
338 */
339 private void notifyListeners(FloatingIpEvent event) {
340 checkNotNull(event, EVENT_NOT_NULL);
341 listeners.forEach(listener -> listener.event(event));
342 }
343}