blob: 3378b82441c1e3bbb2f924620f2fb8d09081b5eb [file] [log] [blame]
Hyunsun Moon44aac662017-02-18 02:07:01 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Hyunsun Moon44aac662017-02-18 02:07:01 +09003 *
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.openstacknetworking.impl;
17
18import com.google.common.collect.ImmutableSet;
Jian Liea1b9662018-03-02 18:07:32 +090019import com.google.common.collect.Maps;
Hyunsun Moon44aac662017-02-18 02:07:01 +090020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.apache.felix.scr.annotations.Service;
26import org.onlab.packet.IpAddress;
27import org.onlab.packet.MacAddress;
28import org.onlab.util.Tools;
29import org.onosproject.event.ListenerRegistry;
30import org.onosproject.net.Host;
31import org.onosproject.net.HostId;
32import org.onosproject.net.host.HostEvent;
33import org.onosproject.net.host.HostListener;
34import org.onosproject.net.host.HostService;
35import org.onosproject.openstacknetworking.api.InstancePort;
36import org.onosproject.openstacknetworking.api.InstancePortEvent;
Jian Liea1b9662018-03-02 18:07:32 +090037import org.onosproject.openstacknetworking.api.InstancePortEvent.Type;
Hyunsun Moon44aac662017-02-18 02:07:01 +090038import org.onosproject.openstacknetworking.api.InstancePortListener;
39import org.onosproject.openstacknetworking.api.InstancePortService;
40import org.slf4j.Logger;
41
Jian Liea1b9662018-03-02 18:07:32 +090042import java.util.Map;
Hyunsun Moon44aac662017-02-18 02:07:01 +090043import java.util.Set;
44import java.util.stream.Collectors;
45
Jian Li24ec59f2018-05-23 19:01:25 +090046import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_ENDED;
47import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_STARTED;
Hyunsun Moon44aac662017-02-18 02:07:01 +090048import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_PORT_DETECTED;
49import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_PORT_UPDATED;
50import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_PORT_VANISHED;
51import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_NETWORK_ID;
52import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_PORT_ID;
53import static org.slf4j.LoggerFactory.getLogger;
54
55/**
56 * Provides implementation of administering and interfacing host based instance ports.
57 * It also provides instance port events for the hosts mapped to OpenStack VM interface.
58 */
59@Service
60@Component(immediate = true)
61public class HostBasedInstancePortManager
62 extends ListenerRegistry<InstancePortEvent, InstancePortListener>
63 implements InstancePortService {
64
65 protected final Logger log = getLogger(getClass());
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected HostService hostService;
69
Jian Li24ec59f2018-05-23 19:01:25 +090070 private final InternalHostListener hostListener = new InternalHostListener();
Hyunsun Moon44aac662017-02-18 02:07:01 +090071
72 @Activate
73 protected void activate() {
74 hostService.addListener(hostListener);
75 log.info("Started");
76 }
77
78 @Deactivate
79 protected void deactivate() {
80 hostService.removeListener(hostListener);
81 log.info("Stopped");
82 }
83
84 @Override
85 public InstancePort instancePort(MacAddress macAddress) {
86 Host host = hostService.getHost(HostId.hostId(macAddress));
87 if (host == null || !isValidHost(host)) {
88 return null;
89 }
90 return HostBasedInstancePort.of(host);
91 }
92
93 @Override
94 public InstancePort instancePort(IpAddress ipAddress, String osNetId) {
95 return Tools.stream(hostService.getHosts()).filter(this::isValidHost)
96 .map(HostBasedInstancePort::of)
97 .filter(instPort -> instPort.networkId().equals(osNetId))
98 .filter(instPort -> instPort.ipAddress().equals(ipAddress))
99 .findAny().orElse(null);
100 }
101
102 @Override
103 public InstancePort instancePort(String osPortId) {
104 return Tools.stream(hostService.getHosts()).filter(this::isValidHost)
105 .map(HostBasedInstancePort::of)
106 .filter(instPort -> instPort.portId().equals(osPortId))
107 .findAny().orElse(null);
108 }
109
110 @Override
111 public Set<InstancePort> instancePorts() {
112 Set<InstancePort> instPors = Tools.stream(hostService.getHosts())
113 .filter(this::isValidHost)
114 .map(HostBasedInstancePort::of)
115 .collect(Collectors.toSet());
116 return ImmutableSet.copyOf(instPors);
117 }
118
119 @Override
120 public Set<InstancePort> instancePorts(String osNetId) {
121 Set<InstancePort> instPors = Tools.stream(hostService.getHosts())
122 .filter(this::isValidHost)
123 .map(HostBasedInstancePort::of)
124 .filter(instPort -> instPort.networkId().equals(osNetId))
125 .collect(Collectors.toSet());
126 return ImmutableSet.copyOf(instPors);
127 }
128
Jian Li24ec59f2018-05-23 19:01:25 +0900129 @Override
130 public void migrationPortAdded(InstancePort port) {
131 hostListener.processEvent(OPENSTACK_INSTANCE_MIGRATION_STARTED, port);
132 }
133
134 @Override
135 public void migrationPortRemoved(InstancePort port) {
136 hostListener.processEvent(OPENSTACK_INSTANCE_MIGRATION_ENDED, port);
137 }
138
Hyunsun Moon44aac662017-02-18 02:07:01 +0900139 private boolean isValidHost(Host host) {
140 return !host.ipAddresses().isEmpty() &&
141 host.annotations().value(ANNOTATION_NETWORK_ID) != null &&
142 host.annotations().value(ANNOTATION_PORT_ID) != null;
143 }
144
Jian Liea1b9662018-03-02 18:07:32 +0900145 /**
146 * An internal listener that listens host event generated by HostLocationTracker
147 * in DistributedHostStore. The role of this listener is to convert host event
148 * to instance port event and post to the subscribers that have interested on
149 * this type of event.
150 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900151 private class InternalHostListener implements HostListener {
152
153 @Override
154 public boolean isRelevant(HostEvent event) {
155 Host host = event.subject();
156 if (!isValidHost(host)) {
157 log.debug("Invalid host detected, ignore it {}", host);
158 return false;
159 }
160 return true;
161 }
162
163 @Override
164 public void event(HostEvent event) {
165 InstancePort instPort = HostBasedInstancePort.of(event.subject());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900166 switch (event.type()) {
167 case HOST_UPDATED:
Jian Liea1b9662018-03-02 18:07:32 +0900168 processEvent(OPENSTACK_INSTANCE_PORT_UPDATED, instPort);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900169 break;
170 case HOST_ADDED:
Jian Liea1b9662018-03-02 18:07:32 +0900171 processEvent(OPENSTACK_INSTANCE_PORT_DETECTED, instPort);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900172 break;
173 case HOST_REMOVED:
Jian Liea1b9662018-03-02 18:07:32 +0900174 processEvent(OPENSTACK_INSTANCE_PORT_VANISHED, instPort);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900175 break;
176 default:
177 break;
178 }
179 }
Jian Liea1b9662018-03-02 18:07:32 +0900180
181 private void processEvent(Type type, InstancePort port) {
182 Map<Type, String> eventMap = Maps.newConcurrentMap();
183 eventMap.put(OPENSTACK_INSTANCE_PORT_UPDATED, "updated");
184 eventMap.put(OPENSTACK_INSTANCE_PORT_DETECTED, "detected");
185 eventMap.put(OPENSTACK_INSTANCE_PORT_VANISHED, "disabled");
Jian Li24ec59f2018-05-23 19:01:25 +0900186 eventMap.put(OPENSTACK_INSTANCE_MIGRATION_STARTED, "detected");
187 eventMap.put(OPENSTACK_INSTANCE_MIGRATION_ENDED, "disabled");
Jian Liea1b9662018-03-02 18:07:32 +0900188
189 InstancePortEvent instPortEvent = new InstancePortEvent(type, port);
190 log.debug("Instance port is {}: {}", eventMap.get(type), port);
191 process(instPortEvent);
192 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900193 }
194}