blob: f81493b30aad38698136c141fb6258b3b41cf945 [file] [log] [blame]
Thomas Vachuska48448082016-02-19 22:14:54 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Thomas Vachuska48448082016-02-19 22:14:54 -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 */
16
17package org.onosproject.net.region.impl;
18
Simon Hunt1bee5292016-10-14 11:02:33 -070019import com.google.common.collect.ImmutableSet;
Thomas Vachuska48448082016-02-19 22:14:54 -080020import org.apache.felix.scr.annotations.Activate;
Jian Li0c451802016-02-24 22:39:25 +090021import org.apache.felix.scr.annotations.Component;
Thomas Vachuska48448082016-02-19 22:14:54 -080022import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
Jian Li0c451802016-02-24 22:39:25 +090025import org.apache.felix.scr.annotations.Service;
Simon Hunt8f60ff82017-04-24 17:19:30 -070026import org.onlab.util.ItemNotFoundException;
Thomas Vachuska48448082016-02-19 22:14:54 -080027import org.onosproject.cluster.NodeId;
28import org.onosproject.event.AbstractListenerManager;
Simon Hunt53612212016-12-04 17:19:52 -080029import org.onosproject.net.Annotations;
30import org.onosproject.net.DefaultAnnotations;
Thomas Vachuska48448082016-02-19 22:14:54 -080031import org.onosproject.net.DeviceId;
Steven Burrows19e6e4f2016-10-05 13:27:07 -050032import org.onosproject.net.HostId;
Simon Hunt8f60ff82017-04-24 17:19:30 -070033import org.onosproject.net.config.NetworkConfigEvent;
34import org.onosproject.net.config.NetworkConfigListener;
Simon Hunt53612212016-12-04 17:19:52 -080035import org.onosproject.net.config.NetworkConfigService;
36import org.onosproject.net.config.basics.BasicElementConfig;
37import org.onosproject.net.config.basics.BasicRegionConfig;
Thomas Vachuska48448082016-02-19 22:14:54 -080038import org.onosproject.net.region.Region;
39import org.onosproject.net.region.RegionAdminService;
40import org.onosproject.net.region.RegionEvent;
41import org.onosproject.net.region.RegionId;
42import org.onosproject.net.region.RegionListener;
43import org.onosproject.net.region.RegionService;
44import org.onosproject.net.region.RegionStore;
45import org.onosproject.net.region.RegionStoreDelegate;
Simon Hunt8f60ff82017-04-24 17:19:30 -070046import org.onosproject.ui.topo.LayoutLocation;
Thomas Vachuska48448082016-02-19 22:14:54 -080047import org.slf4j.Logger;
48
49import java.util.Collection;
50import java.util.List;
51import java.util.Set;
52
53import static com.google.common.base.Preconditions.checkNotNull;
54import static com.google.common.base.Preconditions.checkState;
55import static com.google.common.collect.ImmutableList.of;
Heedo Kang4a47a302016-02-29 17:40:23 +090056import static org.onosproject.security.AppGuard.checkPermission;
57import static org.onosproject.security.AppPermission.Type.REGION_READ;
Simon Hunt8f60ff82017-04-24 17:19:30 -070058import static org.onosproject.ui.topo.LayoutLocation.toCompactListString;
Simon Hunt53612212016-12-04 17:19:52 -080059import static org.slf4j.LoggerFactory.getLogger;
Thomas Vachuska48448082016-02-19 22:14:54 -080060
61/**
62 * Provides implementation of the region service APIs.
63 */
Jian Li0c451802016-02-24 22:39:25 +090064@Component(immediate = true)
65@Service
Thomas Vachuska48448082016-02-19 22:14:54 -080066public class RegionManager extends AbstractListenerManager<RegionEvent, RegionListener>
67 implements RegionAdminService, RegionService {
68
69 private static final String REGION_ID_NULL = "Region ID cannot be null";
70 private static final String REGION_TYPE_NULL = "Region type cannot be null";
71 private static final String DEVICE_ID_NULL = "Device ID cannot be null";
72 private static final String DEVICE_IDS_NULL = "Device IDs cannot be null";
73 private static final String DEVICE_IDS_EMPTY = "Device IDs cannot be empty";
74 private static final String NAME_NULL = "Name cannot be null";
75
Simon Hunt8f60ff82017-04-24 17:19:30 -070076 private static final String PEER_LOCATIONS = "peerLocations";
77
Thomas Vachuska48448082016-02-19 22:14:54 -080078 private final Logger log = getLogger(getClass());
79
Simon Hunt8f60ff82017-04-24 17:19:30 -070080 private final NetworkConfigListener networkConfigListener =
81 new InternalNetworkConfigListener();
82
Thomas Vachuska48448082016-02-19 22:14:54 -080083 private RegionStoreDelegate delegate = this::post;
84
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected RegionStore store;
87
Simon Hunt53612212016-12-04 17:19:52 -080088 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected NetworkConfigService networkConfigService;
90
Thomas Vachuska48448082016-02-19 22:14:54 -080091 @Activate
92 public void activate() {
93 store.setDelegate(delegate);
94 eventDispatcher.addSink(RegionEvent.class, listenerRegistry);
Simon Hunt8f60ff82017-04-24 17:19:30 -070095 networkConfigService.addListener(networkConfigListener);
Thomas Vachuska48448082016-02-19 22:14:54 -080096 log.info("Started");
97 }
98
99 @Deactivate
100 public void deactivate() {
101 store.unsetDelegate(delegate);
Simon Hunt8f60ff82017-04-24 17:19:30 -0700102 networkConfigService.removeListener(networkConfigListener);
Thomas Vachuska48448082016-02-19 22:14:54 -0800103 eventDispatcher.removeSink(RegionEvent.class);
104 log.info("Stopped");
105 }
106
Simon Hunt53612212016-12-04 17:19:52 -0800107 private String dstr(double d) {
108 return Double.toString(d);
109 }
110
111 private Annotations genAnnots(RegionId id) {
112 BasicRegionConfig cfg =
113 networkConfigService.getConfig(id, BasicRegionConfig.class);
Simon Hunt53612212016-12-04 17:19:52 -0800114 if (cfg == null) {
115 return DefaultAnnotations.builder().build();
116 }
Simon Hunt8f60ff82017-04-24 17:19:30 -0700117 return genAnnots(cfg, id);
118 }
119
120 private Annotations genAnnots(BasicRegionConfig cfg, RegionId rid) {
Simon Hunt53612212016-12-04 17:19:52 -0800121
122 DefaultAnnotations.Builder builder = DefaultAnnotations.builder()
123 .set(BasicElementConfig.NAME, cfg.name())
124 .set(BasicElementConfig.LATITUDE, dstr(cfg.latitude()))
125 .set(BasicElementConfig.LONGITUDE, dstr(cfg.longitude()));
126
127 // only set the UI_TYPE annotation if it is not null in the config
128 String uiType = cfg.uiType();
129 if (uiType != null) {
130 builder.set(BasicElementConfig.UI_TYPE, uiType);
131 }
132
Simon Hunt8f60ff82017-04-24 17:19:30 -0700133 List<LayoutLocation> locMappings = cfg.getMappings();
134 builder.set(PEER_LOCATIONS, toCompactListString(locMappings));
135
Simon Hunt53612212016-12-04 17:19:52 -0800136 return builder.build();
137 }
138
Thomas Vachuska48448082016-02-19 22:14:54 -0800139 @Override
140 public Region createRegion(RegionId regionId, String name, Region.Type type,
141 List<Set<NodeId>> masterNodeIds) {
142 checkNotNull(regionId, REGION_ID_NULL);
143 checkNotNull(name, NAME_NULL);
144 checkNotNull(name, REGION_TYPE_NULL);
Simon Hunt53612212016-12-04 17:19:52 -0800145
146 return store.createRegion(regionId, name, type, genAnnots(regionId),
Simon Hunt8f60ff82017-04-24 17:19:30 -0700147 masterNodeIds == null ? of() : masterNodeIds);
Thomas Vachuska48448082016-02-19 22:14:54 -0800148 }
149
150 @Override
151 public Region updateRegion(RegionId regionId, String name, Region.Type type,
152 List<Set<NodeId>> masterNodeIds) {
153 checkNotNull(regionId, REGION_ID_NULL);
154 checkNotNull(name, NAME_NULL);
155 checkNotNull(name, REGION_TYPE_NULL);
Simon Hunt53612212016-12-04 17:19:52 -0800156
157 return store.updateRegion(regionId, name, type, genAnnots(regionId),
Simon Hunt8f60ff82017-04-24 17:19:30 -0700158 masterNodeIds == null ? of() : masterNodeIds);
Thomas Vachuska48448082016-02-19 22:14:54 -0800159 }
160
161 @Override
162 public void removeRegion(RegionId regionId) {
163 checkNotNull(regionId, REGION_ID_NULL);
164 store.removeRegion(regionId);
165 }
166
167 @Override
168 public void addDevices(RegionId regionId, Collection<DeviceId> deviceIds) {
169 checkNotNull(regionId, REGION_ID_NULL);
170 checkNotNull(deviceIds, DEVICE_IDS_NULL);
171 checkState(!deviceIds.isEmpty(), DEVICE_IDS_EMPTY);
172 store.addDevices(regionId, deviceIds);
173 }
174
175 @Override
176 public void removeDevices(RegionId regionId, Collection<DeviceId> deviceIds) {
177 checkNotNull(regionId, REGION_ID_NULL);
178 checkNotNull(deviceIds, DEVICE_IDS_NULL);
179 checkState(!deviceIds.isEmpty(), DEVICE_IDS_EMPTY);
180 store.removeDevices(regionId, deviceIds);
181 }
182
183 @Override
184 public Set<Region> getRegions() {
Heedo Kang4a47a302016-02-29 17:40:23 +0900185 checkPermission(REGION_READ);
Thomas Vachuska48448082016-02-19 22:14:54 -0800186 return store.getRegions();
187 }
188
189 @Override
190 public Region getRegion(RegionId regionId) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900191 checkPermission(REGION_READ);
Thomas Vachuska48448082016-02-19 22:14:54 -0800192 checkNotNull(regionId, REGION_ID_NULL);
193 return store.getRegion(regionId);
194 }
195
196 @Override
197 public Region getRegionForDevice(DeviceId deviceId) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900198 checkPermission(REGION_READ);
Thomas Vachuska48448082016-02-19 22:14:54 -0800199 checkNotNull(deviceId, DEVICE_ID_NULL);
200 return store.getRegionForDevice(deviceId);
201 }
202
203 @Override
204 public Set<DeviceId> getRegionDevices(RegionId regionId) {
Heedo Kang4a47a302016-02-29 17:40:23 +0900205 checkPermission(REGION_READ);
Thomas Vachuska48448082016-02-19 22:14:54 -0800206 checkNotNull(regionId, REGION_ID_NULL);
207 return store.getRegionDevices(regionId);
208 }
209
Steven Burrows19e6e4f2016-10-05 13:27:07 -0500210 @Override
211 public Set<HostId> getRegionHosts(RegionId regionId) {
212 checkPermission(REGION_READ);
213 checkNotNull(regionId, REGION_ID_NULL);
Simon Hunt1bee5292016-10-14 11:02:33 -0700214 // TODO: compute hosts from region devices
215 return ImmutableSet.of();
Steven Burrows19e6e4f2016-10-05 13:27:07 -0500216 }
Simon Hunt351282d2016-10-14 16:27:48 +0000217
Simon Hunt8f60ff82017-04-24 17:19:30 -0700218 // by default allowed, otherwise check flag
219 private boolean isAllowed(BasicRegionConfig cfg) {
220 return (cfg == null || cfg.isAllowed());
221 }
222
223 private class InternalNetworkConfigListener implements NetworkConfigListener {
224 @Override
225 public void event(NetworkConfigEvent event) {
226 RegionId rid = (RegionId) event.subject();
227 BasicRegionConfig cfg =
228 networkConfigService.getConfig(rid, BasicRegionConfig.class);
229
230 if (!isAllowed(cfg)) {
231 kickOutBadRegion(rid);
232
233 } else {
234 // (1) Find the region
235 // (2) Syntehsize new region + cfg details
236 // (3) re-insert new region element into store
237
238 try {
239 Region region = getRegion(rid);
240 String name = region.name();
241 Region.Type type = region.type();
242 Annotations annots = genAnnots(cfg, rid);
243 List<Set<NodeId>> masterNodeIds = region.masters();
244
245 store.updateRegion(rid, name, type, annots, masterNodeIds);
246
247 } catch (ItemNotFoundException infe) {
248 log.debug("warn: no region found with id {}", rid);
249 }
250 }
251 }
252
253 @Override
254 public boolean isRelevant(NetworkConfigEvent event) {
255 return (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED
256 || event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)
257 && (event.configClass().equals(BasicRegionConfig.class));
258 }
259
260 private void kickOutBadRegion(RegionId regionId) {
261 Region badRegion = getRegion(regionId);
262 if (badRegion != null) {
263 removeRegion(regionId);
264 }
265 }
266 }
Thomas Vachuska48448082016-02-19 22:14:54 -0800267}