blob: 998f7dfe15b9c151a3d862ced1978ced75ca1d63 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.host.impl;
tomdb0d03f2014-08-27 16:34:15 -070017
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
soumya3e6f05e2016-08-05 15:11:11 -070021import org.apache.felix.scr.annotations.Modified;
22import org.apache.felix.scr.annotations.Property;
tom5f38b3a2014-08-27 23:50:54 -070023import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
tomdb0d03f2014-08-27 16:34:15 -070025import org.apache.felix.scr.annotations.Service;
Pier Luigi9b1d6262017-02-02 22:31:34 -080026import org.onlab.packet.Ip6Address;
Simon Huntff663742015-05-14 13:33:05 -070027import org.onlab.packet.IpAddress;
28import org.onlab.packet.MacAddress;
29import org.onlab.packet.VlanId;
soumya3e6f05e2016-08-05 15:11:11 -070030import org.onlab.util.Tools;
31import org.onosproject.cfg.ComponentConfigService;
Charles Chan47933752017-11-30 15:37:50 -080032import org.onosproject.net.host.HostLocationProbingService.ProbeMode;
Charles Chan82fac582017-09-12 12:09:22 -070033import org.onosproject.net.intf.Interface;
Ray Milkeyfacf2862017-08-03 11:58:29 -070034import org.onosproject.net.intf.InterfaceService;
Charles Chan888e20a2017-05-01 15:44:23 -070035import org.onosproject.net.HostLocation;
36import org.onosproject.net.edge.EdgePortService;
37import org.onosproject.net.provider.AbstractListenerProviderRegistry;
Simon Huntffbad3b2017-05-16 15:37:51 -070038import org.onosproject.net.config.NetworkConfigEvent;
39import org.onosproject.net.config.NetworkConfigListener;
40import org.onosproject.net.config.NetworkConfigService;
41import org.onosproject.net.config.basics.BasicHostConfig;
Charles Chan888e20a2017-05-01 15:44:23 -070042import org.onosproject.net.ConnectPoint;
43import org.onosproject.net.DeviceId;
44import org.onosproject.net.Host;
45import org.onosproject.net.HostId;
Brian O'Connorabafb502014-12-02 22:26:20 -080046import org.onosproject.net.device.DeviceService;
47import org.onosproject.net.host.HostAdminService;
48import org.onosproject.net.host.HostDescription;
49import org.onosproject.net.host.HostEvent;
50import org.onosproject.net.host.HostListener;
51import org.onosproject.net.host.HostProvider;
52import org.onosproject.net.host.HostProviderRegistry;
53import org.onosproject.net.host.HostProviderService;
54import org.onosproject.net.host.HostService;
55import org.onosproject.net.host.HostStore;
56import org.onosproject.net.host.HostStoreDelegate;
Brian O'Connorabafb502014-12-02 22:26:20 -080057import org.onosproject.net.packet.PacketService;
Brian O'Connorabafb502014-12-02 22:26:20 -080058import org.onosproject.net.provider.AbstractProviderService;
soumya3e6f05e2016-08-05 15:11:11 -070059import org.osgi.service.component.ComponentContext;
tomdb0d03f2014-08-27 16:34:15 -070060import org.slf4j.Logger;
tom5f38b3a2014-08-27 23:50:54 -070061
soumya3e6f05e2016-08-05 15:11:11 -070062import java.util.Dictionary;
Simon Huntff663742015-05-14 13:33:05 -070063import java.util.Set;
64
65import static com.google.common.base.Preconditions.checkNotNull;
Sahil Lele3a0cdd52015-07-21 14:16:31 -070066import static com.google.common.base.Preconditions.checkState;
Pier Luigi9b1d6262017-02-02 22:31:34 -080067import static org.onlab.packet.IPv6.getLinkLocalAddress;
Changhoon Yoon541ef712015-05-23 17:18:34 +090068import static org.onosproject.security.AppGuard.checkPermission;
Simon Huntffbad3b2017-05-16 15:37:51 -070069import static org.onosproject.security.AppPermission.Type.HOST_EVENT;
70import static org.onosproject.security.AppPermission.Type.HOST_READ;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070071import static org.slf4j.LoggerFactory.getLogger;
Simon Huntff663742015-05-14 13:33:05 -070072
tomdb0d03f2014-08-27 16:34:15 -070073/**
74 * Provides basic implementation of the host SB & NB APIs.
75 */
76@Component(immediate = true)
77@Service
tom202175a2014-09-19 19:00:11 -070078public class HostManager
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070079 extends AbstractListenerProviderRegistry<HostEvent, HostListener, HostProvider, HostProviderService>
tom89b63c52014-09-16 09:19:51 -070080 implements HostService, HostAdminService, HostProviderRegistry {
tomdb0d03f2014-08-27 16:34:15 -070081
tom5f38b3a2014-08-27 23:50:54 -070082 private final Logger log = getLogger(getClass());
tomdb0d03f2014-08-27 16:34:15 -070083
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070084 public static final String HOST_ID_NULL = "Host ID cannot be null";
tom5f38b3a2014-08-27 23:50:54 -070085
Sahil Lele3a0cdd52015-07-21 14:16:31 -070086 private final NetworkConfigListener networkConfigListener = new InternalNetworkConfigListener();
87
tomc78acee2014-09-24 15:16:55 -070088 private HostStoreDelegate delegate = new InternalStoreDelegate();
89
tom5bcc9462014-09-19 10:11:31 -070090 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 protected HostStore store;
tom7869ad92014-09-09 14:32:08 -070092
tom5f38b3a2014-08-27 23:50:54 -070093 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hart70da5122014-10-01 16:37:42 -070094 protected DeviceService deviceService;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected PacketService packetService;
98
Sahil Lele3a0cdd52015-07-21 14:16:31 -070099 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected NetworkConfigService networkConfigService;
101
Jonathan Hart4cb39882015-08-12 23:50:55 -0400102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected InterfaceService interfaceService;
104
Jonathan Hartfb32a6e2015-09-01 12:12:14 +0200105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 protected EdgePortService edgePortService;
107
soumya3e6f05e2016-08-05 15:11:11 -0700108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected ComponentConfigService cfgService;
110
111 @Property(name = "allowDuplicateIps", boolValue = true,
112 label = "Enable removal of duplicate ip address")
soumya3e6f05e2016-08-05 15:11:11 -0700113 private boolean allowDuplicateIps = true;
sdn94b00152016-08-30 02:12:32 -0700114
115 @Property(name = "monitorHosts", boolValue = false,
116 label = "Enable/Disable monitoring of hosts")
117 private boolean monitorHosts = false;
118
119 @Property(name = "probeRate", longValue = 30000,
120 label = "Set the probe Rate in milli seconds")
121 private long probeRate = 30000;
122
Pier Luigi9b1d6262017-02-02 22:31:34 -0800123 @Property(name = "greedyLearningIpv6", boolValue = false,
124 label = "Enable/Disable greedy learning of IPv6 link local address")
125 private boolean greedyLearningIpv6 = false;
126
Jonathan Hart70da5122014-10-01 16:37:42 -0700127 private HostMonitor monitor;
tomdb0d03f2014-08-27 16:34:15 -0700128
soumya3e6f05e2016-08-05 15:11:11 -0700129
tomdb0d03f2014-08-27 16:34:15 -0700130 @Activate
soumya3e6f05e2016-08-05 15:11:11 -0700131 public void activate(ComponentContext context) {
tomc78acee2014-09-24 15:16:55 -0700132 store.setDelegate(delegate);
tom96dfcab2014-08-28 09:26:03 -0700133 eventDispatcher.addSink(HostEvent.class, listenerRegistry);
soumya3e6f05e2016-08-05 15:11:11 -0700134 cfgService.registerProperties(getClass());
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700135 networkConfigService.addListener(networkConfigListener);
Jonathan Hartfb32a6e2015-09-01 12:12:14 +0200136 monitor = new HostMonitor(packetService, this, interfaceService, edgePortService);
sdn94b00152016-08-30 02:12:32 -0700137 monitor.setProbeRate(probeRate);
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -0700138 monitor.start();
sdn94b00152016-08-30 02:12:32 -0700139 modified(context);
140 cfgService.registerProperties(getClass());
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700141 log.info("Started");
tomdb0d03f2014-08-27 16:34:15 -0700142 }
143
sdn94b00152016-08-30 02:12:32 -0700144 @Deactivate
145 public void deactivate() {
146 store.unsetDelegate(delegate);
147 eventDispatcher.removeSink(HostEvent.class);
148 networkConfigService.removeListener(networkConfigListener);
149 cfgService.unregisterProperties(getClass(), false);
150 monitor.shutdown();
151 log.info("Stopped");
152 }
153
soumya3e6f05e2016-08-05 15:11:11 -0700154 @Modified
Simon Huntffbad3b2017-05-16 15:37:51 -0700155 public void modified(ComponentContext context) {
sdn94b00152016-08-30 02:12:32 -0700156 boolean oldValue = monitorHosts;
157 readComponentConfiguration(context);
158 if (probeRate > 0) {
159 monitor.setProbeRate(probeRate);
160 } else {
161 log.warn("probeRate cannot be lessthan 0");
162 }
163
164 if (oldValue != monitorHosts) {
165 if (monitorHosts) {
166 startMonitoring();
167 } else {
168 stopMonitoring();
169 }
170 }
171 }
172
173 /**
174 * Extracts properties from the component configuration context.
175 *
176 * @param context the component context
177 */
178 private void readComponentConfiguration(ComponentContext context) {
soumya3e6f05e2016-08-05 15:11:11 -0700179 Dictionary<?, ?> properties = context.getProperties();
180 Boolean flag;
sdn94b00152016-08-30 02:12:32 -0700181
182 flag = Tools.isPropertyEnabled(properties, "monitorHosts");
183 if (flag == null) {
184 log.info("monitorHosts is not enabled " +
185 "using current value of {}", monitorHosts);
186 } else {
187 monitorHosts = flag;
188 log.info("Configured. monitorHosts {}",
Simon Huntffbad3b2017-05-16 15:37:51 -0700189 monitorHosts ? "enabled" : "disabled");
sdn94b00152016-08-30 02:12:32 -0700190 }
191
192 Long longValue = Tools.getLongProperty(properties, "probeRate");
193 if (longValue == null || longValue == 0) {
194 log.info("probeRate is not set sing default value of {}", probeRate);
195 } else {
196 probeRate = longValue;
197 log.info("Configured. probeRate {}", probeRate);
198 }
199
soumya3e6f05e2016-08-05 15:11:11 -0700200 flag = Tools.isPropertyEnabled(properties, "allowDuplicateIps");
201 if (flag == null) {
202 log.info("Removal of duplicate ip address is not configured");
203 } else {
204 allowDuplicateIps = flag;
205 log.info("Removal of duplicate ip address is {}",
206 allowDuplicateIps ? "disabled" : "enabled");
207 }
sdn94b00152016-08-30 02:12:32 -0700208
Pier Luigi9b1d6262017-02-02 22:31:34 -0800209 flag = Tools.isPropertyEnabled(properties, "greedyLearningIpv6");
210 if (flag == null) {
211 log.info("greedy learning is not enabled " +
212 "using current value of {}", greedyLearningIpv6);
213 } else {
214 greedyLearningIpv6 = flag;
215 log.info("Configured. greedyLearningIpv6 {}",
216 greedyLearningIpv6 ? "enabled" : "disabled");
217 }
218
soumya3e6f05e2016-08-05 15:11:11 -0700219 }
220
sdn94b00152016-08-30 02:12:32 -0700221 /**
222 * Starts monitoring the hosts by IP Address.
sdn94b00152016-08-30 02:12:32 -0700223 */
224 private void startMonitoring() {
225 store.getHosts().forEach(host -> {
Simon Huntffbad3b2017-05-16 15:37:51 -0700226 host.ipAddresses().forEach(ip -> {
227 monitor.addMonitoringFor(ip);
sdn94b00152016-08-30 02:12:32 -0700228 });
229 });
230 }
231
232 /**
233 * Stops monitoring the hosts by IP Address.
sdn94b00152016-08-30 02:12:32 -0700234 */
235 private void stopMonitoring() {
236 store.getHosts().forEach(host -> {
Simon Huntffbad3b2017-05-16 15:37:51 -0700237 host.ipAddresses().forEach(ip -> {
238 monitor.stopMonitoring(ip);
sdn94b00152016-08-30 02:12:32 -0700239 });
240 });
tomdb0d03f2014-08-27 16:34:15 -0700241 }
242
243 @Override
tom5f38b3a2014-08-27 23:50:54 -0700244 protected HostProviderService createProviderService(HostProvider provider) {
Jonathan Hart70da5122014-10-01 16:37:42 -0700245 monitor.registerHostProvider(provider);
tom5f38b3a2014-08-27 23:50:54 -0700246 return new InternalHostProviderService(provider);
tomdb0d03f2014-08-27 16:34:15 -0700247 }
248
tom7869ad92014-09-09 14:32:08 -0700249 @Override
250 public int getHostCount() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900251 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700252 return store.getHostCount();
253 }
254
255 @Override
256 public Iterable<Host> getHosts() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900257 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700258 return store.getHosts();
259 }
260
261 @Override
262 public Host getHost(HostId hostId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900263 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700264 checkNotNull(hostId, HOST_ID_NULL);
265 return store.getHost(hostId);
266 }
267
268 @Override
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700269 public Set<Host> getHostsByVlan(VlanId vlanId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900270 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700271 return store.getHosts(vlanId);
272 }
273
274 @Override
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700275 public Set<Host> getHostsByMac(MacAddress mac) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900276 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700277 checkNotNull(mac, "MAC address cannot be null");
278 return store.getHosts(mac);
279 }
280
281 @Override
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700282 public Set<Host> getHostsByIp(IpAddress ip) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900283 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700284 checkNotNull(ip, "IP address cannot be null");
285 return store.getHosts(ip);
286 }
287
288 @Override
289 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900290 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700291 checkNotNull(connectPoint, "Connection point cannot be null");
292 return store.getConnectedHosts(connectPoint);
293 }
294
295 @Override
296 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900297 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700298 checkNotNull(deviceId, "Device ID cannot be null");
299 return store.getConnectedHosts(deviceId);
300 }
301
302 @Override
Jonathan Hartac60c082014-09-23 08:55:17 -0700303 public void startMonitoringIp(IpAddress ip) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900304 checkPermission(HOST_EVENT);
Jonathan Hart70da5122014-10-01 16:37:42 -0700305 monitor.addMonitoringFor(ip);
Jonathan Hartfca736c2014-09-19 17:26:59 -0700306 }
307
308 @Override
Jonathan Hartac60c082014-09-23 08:55:17 -0700309 public void stopMonitoringIp(IpAddress ip) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900310 checkPermission(HOST_EVENT);
Jonathan Hart70da5122014-10-01 16:37:42 -0700311 monitor.stopMonitoring(ip);
Jonathan Hartac60c082014-09-23 08:55:17 -0700312 }
313
314 @Override
315 public void requestMac(IpAddress ip) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700316 // FIXME!!!! Auto-generated method stub
tom7869ad92014-09-09 14:32:08 -0700317 }
318
tom89b63c52014-09-16 09:19:51 -0700319 @Override
320 public void removeHost(HostId hostId) {
321 checkNotNull(hostId, HOST_ID_NULL);
Charles Chan009c3082015-11-10 14:18:04 -0800322 store.removeHost(hostId);
tom89b63c52014-09-16 09:19:51 -0700323 }
324
tomdb0d03f2014-08-27 16:34:15 -0700325 // Personalized host provider service issued to the supplied provider.
tom7869ad92014-09-09 14:32:08 -0700326 private class InternalHostProviderService
327 extends AbstractProviderService<HostProvider>
tomdb0d03f2014-08-27 16:34:15 -0700328 implements HostProviderService {
tomcfde0622014-09-09 11:02:42 -0700329 InternalHostProviderService(HostProvider provider) {
tomdb0d03f2014-08-27 16:34:15 -0700330 super(provider);
331 }
332
333 @Override
Brian O'Connorf107bd72015-09-21 15:31:03 -0700334 public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) {
tom7869ad92014-09-09 14:32:08 -0700335 checkNotNull(hostId, HOST_ID_NULL);
336 checkValidity();
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700337 hostDescription = validateHost(hostDescription, hostId);
soumya3e6f05e2016-08-05 15:11:11 -0700338
339 if (!allowDuplicateIps) {
340 removeDuplicates(hostId, hostDescription);
341 }
Charles Chan009c3082015-11-10 14:18:04 -0800342 store.createOrUpdateHost(provider().id(), hostId,
soumya3e6f05e2016-08-05 15:11:11 -0700343 hostDescription, replaceIps);
sdn94b00152016-08-30 02:12:32 -0700344
345 if (monitorHosts) {
346 hostDescription.ipAddress().forEach(ip -> {
347 monitor.addMonitoringFor(ip);
348 });
349 }
Pier Luigi9b1d6262017-02-02 22:31:34 -0800350
351 // Greedy learning of IPv6 host. We have to disable the greedy
352 // learning of configured hosts. Validate hosts each time will
Charles Chan82fac582017-09-12 12:09:22 -0700353 // overwrite the learnt information with the configured information.
Pier Luigi9b1d6262017-02-02 22:31:34 -0800354 if (greedyLearningIpv6) {
355 // Auto-generation of the IPv6 link local address
356 // using the mac address
357 Ip6Address targetIp6Address = Ip6Address.valueOf(
358 getLinkLocalAddress(hostId.mac().toBytes())
359 );
360 // If we already know this guy we don't need to do other
361 if (!hostDescription.ipAddress().contains(targetIp6Address)) {
362 Host host = store.getHost(hostId);
363 // Configured host, skip it.
364 if (host != null && host.configured()) {
365 return;
366 }
367 // Host does not exist in the store or the target is not known
368 if ((host == null || !host.ipAddresses().contains(targetIp6Address))) {
Charles Chan82fac582017-09-12 12:09:22 -0700369 // Use DAD to probe if interface MAC is not specified
370 MacAddress probeMac = interfaceService.getInterfacesByPort(hostDescription.location())
371 .stream().map(Interface::mac).findFirst().orElse(MacAddress.ONOS);
372 Ip6Address probeIp = !probeMac.equals(MacAddress.ONOS) ?
373 Ip6Address.valueOf(getLinkLocalAddress(probeMac.toBytes())) :
374 Ip6Address.ZERO;
Pier Luigi9b1d6262017-02-02 22:31:34 -0800375 // We send a probe using the monitoring service
376 monitor.sendProbe(
377 hostDescription.location(),
378 targetIp6Address,
Charles Chan82fac582017-09-12 12:09:22 -0700379 probeIp,
380 probeMac,
Pier Luigi9b1d6262017-02-02 22:31:34 -0800381 hostId.vlanId()
382 );
383 }
384 }
385 }
tomdb0d03f2014-08-27 16:34:15 -0700386 }
387
soumya3e6f05e2016-08-05 15:11:11 -0700388 // When a new IP is detected, remove that IP on other hosts if it exists
389 public void removeDuplicates(HostId hostId, HostDescription desc) {
390 desc.ipAddress().forEach(ip -> {
391 Set<Host> allHosts = store.getHosts(ip);
392 allHosts.forEach(eachHost -> {
393 if (!(eachHost.id().equals(hostId))) {
394 log.info("Duplicate ip {} found on host {} and {}", ip,
395 hostId.toString(), eachHost.id().toString());
396 store.removeIp(eachHost.id(), ip);
397 }
398 });
399 });
Jonathan Hart38feb6e2016-08-29 22:54:16 +0000400 }
401
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700402 // returns a HostDescription made from the union of the BasicHostConfig
403 // annotations if it exists
404 private HostDescription validateHost(HostDescription hostDescription, HostId hostId) {
405 BasicHostConfig cfg = networkConfigService.getConfig(hostId, BasicHostConfig.class);
406 checkState(cfg == null || cfg.isAllowed(), "Host {} is not allowed", hostId);
Ayaka Koshibe5373e762015-08-06 12:31:44 -0700407
408 return BasicHostOperator.combine(cfg, hostDescription);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700409 }
410
tomdb0d03f2014-08-27 16:34:15 -0700411 @Override
tom7869ad92014-09-09 14:32:08 -0700412 public void hostVanished(HostId hostId) {
413 checkNotNull(hostId, HOST_ID_NULL);
414 checkValidity();
sdn94b00152016-08-30 02:12:32 -0700415 Host host = store.getHost(hostId);
Charles Chan29ecdee2017-02-22 18:46:56 -0800416
Charles Chan888e20a2017-05-01 15:44:23 -0700417 if (!allowedToChange(hostId)) {
418 log.info("Request to remove {} is ignored due to provider mismatch", hostId);
Charles Chan29ecdee2017-02-22 18:46:56 -0800419 return;
420 }
421
sdn94b00152016-08-30 02:12:32 -0700422 if (monitorHosts) {
423 host.ipAddresses().forEach(ip -> {
424 monitor.stopMonitoring(ip);
425 });
426 }
Charles Chan009c3082015-11-10 14:18:04 -0800427 store.removeHost(hostId);
tomdb0d03f2014-08-27 16:34:15 -0700428 }
samanwita palc40e5ed2015-09-24 11:01:51 -0700429
430 @Override
431 public void removeIpFromHost(HostId hostId, IpAddress ipAddress) {
432 checkNotNull(hostId, HOST_ID_NULL);
433 checkValidity();
Charles Chan888e20a2017-05-01 15:44:23 -0700434
435 if (!allowedToChange(hostId)) {
436 log.info("Request to remove {} from {} is ignored due to provider mismatch",
437 ipAddress, hostId);
438 return;
439 }
440
Charles Chan009c3082015-11-10 14:18:04 -0800441 store.removeIp(hostId, ipAddress);
samanwita palc40e5ed2015-09-24 11:01:51 -0700442 }
Charles Chan888e20a2017-05-01 15:44:23 -0700443
444 @Override
445 public void removeLocationFromHost(HostId hostId, HostLocation location) {
446 checkNotNull(hostId, HOST_ID_NULL);
447 checkValidity();
448
449 if (!allowedToChange(hostId)) {
450 log.info("Request to remove {} from {} is ignored due to provider mismatch",
451 location, hostId);
452 return;
453 }
454
455 store.removeLocation(hostId, location);
456 }
457
Charles Chan35a32322017-08-14 11:42:11 -0700458 @Override
Charles Chan47933752017-11-30 15:37:50 -0800459 public MacAddress addPendingHostLocation(HostId hostId, ConnectPoint connectPoint, ProbeMode probeMode) {
460 return store.addPendingHostLocation(hostId, connectPoint, probeMode);
Charles Chan35a32322017-08-14 11:42:11 -0700461 }
462
463 @Override
464 public void removePendingHostLocation(MacAddress probeMac) {
465 store.removePendingHostLocation(probeMac);
466 }
467
Charles Chand0c147a2017-09-14 14:00:10 -0700468 /**
469 * Providers should only be able to remove a host that is provided by itself,
470 * or a host that is not configured.
471 */
Charles Chan888e20a2017-05-01 15:44:23 -0700472 private boolean allowedToChange(HostId hostId) {
Charles Chan888e20a2017-05-01 15:44:23 -0700473 Host host = store.getHost(hostId);
Charles Chand0c147a2017-09-14 14:00:10 -0700474 return host == null || !host.configured() || host.providerId().equals(provider().id());
Charles Chan888e20a2017-05-01 15:44:23 -0700475 }
tomdb0d03f2014-08-27 16:34:15 -0700476 }
tom7869ad92014-09-09 14:32:08 -0700477
tomc78acee2014-09-24 15:16:55 -0700478 // Store delegate to re-post events emitted from the store.
479 private class InternalStoreDelegate implements HostStoreDelegate {
480 @Override
481 public void notify(HostEvent event) {
482 post(event);
483 }
484 }
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700485
486 // listens for NetworkConfigEvents of type BasicHostConfig and removes
487 // links that the config does not allow
488 private class InternalNetworkConfigListener implements NetworkConfigListener {
489 @Override
Simon Huntffbad3b2017-05-16 15:37:51 -0700490 public boolean isRelevant(NetworkConfigEvent event) {
491 return (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED
492 || event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)
493 && (event.configClass().equals(BasicHostConfig.class));
494 }
495
496 @Override
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700497 public void event(NetworkConfigEvent event) {
Simon Huntffbad3b2017-05-16 15:37:51 -0700498 log.debug("Detected host network config event {}", event.type());
499 HostEvent he = null;
500
501 HostId hostId = (HostId) event.subject();
502 BasicHostConfig cfg =
503 networkConfigService.getConfig(hostId, BasicHostConfig.class);
504
505 if (!isAllowed(cfg)) {
506 kickOutBadHost(hostId);
507 } else {
508 Host host = getHost(hostId);
509 HostDescription desc =
510 (host == null) ? null : BasicHostOperator.descriptionOf(host);
511 desc = BasicHostOperator.combine(cfg, desc);
512 if (desc != null) {
513 he = store.createOrUpdateHost(host.providerId(), hostId, desc, false);
514 }
515 }
516
517 if (he != null) {
518 post(he);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700519 }
520 }
521 }
522
Simon Huntffbad3b2017-05-16 15:37:51 -0700523 // by default allowed, otherwise check flag
524 private boolean isAllowed(BasicHostConfig cfg) {
525 return (cfg == null || cfg.isAllowed());
526 }
527
528 // removes the specified host, if it exists
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700529 private void kickOutBadHost(HostId hostId) {
Simon Huntffbad3b2017-05-16 15:37:51 -0700530 Host badHost = getHost(hostId);
531 if (badHost != null) {
532 removeHost(hostId);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700533 }
534 }
tomdb0d03f2014-08-27 16:34:15 -0700535}