blob: 24f650d489955f43d96efdd2b6b8198ed1dfd83e [file] [log] [blame]
Hyunsun Moone9d75992015-09-15 22:39:16 -07001/*
Brian O'Connor8e57fd52016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Hyunsun Moone9d75992015-09-15 22:39:16 -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 */
Hyunsun Moonf9480202016-04-14 16:13:42 -070016package org.onosproject.cordvtn.impl;
Hyunsun Moone9d75992015-09-15 22:39:16 -070017
Hyunsun Moon8b530e32016-02-03 00:11:11 -080018import com.google.common.collect.Lists;
Hyunsun Moonb5f92e52016-02-17 15:02:06 -080019import com.google.common.collect.Maps;
Hyunsun Moon7dca9b32015-10-08 22:25:30 -070020import com.google.common.collect.Sets;
Hyunsun Moone9d75992015-09-15 22:39:16 -070021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.apache.felix.scr.annotations.Service;
Hyunsun Moon022272f2016-01-11 15:30:42 -080027import org.onlab.packet.Ethernet;
Hyunsun Moon8b530e32016-02-03 00:11:11 -080028import org.onlab.packet.Ip4Address;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080029import org.onlab.packet.IpAddress;
Hyunsun Mooncb799442016-01-15 20:03:18 -080030import org.onlab.packet.MacAddress;
31import org.onlab.packet.VlanId;
Hyunsun Moonf9480202016-04-14 16:13:42 -070032import org.onosproject.cordvtn.api.CordService;
33import org.onosproject.cordvtn.api.CordServiceId;
34import org.onosproject.cordvtn.api.CordVtnConfig;
35import org.onosproject.cordvtn.api.CordVtnNode;
36import org.onosproject.cordvtn.api.CordVtnService;
Hyunsun Moon7dca9b32015-10-08 22:25:30 -070037import org.onosproject.core.ApplicationId;
Hyunsun Moone9d75992015-09-15 22:39:16 -070038import org.onosproject.core.CoreService;
Hyunsun Moon8b530e32016-02-03 00:11:11 -080039import org.onosproject.dhcp.DhcpService;
Hyunsun Moonba290072015-12-16 20:53:23 -080040import org.onosproject.mastership.MastershipService;
Hyunsun Mooncb799442016-01-15 20:03:18 -080041import org.onosproject.net.ConnectPoint;
Hyunsun Moon169f9382015-10-28 20:28:16 -070042import org.onosproject.net.DefaultAnnotations;
Hyunsun Moone9d75992015-09-15 22:39:16 -070043import org.onosproject.net.Host;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080044import org.onosproject.net.HostId;
Hyunsun Mooncb799442016-01-15 20:03:18 -080045import org.onosproject.net.HostLocation;
Hyunsun Moon4edb0172015-11-07 22:08:43 -080046import org.onosproject.net.Port;
Hyunsun Moon3fc17f72016-01-24 21:47:06 -080047import org.onosproject.net.config.ConfigFactory;
48import org.onosproject.net.config.NetworkConfigEvent;
49import org.onosproject.net.config.NetworkConfigListener;
50import org.onosproject.net.config.NetworkConfigRegistry;
51import org.onosproject.net.config.NetworkConfigService;
52import org.onosproject.net.config.basics.SubjectFactories;
Hyunsun Moone9d75992015-09-15 22:39:16 -070053import org.onosproject.net.device.DeviceService;
Hyunsun Moon169f9382015-10-28 20:28:16 -070054import org.onosproject.net.driver.DriverService;
Hyunsun Moonba290072015-12-16 20:53:23 -080055import org.onosproject.net.flow.FlowRuleService;
56import org.onosproject.net.group.GroupService;
Hyunsun Mooncb799442016-01-15 20:03:18 -080057import org.onosproject.net.host.DefaultHostDescription;
58import org.onosproject.net.host.HostDescription;
Hyunsun Moone9d75992015-09-15 22:39:16 -070059import org.onosproject.net.host.HostEvent;
60import org.onosproject.net.host.HostListener;
Hyunsun Mooncb799442016-01-15 20:03:18 -080061import org.onosproject.net.host.HostProvider;
62import org.onosproject.net.host.HostProviderRegistry;
63import org.onosproject.net.host.HostProviderService;
Hyunsun Moone9d75992015-09-15 22:39:16 -070064import org.onosproject.net.host.HostService;
Hyunsun Moon022272f2016-01-11 15:30:42 -080065import org.onosproject.net.packet.PacketContext;
66import org.onosproject.net.packet.PacketProcessor;
67import org.onosproject.net.packet.PacketService;
Hyunsun Mooncb799442016-01-15 20:03:18 -080068import org.onosproject.net.provider.AbstractProvider;
69import org.onosproject.net.provider.ProviderId;
Hyunsun Moon61e79ee2016-04-14 19:04:23 -070070
71import org.openstack4j.api.OSClient;
72import org.openstack4j.api.exceptions.AuthenticationException;
73import org.openstack4j.model.identity.Access;
74import org.openstack4j.model.network.Network;
75import org.openstack4j.model.network.Subnet;
76import org.openstack4j.openstack.OSFactory;
Hyunsun Moone9d75992015-09-15 22:39:16 -070077import org.slf4j.Logger;
78
Hyunsun Moon8b530e32016-02-03 00:11:11 -080079import java.util.List;
Hyunsun Moon7dca9b32015-10-08 22:25:30 -070080import java.util.Map;
Hyunsun Moond05b32e2016-03-02 19:27:26 -080081import java.util.Objects;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080082import java.util.Set;
Hyunsun Moone9d75992015-09-15 22:39:16 -070083import java.util.concurrent.ExecutorService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080084import java.util.stream.Collectors;
Hyunsun Moond05b32e2016-03-02 19:27:26 -080085import java.util.stream.StreamSupport;
Hyunsun Moone9d75992015-09-15 22:39:16 -070086
Hyunsun Moon7dca9b32015-10-08 22:25:30 -070087import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moon3fc17f72016-01-24 21:47:06 -080088import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
Hyunsun Moone9d75992015-09-15 22:39:16 -070089import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moone9d75992015-09-15 22:39:16 -070090import static org.slf4j.LoggerFactory.getLogger;
91
92/**
Hyunsun Moon05f528a2015-11-04 17:34:35 -080093 * Provisions virtual tenant networks with service chaining capability
94 * in OpenStack environment.
Hyunsun Moone9d75992015-09-15 22:39:16 -070095 */
96@Component(immediate = true)
97@Service
Hyunsun Mooncb799442016-01-15 20:03:18 -080098public class CordVtn extends AbstractProvider implements CordVtnService, HostProvider {
Hyunsun Moone9d75992015-09-15 22:39:16 -070099
100 protected final Logger log = getLogger(getClass());
101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected CoreService coreService;
104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800106 protected NetworkConfigRegistry configRegistry;
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected NetworkConfigService configService;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Mooncb799442016-01-15 20:03:18 -0800112 protected HostProviderRegistry hostProviderRegistry;
Hyunsun Moone9d75992015-09-15 22:39:16 -0700113
114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moone9d75992015-09-15 22:39:16 -0700115 protected DeviceService deviceService;
116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected HostService hostService;
119
Hyunsun Moon7dca9b32015-10-08 22:25:30 -0700120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon169f9382015-10-28 20:28:16 -0700121 protected DriverService driverService;
122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonba290072015-12-16 20:53:23 -0800124 protected FlowRuleService flowRuleService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800125
126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon022272f2016-01-11 15:30:42 -0800127 protected PacketService packetService;
128
129 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonba290072015-12-16 20:53:23 -0800130 protected MastershipService mastershipService;
131
132 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
133 protected GroupService groupService;
134
135 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon8b530e32016-02-03 00:11:11 -0800136 protected DhcpService dhcpService;
137
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800138 private final ConfigFactory configFactory =
139 new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
140 @Override
141 public CordVtnConfig createConfig() {
142 return new CordVtnConfig();
143 }
144 };
145
Hyunsun Mooncb799442016-01-15 20:03:18 -0800146 private static final String DEFAULT_TUNNEL = "vxlan";
147 private static final String SERVICE_ID = "serviceId";
Hyunsun Moon01556a52016-02-12 12:48:47 -0800148 private static final String OPENSTACK_PORT_ID = "openstackPortId";
149 private static final String DATA_PLANE_IP = "dataPlaneIp";
150 private static final String DATA_PLANE_INTF = "dataPlaneIntf";
151 private static final String S_TAG = "stag";
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800152 private static final String VSG_HOST_ID = "vsgHostId";
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800153 private static final String CREATED_TIME = "createdTime";
Hyunsun Moon01556a52016-02-12 12:48:47 -0800154
155 private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
Hyunsun Mooncb799442016-01-15 20:03:18 -0800156
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800157 private final ExecutorService eventExecutor =
158 newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "event-handler"));
Hyunsun Moone9d75992015-09-15 22:39:16 -0700159
Hyunsun Moon022272f2016-01-11 15:30:42 -0800160 private final PacketProcessor packetProcessor = new InternalPacketProcessor();
Hyunsun Mooncb799442016-01-15 20:03:18 -0800161 private final HostListener hostListener = new InternalHostListener();
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800162 private final NetworkConfigListener configListener = new InternalConfigListener();
Hyunsun Moon9661d642015-09-23 13:24:35 -0700163
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800164 private ApplicationId appId;
Hyunsun Mooncb799442016-01-15 20:03:18 -0800165 private HostProviderService hostProvider;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800166 private CordVtnRuleInstaller ruleInstaller;
Hyunsun Moon022272f2016-01-11 15:30:42 -0800167 private CordVtnArpProxy arpProxy;
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700168
169 private volatile Access osAccess = null;
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800170 private volatile MacAddress privateGatewayMac = MacAddress.NONE;
Hyunsun Moon4edb0172015-11-07 22:08:43 -0800171
Hyunsun Mooncb799442016-01-15 20:03:18 -0800172 /**
173 * Creates an cordvtn host location provider.
174 */
175 public CordVtn() {
176 super(new ProviderId("host", CORDVTN_APP_ID));
Hyunsun Moon4edb0172015-11-07 22:08:43 -0800177 }
Hyunsun Moone9d75992015-09-15 22:39:16 -0700178
179 @Activate
180 protected void activate() {
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800181 appId = coreService.registerApplication("org.onosproject.cordvtn");
Hyunsun Moonba290072015-12-16 20:53:23 -0800182 ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService,
183 deviceService,
184 driverService,
185 groupService,
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800186 configRegistry,
Hyunsun Moonba290072015-12-16 20:53:23 -0800187 DEFAULT_TUNNEL);
188
Hyunsun Moonb6febbe2016-02-12 15:59:53 -0800189 arpProxy = new CordVtnArpProxy(appId, packetService, hostService);
Hyunsun Moon022272f2016-01-11 15:30:42 -0800190 packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
191 arpProxy.requestPacket();
192
Hyunsun Moone9d75992015-09-15 22:39:16 -0700193 hostService.addListener(hostListener);
Hyunsun Mooncb799442016-01-15 20:03:18 -0800194 hostProvider = hostProviderRegistry.register(this);
Hyunsun Moon9661d642015-09-23 13:24:35 -0700195
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800196 configRegistry.registerConfigFactory(configFactory);
197 configService.addListener(configListener);
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800198
Hyunsun Moone9d75992015-09-15 22:39:16 -0700199 log.info("Started");
200 }
201
202 @Deactivate
203 protected void deactivate() {
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800204 hostProviderRegistry.unregister(this);
Hyunsun Moone9d75992015-09-15 22:39:16 -0700205 hostService.removeListener(hostListener);
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800206
Hyunsun Moon022272f2016-01-11 15:30:42 -0800207 packetService.removeProcessor(packetProcessor);
Hyunsun Moon9661d642015-09-23 13:24:35 -0700208
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800209 configRegistry.unregisterConfigFactory(configFactory);
210 configService.removeListener(configListener);
Hyunsun Moon9661d642015-09-23 13:24:35 -0700211
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800212 eventExecutor.shutdown();
Hyunsun Moone9d75992015-09-15 22:39:16 -0700213 log.info("Stopped");
214 }
215
216 @Override
Hyunsun Mooncb799442016-01-15 20:03:18 -0800217 public void triggerProbe(Host host) {
218 /*
219 * Note: In CORD deployment, we assume that all hosts are configured.
220 * Therefore no probe is required.
221 */
Hyunsun Moonde372572016-01-14 03:42:47 -0800222 }
223
224 @Override
Hyunsun Moon5f7ed8a2016-02-10 17:02:37 -0800225 public void createServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId,
226 boolean isBidirectional) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800227 CordService tService = getCordService(tServiceId);
228 CordService pService = getCordService(pServiceId);
Hyunsun Moon97eaf502015-12-07 14:06:28 -0800229
Hyunsun Moonba290072015-12-16 20:53:23 -0800230 if (tService == null || pService == null) {
231 log.error("Failed to create CordService for {}", tServiceId.id());
232 return;
233 }
234
Hyunsun Mooncb799442016-01-15 20:03:18 -0800235 log.info("Service dependency from {} to {} created.", tService.id().id(), pService.id().id());
Hyunsun Moon5f7ed8a2016-02-10 17:02:37 -0800236 ruleInstaller.populateServiceDependencyRules(tService, pService, isBidirectional);
Hyunsun Moon9274aaf2015-12-04 11:35:25 -0800237 }
238
239 @Override
Hyunsun Moonba290072015-12-16 20:53:23 -0800240 public void removeServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId) {
241 CordService tService = getCordService(tServiceId);
242 CordService pService = getCordService(pServiceId);
Hyunsun Moon97eaf502015-12-07 14:06:28 -0800243
Hyunsun Moonba290072015-12-16 20:53:23 -0800244 if (tService == null || pService == null) {
245 log.error("Failed to create CordService for {}", tServiceId.id());
246 return;
247 }
248
Hyunsun Mooncb799442016-01-15 20:03:18 -0800249 log.info("Service dependency from {} to {} removed.", tService.id().id(), pService.id().id());
Hyunsun Moonba290072015-12-16 20:53:23 -0800250 ruleInstaller.removeServiceDependencyRules(tService, pService);
Hyunsun Moon9274aaf2015-12-04 11:35:25 -0800251 }
252
Hyunsun Mooncb799442016-01-15 20:03:18 -0800253 @Override
254 public void addServiceVm(CordVtnNode node, ConnectPoint connectPoint) {
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700255 checkNotNull(osAccess, "OpenStack access is not set");
256
257 OSClient osClient = OSFactory.clientFromAccess(osAccess);
Hyunsun Mooncb799442016-01-15 20:03:18 -0800258 Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700259 org.openstack4j.model.network.Port osPort = osClient.networking().port().list()
260 .stream()
261 .filter(p -> p.getId().contains(getPortName(port).substring(3)))
262 .findFirst().orElse(null);
263 if (osPort == null) {
264 log.warn("Failed to get OpenStack port for {}", getPortName(port));
Hyunsun Moon4edb0172015-11-07 22:08:43 -0800265 return;
266 }
267
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700268 MacAddress mac = MacAddress.valueOf(osPort.getMacAddress());
Hyunsun Mooncb799442016-01-15 20:03:18 -0800269 HostId hostId = HostId.hostId(mac);
Hyunsun Moon4edb0172015-11-07 22:08:43 -0800270
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800271 Host existingHost = hostService.getHost(hostId);
272 if (existingHost != null) {
273 String serviceId = existingHost.annotations().value(SERVICE_ID);
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700274 if (serviceId == null || !serviceId.equals(osPort.getNetworkId())) {
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800275 // this host is not injected by cordvtn or a stale host, remove it
276 hostProvider.hostVanished(existingHost.id());
Hyunsun Moon8b530e32016-02-03 00:11:11 -0800277 }
Hyunsun Moon4edb0172015-11-07 22:08:43 -0800278 }
279
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800280 // Included CREATED_TIME to annotation intentionally to trigger HOST_UPDATED
281 // event so that the flow rule population for this host can happen.
282 // This ensures refreshing data plane by pushing network config always make
283 // the data plane synced.
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700284 Set<IpAddress> fixedIps = osPort.getFixedIps().stream()
285 .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
286 .collect(Collectors.toSet());
287
Hyunsun Moon01556a52016-02-12 12:48:47 -0800288 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700289 .set(SERVICE_ID, osPort.getNetworkId())
290 .set(OPENSTACK_PORT_ID, osPort.getId())
Hyunsun Moon01556a52016-02-12 12:48:47 -0800291 .set(DATA_PLANE_IP, node.dpIp().ip().toString())
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800292 .set(DATA_PLANE_INTF, node.dpIntf())
293 .set(CREATED_TIME, String.valueOf(System.currentTimeMillis()));
Hyunsun Moon01556a52016-02-12 12:48:47 -0800294
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700295 String serviceVlan = getServiceVlan(osPort);
Hyunsun Moon01556a52016-02-12 12:48:47 -0800296 if (serviceVlan != null) {
297 annotations.set(S_TAG, serviceVlan);
298 }
Hyunsun Mooncb799442016-01-15 20:03:18 -0800299
300 HostDescription hostDesc = new DefaultHostDescription(
301 mac,
302 VlanId.NONE,
303 new HostLocation(connectPoint, System.currentTimeMillis()),
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700304 fixedIps,
Hyunsun Moon01556a52016-02-12 12:48:47 -0800305 annotations.build());
Hyunsun Mooncb799442016-01-15 20:03:18 -0800306
307 hostProvider.hostDetected(hostId, hostDesc, false);
Hyunsun Moon4edb0172015-11-07 22:08:43 -0800308 }
309
Hyunsun Mooncb799442016-01-15 20:03:18 -0800310 @Override
311 public void removeServiceVm(ConnectPoint connectPoint) {
Hyunsun Moon97c74192016-02-17 19:00:50 -0800312 hostService.getConnectedHosts(connectPoint)
Hyunsun Moonba290072015-12-16 20:53:23 -0800313 .stream()
Hyunsun Moon97c74192016-02-17 19:00:50 -0800314 .forEach(host -> hostProvider.hostVanished(host.id()));
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800315 }
316
Hyunsun Moon01556a52016-02-12 12:48:47 -0800317 @Override
318 public void updateVirtualSubscriberGateways(HostId vSgHostId, String serviceVlan,
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800319 Map<IpAddress, MacAddress> vSgs) {
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800320 Host vSgHost = hostService.getHost(vSgHostId);
321 if (vSgHost == null || !vSgHost.annotations().value(S_TAG).equals(serviceVlan)) {
Hyunsun Moon01556a52016-02-12 12:48:47 -0800322 log.debug("Invalid vSG updates for {}", serviceVlan);
323 return;
324 }
325
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800326 log.info("Updates vSGs in {} with {}", vSgHost.id(), vSgs.toString());
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800327 vSgs.entrySet().stream()
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800328 .filter(entry -> hostService.getHostsByMac(entry.getValue()).isEmpty())
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800329 .forEach(entry -> addVirtualSubscriberGateway(
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800330 vSgHost,
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800331 entry.getKey(),
332 entry.getValue(),
333 serviceVlan));
334
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800335 hostService.getConnectedHosts(vSgHost.location()).stream()
336 .filter(host -> !host.mac().equals(vSgHost.mac()))
Hyunsun Moon97c74192016-02-17 19:00:50 -0800337 .filter(host -> !vSgs.values().contains(host.mac()))
338 .forEach(host -> {
339 log.info("Removed vSG {}", host.toString());
340 hostProvider.hostVanished(host.id());
341 });
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800342 }
343
344 /**
345 * Adds virtual subscriber gateway to the system.
346 *
347 * @param vSgHost host virtual machine of this vSG
348 * @param vSgIp vSG ip address
349 * @param vSgMac vSG mac address
350 * @param serviceVlan service vlan
351 */
Hyunsun Moon97c74192016-02-17 19:00:50 -0800352 private void addVirtualSubscriberGateway(Host vSgHost, IpAddress vSgIp, MacAddress vSgMac,
353 String serviceVlan) {
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800354 log.info("vSG with IP({}) MAC({}) added", vSgIp.toString(), vSgMac.toString());
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800355
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800356 HostId hostId = HostId.hostId(vSgMac);
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800357 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800358 .set(S_TAG, serviceVlan)
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800359 .set(VSG_HOST_ID, vSgHost.id().toString())
360 .set(CREATED_TIME, String.valueOf(System.currentTimeMillis()));
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800361
362 HostDescription hostDesc = new DefaultHostDescription(
363 vSgMac,
364 VlanId.NONE,
365 vSgHost.location(),
366 Sets.newHashSet(vSgIp),
367 annotations.build());
368
369 hostProvider.hostDetected(hostId, hostDesc, false);
Hyunsun Moon01556a52016-02-12 12:48:47 -0800370 }
371
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800372 /**
Hyunsun Moond05b32e2016-03-02 19:27:26 -0800373 * Returns public ip addresses of vSGs running inside a give vSG host.
374 *
375 * @param vSgHost vSG host
376 * @return map of ip and mac address, or empty map
377 */
378 private Map<IpAddress, MacAddress> getSubscriberGateways(Host vSgHost) {
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700379 checkNotNull(osAccess, "OpenStack access is not set");
380
381 String osPortId = vSgHost.annotations().value(OPENSTACK_PORT_ID);
Hyunsun Moond05b32e2016-03-02 19:27:26 -0800382 String serviceVlan = vSgHost.annotations().value(S_TAG);
383
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700384 OSClient osClient = OSFactory.clientFromAccess(osAccess);
385 org.openstack4j.model.network.Port osPort = osClient.networking().port().get(osPortId);
386 if (osPort == null) {
387 log.warn("Failed to get OpenStack port {} for VM {}", osPortId, vSgHost.id());
Hyunsun Moond05b32e2016-03-02 19:27:26 -0800388 return Maps.newHashMap();
389 }
390
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700391 if (!serviceVlan.equals(getServiceVlan(osPort))) {
392 log.error("Host({}) s-tag does not match with OpenStack port s-tag", vSgHost.id());
Hyunsun Moond05b32e2016-03-02 19:27:26 -0800393 return Maps.newHashMap();
394 }
395
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700396 Map<IpAddress, MacAddress> addressPairs = Maps.newHashMap();
397 osPort.getAllowedAddressPairs()
398 .stream().forEach(p -> addressPairs.put(
399 IpAddress.valueOf(p.getIpAddress()),
400 MacAddress.valueOf(p.getMacAddress())));
401
402 return addressPairs;
Hyunsun Moond05b32e2016-03-02 19:27:26 -0800403 }
404
405 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800406 * Returns CordService by service ID.
Hyunsun Moon97eaf502015-12-07 14:06:28 -0800407 *
408 * @param serviceId service id
409 * @return cord service, or null if it fails to get network from OpenStack
410 */
411 private CordService getCordService(CordServiceId serviceId) {
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700412 checkNotNull(osAccess, "OpenStack access is not set");
413
414 OSClient osClient = OSFactory.clientFromAccess(osAccess);
415 Network osNet = osClient.networking().network().get(serviceId.id());
416 if (osNet == null) {
Hyunsun Moon97eaf502015-12-07 14:06:28 -0800417 log.warn("Couldn't find OpenStack network for service {}", serviceId.id());
418 return null;
419 }
420
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700421 // here it assumes all cord service networks has only one subnet
422 Subnet osSubnet = osNet.getNeutronSubnets().stream()
Hyunsun Moonba290072015-12-16 20:53:23 -0800423 .findFirst()
424 .orElse(null);
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700425 if (osSubnet == null) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800426 log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id());
427 return null;
428 }
429
430 Set<CordServiceId> tServices = Sets.newHashSet();
431 // TODO get tenant services from XOS
432
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700433 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(osNet)
Hyunsun Moonba290072015-12-16 20:53:23 -0800434 .stream()
Hyunsun Mooncb799442016-01-15 20:03:18 -0800435 .collect(Collectors.toMap(host -> host, this::getTunnelIp));
Hyunsun Moonba290072015-12-16 20:53:23 -0800436
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700437 return new CordService(osNet, osSubnet, hosts, tServices);
Hyunsun Moon97eaf502015-12-07 14:06:28 -0800438 }
439
440 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800441 * Returns CordService by OpenStack network.
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800442 *
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700443 * @param osNet OpenStack network
Hyunsun Moonba290072015-12-16 20:53:23 -0800444 * @return cord service
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800445 */
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700446 private CordService getCordService(Network osNet) {
447 checkNotNull(osNet);
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800448
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700449 CordServiceId serviceId = CordServiceId.of(osNet.getId());
450 // here it assumes all cord service networks has only one subnet
451 Subnet osSubnet = osNet.getNeutronSubnets().stream()
Hyunsun Moonba290072015-12-16 20:53:23 -0800452 .findFirst()
453 .orElse(null);
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700454 if (osSubnet == null) {
455 log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id());
Hyunsun Moonba290072015-12-16 20:53:23 -0800456 return null;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800457 }
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800458
Hyunsun Moonba290072015-12-16 20:53:23 -0800459 Set<CordServiceId> tServices = Sets.newHashSet();
460 // TODO get tenant services from XOS
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800461
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700462 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(osNet)
Hyunsun Moonba290072015-12-16 20:53:23 -0800463 .stream()
Hyunsun Mooncb799442016-01-15 20:03:18 -0800464 .collect(Collectors.toMap(host -> host, this::getTunnelIp));
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800465
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700466 return new CordService(osNet, osSubnet, hosts, tServices);
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800467 }
468
Hyunsun Mooncb799442016-01-15 20:03:18 -0800469 /**
470 * Returns IP address for tunneling for a given host.
471 *
472 * @param host host
Hyunsun Moon01556a52016-02-12 12:48:47 -0800473 * @return ip address, or null
Hyunsun Mooncb799442016-01-15 20:03:18 -0800474 */
475 private IpAddress getTunnelIp(Host host) {
Hyunsun Moon01556a52016-02-12 12:48:47 -0800476 String ip = host.annotations().value(DATA_PLANE_IP);
477 return ip == null ? null : IpAddress.valueOf(ip);
Hyunsun Mooncb799442016-01-15 20:03:18 -0800478 }
Hyunsun Moone9d75992015-09-15 22:39:16 -0700479
Hyunsun Mooncb799442016-01-15 20:03:18 -0800480 /**
481 * Returns port name.
482 *
483 * @param port port
484 * @return port name
485 */
486 private String getPortName(Port port) {
487 return port.annotations().value("portName");
488 }
Hyunsun Moon4edb0172015-11-07 22:08:43 -0800489
Hyunsun Mooncb799442016-01-15 20:03:18 -0800490 /**
Hyunsun Moon01556a52016-02-12 12:48:47 -0800491 * Returns s-tag from a given OpenStack port.
492 *
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700493 * @param osPort openstack port
Hyunsun Moon01556a52016-02-12 12:48:47 -0800494 * @return s-tag string
495 */
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700496 private String getServiceVlan(org.openstack4j.model.network.Port osPort) {
497 checkNotNull(osPort);
Hyunsun Moon01556a52016-02-12 12:48:47 -0800498
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700499 String portName = osPort.getName();
500 if (portName != null && portName.startsWith(S_TAG)) {
501 return portName.split("-")[1];
Hyunsun Moon01556a52016-02-12 12:48:47 -0800502 } else {
503 return null;
504 }
505 }
506
507 /**
Hyunsun Moond05b32e2016-03-02 19:27:26 -0800508 * Returns service ID of this host.
509 *
510 * @param host host
511 * @return service id, or null if not found
512 */
513 private String getServiceId(Host host) {
514 return host.annotations().value(SERVICE_ID);
515 }
516
517 /**
Hyunsun Mooncb799442016-01-15 20:03:18 -0800518 * Returns hosts associated with a given OpenStack network.
519 *
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700520 * @param osNet openstack network
Hyunsun Mooncb799442016-01-15 20:03:18 -0800521 * @return set of hosts
522 */
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700523 private Set<Host> getHostsWithOpenstackNetwork(Network osNet) {
524 checkNotNull(osNet);
Hyunsun Moone9d75992015-09-15 22:39:16 -0700525
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700526 String osNetId = osNet.getId();
Hyunsun Moond05b32e2016-03-02 19:27:26 -0800527 return StreamSupport.stream(hostService.getHosts().spliterator(), false)
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700528 .filter(host -> Objects.equals(osNetId, getServiceId(host)))
Hyunsun Mooncb799442016-01-15 20:03:18 -0800529 .collect(Collectors.toSet());
Hyunsun Moon01556a52016-02-12 12:48:47 -0800530 }
531
532 /**
Hyunsun Moon8b530e32016-02-03 00:11:11 -0800533 * Registers static DHCP lease for a given host.
534 *
535 * @param host host
536 * @param service cord service
537 */
538 private void registerDhcpLease(Host host, CordService service) {
539 List<Ip4Address> options = Lists.newArrayList();
540 options.add(Ip4Address.makeMaskPrefix(service.serviceIpRange().prefixLength()));
541 options.add(service.serviceIp().getIp4Address());
542 options.add(service.serviceIp().getIp4Address());
543 options.add(DEFAULT_DNS);
544
545 log.debug("Set static DHCP mapping for {}", host.mac());
546 dhcpService.setStaticMapping(host.mac(),
547 host.ipAddresses().stream().findFirst().get().getIp4Address(),
548 true,
549 options);
550 }
551
552 /**
Hyunsun Mooncb799442016-01-15 20:03:18 -0800553 * Handles VM detected situation.
554 *
555 * @param host host
556 */
557 private void serviceVmAdded(Host host) {
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700558 checkNotNull(osAccess, "OpenStack access is not set");
559
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800560 String serviceVlan = host.annotations().value(S_TAG);
561 if (serviceVlan != null) {
562 virtualSubscriberGatewayAdded(host, serviceVlan);
563 }
564
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700565 String osNetId = host.annotations().value(SERVICE_ID);
566 if (osNetId == null) {
Hyunsun Moon97c74192016-02-17 19:00:50 -0800567 // ignore this host, it is not the service VM, or it's a vSG
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800568 return;
569 }
570
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700571 OSClient osClient = OSFactory.clientFromAccess(osAccess);
572 Network osNet = osClient.networking().network().get(osNetId);
573 if (osNet == null) {
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800574 log.warn("Failed to get OpenStack network {} for VM {}.",
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700575 osNetId, host.id());
Hyunsun Mooncb799442016-01-15 20:03:18 -0800576 return;
577 }
578
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800579 log.info("VM is detected, MAC: {} IP: {}",
Hyunsun Mooncb799442016-01-15 20:03:18 -0800580 host.mac(),
581 host.ipAddresses().stream().findFirst().get());
582
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700583 CordService service = getCordService(osNet);
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800584 if (service == null) {
585 return;
586 }
587
Hyunsun Mooncca9c682016-03-01 16:36:23 -0800588 switch (service.serviceType()) {
589 case MANAGEMENT:
590 ruleInstaller.populateManagementNetworkRules(host, service);
591 break;
592 case PRIVATE:
Hyunsun Mooncca9c682016-03-01 16:36:23 -0800593 arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
Hyunsun Moon450d66d2016-03-03 13:27:44 -0800594 case PUBLIC:
Hyunsun Mooncca9c682016-03-01 16:36:23 -0800595 default:
596 // TODO check if the service needs an update on its group buckets after done CORD-433
597 ruleInstaller.updateServiceGroup(service);
598 // sends gratuitous ARP here for the case of adding existing VMs
599 // when ONOS or cordvtn app is restarted
600 arpProxy.sendGratuitousArpForGateway(service.serviceIp(), Sets.newHashSet(host));
601 break;
Hyunsun Mooncb799442016-01-15 20:03:18 -0800602 }
603
Hyunsun Moon8b530e32016-02-03 00:11:11 -0800604 registerDhcpLease(host, service);
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700605 ruleInstaller.populateBasicConnectionRules(host, getTunnelIp(host), osNet);
Hyunsun Mooncb799442016-01-15 20:03:18 -0800606 }
607
608 /**
609 * Handles VM removed situation.
610 *
611 * @param host host
612 */
613 private void serviceVmRemoved(Host host) {
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700614 checkNotNull(osAccess, "OpenStack access is not set");
615
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800616 String serviceVlan = host.annotations().value(S_TAG);
617 if (serviceVlan != null) {
618 virtualSubscriberGatewayRemoved(host);
619 }
620
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700621 String osNetId = host.annotations().value(SERVICE_ID);
622 if (osNetId == null) {
Hyunsun Moon97c74192016-02-17 19:00:50 -0800623 // ignore it, it's not the service VM or it's a vSG
Hyunsun Moon8b530e32016-02-03 00:11:11 -0800624 return;
625 }
626
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700627 OSClient osClient = OSFactory.clientFromAccess(osAccess);
628 Network osNet = osClient.networking().network().get(osNetId);
629 if (osNet == null) {
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800630 log.warn("Failed to get OpenStack network {} for VM {}",
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700631 osNetId, host.id());
Hyunsun Mooncb799442016-01-15 20:03:18 -0800632 return;
633 }
634
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800635 log.info("VM is vanished, MAC: {} IP: {}",
Hyunsun Mooncb799442016-01-15 20:03:18 -0800636 host.mac(),
637 host.ipAddresses().stream().findFirst().get());
638
639 ruleInstaller.removeBasicConnectionRules(host);
Hyunsun Moon1b2355e2016-02-03 14:44:06 -0800640 dhcpService.removeStaticMapping(host.mac());
Hyunsun Mooncb799442016-01-15 20:03:18 -0800641
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700642 CordService service = getCordService(osNet);
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800643 if (service == null) {
644 return;
645 }
646
Hyunsun Mooncca9c682016-03-01 16:36:23 -0800647 switch (service.serviceType()) {
648 case MANAGEMENT:
649 ruleInstaller.removeManagementNetworkRules(host, service);
650 break;
651 case PRIVATE:
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700652 if (getHostsWithOpenstackNetwork(osNet).isEmpty()) {
Hyunsun Mooncca9c682016-03-01 16:36:23 -0800653 arpProxy.removeGateway(service.serviceIp());
654 }
Hyunsun Moon450d66d2016-03-03 13:27:44 -0800655 case PUBLIC:
Hyunsun Mooncca9c682016-03-01 16:36:23 -0800656 default:
657 // TODO check if the service needs an update on its group buckets after done CORD-433
658 ruleInstaller.updateServiceGroup(service);
659 break;
Hyunsun Moone9d75992015-09-15 22:39:16 -0700660 }
661 }
662
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800663
664 /**
665 * Handles virtual subscriber gateway VM or container.
666 *
667 * @param host new host with stag, it can be vsg VM or vsg
668 * @param serviceVlan service vlan
669 */
670 private void virtualSubscriberGatewayAdded(Host host, String serviceVlan) {
671 Map<IpAddress, MacAddress> vSgs;
672 Host vSgHost;
673
674 String vSgHostId = host.annotations().value(VSG_HOST_ID);
675 if (vSgHostId == null) {
676 log.debug("vSG VM detected {}", host.id());
677
678 vSgHost = host;
679 vSgs = getSubscriberGateways(vSgHost);
680 vSgs.entrySet().stream().forEach(entry -> addVirtualSubscriberGateway(
681 vSgHost,
682 entry.getKey(),
683 entry.getValue(),
684 serviceVlan));
685 } else {
686 vSgHost = hostService.getHost(HostId.hostId(vSgHostId));
687 if (vSgHost == null) {
688 return;
689 }
690
691 log.debug("vSG detected {}", host.id());
692 vSgs = getSubscriberGateways(vSgHost);
693 }
694
695 ruleInstaller.populateSubscriberGatewayRules(vSgHost, vSgs.keySet());
696 }
697
698 /**
699 * Handles virtual subscriber gateway removed.
700 *
701 * @param vSg vsg host to remove
702 */
703 private void virtualSubscriberGatewayRemoved(Host vSg) {
704 String vSgHostId = vSg.annotations().value(VSG_HOST_ID);
705 if (vSgHostId == null) {
706 return;
707 }
708
709 Host vSgHost = hostService.getHost(HostId.hostId(vSgHostId));
710 if (vSgHost == null) {
711 return;
712 }
713
714 log.info("vSG removed {}", vSg.id());
715 Map<IpAddress, MacAddress> vSgs = getSubscriberGateways(vSgHost);
716 ruleInstaller.populateSubscriberGatewayRules(vSgHost, vSgs.keySet());
717 }
718
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800719 /**
720 * Sets service network gateway MAC address and sends out gratuitous ARP to all
721 * VMs to update the gateway MAC address.
722 *
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800723 * @param newMac mac address to update
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800724 */
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800725 private void setPrivateGatewayMac(MacAddress newMac) {
726 if (newMac == null || newMac.equals(privateGatewayMac)) {
727 // no updates, do nothing
728 return;
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800729 }
730
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800731 privateGatewayMac = newMac;
732 log.debug("Set service gateway MAC address to {}", privateGatewayMac.toString());
733
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800734 // TODO get existing service list from XOS and replace the loop below
735 Set<String> vNets = Sets.newHashSet();
736 hostService.getHosts().forEach(host -> vNets.add(host.annotations().value(SERVICE_ID)));
737 vNets.remove(null);
738
739 vNets.stream().forEach(vNet -> {
740 CordService service = getCordService(CordServiceId.of(vNet));
741 if (service != null) {
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800742 arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
743 arpProxy.sendGratuitousArpForGateway(service.serviceIp(), service.hosts().keySet());
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800744 }
745 });
746 }
747
748 /**
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800749 * Sets public gateway MAC address.
750 *
751 * @param publicGateways gateway ip and mac address pairs
752 */
753 private void setPublicGatewayMac(Map<IpAddress, MacAddress> publicGateways) {
754 publicGateways.entrySet()
755 .stream()
756 .forEach(entry -> {
757 arpProxy.addGateway(entry.getKey(), entry.getValue());
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700758 log.debug("Added public gateway IP {}, MAC {}",
759 entry.getKey().toString(), entry.getValue().toString());
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800760 });
761 // TODO notice gateway MAC change to VMs holds this gateway IP
762 }
763
764 /**
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700765 * Sets OpenStack access information.
766 * Access is the entity returned when authenticated and provides a singleton client
767 * between multiple threads.
768 *
769 * @param osConfig openstack config
770 */
771 private void setOpenstackAccess(CordVtnConfig.OpenStackConfig osConfig) {
772 log.debug("Get OpenStack access with Endpoint: {} Tenant: {} User: {} Passwd: {}",
773 osConfig.endpoint(),
774 osConfig.tenant(),
775 osConfig.user(),
776 osConfig.password());
777 try {
778 osAccess = OSFactory.builder()
779 .endpoint(osConfig.endpoint())
780 .credentials(osConfig.user(), osConfig.password())
781 .tenantName(osConfig.tenant())
782 .authenticate()
783 .getAccess();
784 } catch (AuthenticationException e) {
785 log.error("Failed to get OpenStack Access");
786 }
787 }
788
789 /**
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800790 * Updates configurations.
791 */
792 private void readConfiguration() {
793 CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
794 if (config == null) {
795 log.debug("No configuration found");
796 return;
797 }
798
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700799 setOpenstackAccess(config.openstackConfig());
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800800 setPrivateGatewayMac(config.privateGatewayMac());
801 setPublicGatewayMac(config.publicGateways());
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700802 }
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800803
Hyunsun Moone9d75992015-09-15 22:39:16 -0700804 private class InternalHostListener implements HostListener {
805
806 @Override
807 public void event(HostEvent event) {
Hyunsun Mooncb799442016-01-15 20:03:18 -0800808 Host host = event.subject();
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800809 if (!mastershipService.isLocalMaster(host.location().deviceId())) {
810 // do not allow to proceed without mastership
811 return;
812 }
Hyunsun Moone9d75992015-09-15 22:39:16 -0700813
814 switch (event.type()) {
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800815 case HOST_UPDATED:
Hyunsun Moone9d75992015-09-15 22:39:16 -0700816 case HOST_ADDED:
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800817 eventExecutor.submit(() -> serviceVmAdded(host));
Hyunsun Moone9d75992015-09-15 22:39:16 -0700818 break;
819 case HOST_REMOVED:
Hyunsun Moone58a4ad2016-03-08 21:59:13 -0800820 eventExecutor.submit(() -> serviceVmRemoved(host));
Hyunsun Moone9d75992015-09-15 22:39:16 -0700821 break;
822 default:
823 break;
824 }
825 }
826 }
827
Hyunsun Moon022272f2016-01-11 15:30:42 -0800828 private class InternalPacketProcessor implements PacketProcessor {
829
830 @Override
831 public void process(PacketContext context) {
832 if (context.isHandled()) {
833 return;
834 }
835
836 Ethernet ethPacket = context.inPacket().parsed();
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800837 if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
Hyunsun Moon022272f2016-01-11 15:30:42 -0800838 return;
839 }
840
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800841 arpProxy.processArpPacket(context, ethPacket);
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800842 }
843 }
844
845 private class InternalConfigListener implements NetworkConfigListener {
846
847 @Override
848 public void event(NetworkConfigEvent event) {
849 if (!event.configClass().equals(CordVtnConfig.class)) {
Hyunsun Moon022272f2016-01-11 15:30:42 -0800850 return;
851 }
852
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800853 switch (event.type()) {
854 case CONFIG_ADDED:
855 case CONFIG_UPDATED:
856 log.info("Network configuration changed");
857 eventExecutor.execute(CordVtn.this::readConfiguration);
858 break;
859 default:
860 break;
861 }
Hyunsun Moon022272f2016-01-11 15:30:42 -0800862 }
863 }
Hyunsun Moone9d75992015-09-15 22:39:16 -0700864}