blob: 61f37b58ca84b7f241b65bdc76e2585fdeed3145 [file] [log] [blame]
Hyunsun Moond0e932a2015-09-15 22:39:16 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Hyunsun Moond0e932a2015-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 Moon7f4ed9d2016-04-14 16:13:42 -070016package org.onosproject.cordvtn.impl;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070017
Hyunsun Moon1d3eac92016-02-03 00:11:11 -080018import com.google.common.collect.Lists;
Hyunsun Moonae39ae82016-02-17 15:02:06 -080019import com.google.common.collect.Maps;
Hyunsun Moon1f145552015-10-08 22:25:30 -070020import com.google.common.collect.Sets;
Hyunsun Moond0e932a2015-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 Moon42c7b4e2016-01-11 15:30:42 -080027import org.onlab.packet.Ethernet;
Hyunsun Moon1d3eac92016-02-03 00:11:11 -080028import org.onlab.packet.Ip4Address;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080029import org.onlab.packet.IpAddress;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080030import org.onlab.packet.MacAddress;
31import org.onlab.packet.VlanId;
Hyunsun Moon7f4ed9d2016-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 Moon1f145552015-10-08 22:25:30 -070037import org.onosproject.core.ApplicationId;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070038import org.onosproject.core.CoreService;
Hyunsun Moon1d3eac92016-02-03 00:11:11 -080039import org.onosproject.dhcp.DhcpService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080040import org.onosproject.mastership.MastershipService;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080041import org.onosproject.net.ConnectPoint;
Hyunsun Moond772f342015-10-28 20:28:16 -070042import org.onosproject.net.DefaultAnnotations;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070043import org.onosproject.net.Host;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080044import org.onosproject.net.HostId;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080045import org.onosproject.net.HostLocation;
Hyunsun Moon8539b042015-11-07 22:08:43 -080046import org.onosproject.net.Port;
Hyunsun Moon746956f2016-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 Moond0e932a2015-09-15 22:39:16 -070053import org.onosproject.net.device.DeviceService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080054import org.onosproject.net.flow.FlowRuleService;
55import org.onosproject.net.group.GroupService;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080056import org.onosproject.net.host.DefaultHostDescription;
57import org.onosproject.net.host.HostDescription;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070058import org.onosproject.net.host.HostEvent;
59import org.onosproject.net.host.HostListener;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080060import org.onosproject.net.host.HostProvider;
61import org.onosproject.net.host.HostProviderRegistry;
62import org.onosproject.net.host.HostProviderService;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070063import org.onosproject.net.host.HostService;
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -080064import org.onosproject.net.packet.PacketContext;
65import org.onosproject.net.packet.PacketProcessor;
66import org.onosproject.net.packet.PacketService;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080067import org.onosproject.net.provider.AbstractProvider;
68import org.onosproject.net.provider.ProviderId;
Hyunsun Moon576d6872016-04-14 19:04:23 -070069import org.openstack4j.api.OSClient;
70import org.openstack4j.api.exceptions.AuthenticationException;
71import org.openstack4j.model.identity.Access;
72import org.openstack4j.model.network.Network;
73import org.openstack4j.model.network.Subnet;
74import org.openstack4j.openstack.OSFactory;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070075import org.slf4j.Logger;
76
Hyunsun Moon1d3eac92016-02-03 00:11:11 -080077import java.util.List;
Hyunsun Moon1f145552015-10-08 22:25:30 -070078import java.util.Map;
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -080079import java.util.Objects;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080080import java.util.Set;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070081import java.util.concurrent.ExecutorService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080082import java.util.stream.Collectors;
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -080083import java.util.stream.StreamSupport;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070084
Hyunsun Moon1f145552015-10-08 22:25:30 -070085import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moon746956f2016-01-24 21:47:06 -080086import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070087import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070088import static org.slf4j.LoggerFactory.getLogger;
89
90/**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080091 * Provisions virtual tenant networks with service chaining capability
92 * in OpenStack environment.
Hyunsun Moond0e932a2015-09-15 22:39:16 -070093 */
94@Component(immediate = true)
95@Service
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080096public class CordVtn extends AbstractProvider implements CordVtnService, HostProvider {
Hyunsun Moond0e932a2015-09-15 22:39:16 -070097
98 protected final Logger log = getLogger(getClass());
99
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected CoreService coreService;
102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon746956f2016-01-24 21:47:06 -0800104 protected NetworkConfigRegistry configRegistry;
105
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected NetworkConfigService configService;
108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800110 protected HostProviderRegistry hostProviderRegistry;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700111
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700113 protected DeviceService deviceService;
114
115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 protected HostService hostService;
117
Hyunsun Moon1f145552015-10-08 22:25:30 -0700118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800119 protected FlowRuleService flowRuleService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800122 protected PacketService packetService;
123
124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800125 protected MastershipService mastershipService;
126
127 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
128 protected GroupService groupService;
129
130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800131 protected DhcpService dhcpService;
132
Hyunsun Moon746956f2016-01-24 21:47:06 -0800133 private final ConfigFactory configFactory =
134 new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
135 @Override
136 public CordVtnConfig createConfig() {
137 return new CordVtnConfig();
138 }
139 };
140
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800141 private static final String DEFAULT_TUNNEL = "vxlan";
142 private static final String SERVICE_ID = "serviceId";
Hyunsun Moon6d247342016-02-12 12:48:47 -0800143 private static final String OPENSTACK_PORT_ID = "openstackPortId";
144 private static final String DATA_PLANE_IP = "dataPlaneIp";
145 private static final String DATA_PLANE_INTF = "dataPlaneIntf";
146 private static final String S_TAG = "stag";
Hyunsun Moon98025542016-03-08 04:36:02 -0800147 private static final String VSG_HOST_ID = "vsgHostId";
Hyunsun Moond35420f2016-03-08 21:59:13 -0800148 private static final String CREATED_TIME = "createdTime";
Hyunsun Moon6d247342016-02-12 12:48:47 -0800149
150 private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800151
Hyunsun Moon746956f2016-01-24 21:47:06 -0800152 private final ExecutorService eventExecutor =
153 newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "event-handler"));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700154
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800155 private final PacketProcessor packetProcessor = new InternalPacketProcessor();
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800156 private final HostListener hostListener = new InternalHostListener();
Hyunsun Moon746956f2016-01-24 21:47:06 -0800157 private final NetworkConfigListener configListener = new InternalConfigListener();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700158
Hyunsun Moon746956f2016-01-24 21:47:06 -0800159 private ApplicationId appId;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800160 private HostProviderService hostProvider;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800161 private CordVtnRuleInstaller ruleInstaller;
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800162 private CordVtnArpProxy arpProxy;
Hyunsun Moon576d6872016-04-14 19:04:23 -0700163
164 private volatile Access osAccess = null;
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800165 private volatile MacAddress privateGatewayMac = MacAddress.NONE;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800166
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800167 /**
168 * Creates an cordvtn host location provider.
169 */
170 public CordVtn() {
171 super(new ProviderId("host", CORDVTN_APP_ID));
Hyunsun Moon8539b042015-11-07 22:08:43 -0800172 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700173
174 @Activate
175 protected void activate() {
Hyunsun Moon746956f2016-01-24 21:47:06 -0800176 appId = coreService.registerApplication("org.onosproject.cordvtn");
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800177 ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService,
178 deviceService,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800179 groupService,
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800180 configRegistry,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800181 DEFAULT_TUNNEL);
182
Hyunsun Moon9cf43db2016-02-12 15:59:53 -0800183 arpProxy = new CordVtnArpProxy(appId, packetService, hostService);
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800184 packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
185 arpProxy.requestPacket();
186
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700187 hostService.addListener(hostListener);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800188 hostProvider = hostProviderRegistry.register(this);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700189
Hyunsun Moon746956f2016-01-24 21:47:06 -0800190 configRegistry.registerConfigFactory(configFactory);
191 configService.addListener(configListener);
Hyunsun Moon746956f2016-01-24 21:47:06 -0800192
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700193 log.info("Started");
194 }
195
196 @Deactivate
197 protected void deactivate() {
Hyunsun Moon746956f2016-01-24 21:47:06 -0800198 hostProviderRegistry.unregister(this);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700199 hostService.removeListener(hostListener);
Hyunsun Moon746956f2016-01-24 21:47:06 -0800200
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800201 packetService.removeProcessor(packetProcessor);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700202
Hyunsun Moon746956f2016-01-24 21:47:06 -0800203 configRegistry.unregisterConfigFactory(configFactory);
204 configService.removeListener(configListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700205
Hyunsun Moon746956f2016-01-24 21:47:06 -0800206 eventExecutor.shutdown();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700207 log.info("Stopped");
208 }
209
210 @Override
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800211 public void triggerProbe(Host host) {
212 /*
213 * Note: In CORD deployment, we assume that all hosts are configured.
214 * Therefore no probe is required.
215 */
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800216 }
217
218 @Override
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800219 public void createServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId,
220 boolean isBidirectional) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800221 CordService tService = getCordService(tServiceId);
222 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800223
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800224 if (tService == null || pService == null) {
225 log.error("Failed to create CordService for {}", tServiceId.id());
226 return;
227 }
228
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800229 log.info("Service dependency from {} to {} created.", tService.id().id(), pService.id().id());
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800230 ruleInstaller.populateServiceDependencyRules(tService, pService, isBidirectional);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800231 }
232
233 @Override
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800234 public void removeServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId) {
235 CordService tService = getCordService(tServiceId);
236 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800237
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800238 if (tService == null || pService == null) {
239 log.error("Failed to create CordService for {}", tServiceId.id());
240 return;
241 }
242
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800243 log.info("Service dependency from {} to {} removed.", tService.id().id(), pService.id().id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800244 ruleInstaller.removeServiceDependencyRules(tService, pService);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800245 }
246
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800247 @Override
248 public void addServiceVm(CordVtnNode node, ConnectPoint connectPoint) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700249 checkNotNull(osAccess, "OpenStack access is not set");
250
251 OSClient osClient = OSFactory.clientFromAccess(osAccess);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800252 Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
Hyunsun Moon576d6872016-04-14 19:04:23 -0700253 org.openstack4j.model.network.Port osPort = osClient.networking().port().list()
254 .stream()
255 .filter(p -> p.getId().contains(getPortName(port).substring(3)))
256 .findFirst().orElse(null);
257 if (osPort == null) {
258 log.warn("Failed to get OpenStack port for {}", getPortName(port));
Hyunsun Moon8539b042015-11-07 22:08:43 -0800259 return;
260 }
261
Hyunsun Moon576d6872016-04-14 19:04:23 -0700262 MacAddress mac = MacAddress.valueOf(osPort.getMacAddress());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800263 HostId hostId = HostId.hostId(mac);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800264
Hyunsun Moond35420f2016-03-08 21:59:13 -0800265 Host existingHost = hostService.getHost(hostId);
266 if (existingHost != null) {
267 String serviceId = existingHost.annotations().value(SERVICE_ID);
Hyunsun Moon576d6872016-04-14 19:04:23 -0700268 if (serviceId == null || !serviceId.equals(osPort.getNetworkId())) {
Hyunsun Moond35420f2016-03-08 21:59:13 -0800269 // this host is not injected by cordvtn or a stale host, remove it
270 hostProvider.hostVanished(existingHost.id());
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800271 }
Hyunsun Moon8539b042015-11-07 22:08:43 -0800272 }
273
Hyunsun Moond35420f2016-03-08 21:59:13 -0800274 // Included CREATED_TIME to annotation intentionally to trigger HOST_UPDATED
275 // event so that the flow rule population for this host can happen.
276 // This ensures refreshing data plane by pushing network config always make
277 // the data plane synced.
Hyunsun Moon576d6872016-04-14 19:04:23 -0700278 Set<IpAddress> fixedIps = osPort.getFixedIps().stream()
279 .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
280 .collect(Collectors.toSet());
281
Hyunsun Moon6d247342016-02-12 12:48:47 -0800282 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
Hyunsun Moon576d6872016-04-14 19:04:23 -0700283 .set(SERVICE_ID, osPort.getNetworkId())
284 .set(OPENSTACK_PORT_ID, osPort.getId())
Hyunsun Moon6d247342016-02-12 12:48:47 -0800285 .set(DATA_PLANE_IP, node.dpIp().ip().toString())
Hyunsun Moond35420f2016-03-08 21:59:13 -0800286 .set(DATA_PLANE_INTF, node.dpIntf())
287 .set(CREATED_TIME, String.valueOf(System.currentTimeMillis()));
Hyunsun Moon6d247342016-02-12 12:48:47 -0800288
Hyunsun Moon576d6872016-04-14 19:04:23 -0700289 String serviceVlan = getServiceVlan(osPort);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800290 if (serviceVlan != null) {
291 annotations.set(S_TAG, serviceVlan);
292 }
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800293
294 HostDescription hostDesc = new DefaultHostDescription(
295 mac,
296 VlanId.NONE,
297 new HostLocation(connectPoint, System.currentTimeMillis()),
Hyunsun Moon576d6872016-04-14 19:04:23 -0700298 fixedIps,
Hyunsun Moon6d247342016-02-12 12:48:47 -0800299 annotations.build());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800300
301 hostProvider.hostDetected(hostId, hostDesc, false);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800302 }
303
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800304 @Override
305 public void removeServiceVm(ConnectPoint connectPoint) {
Hyunsun Moon2a225162016-02-17 19:00:50 -0800306 hostService.getConnectedHosts(connectPoint)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800307 .stream()
Hyunsun Moon2a225162016-02-17 19:00:50 -0800308 .forEach(host -> hostProvider.hostVanished(host.id()));
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800309 }
310
Hyunsun Moon6d247342016-02-12 12:48:47 -0800311 @Override
312 public void updateVirtualSubscriberGateways(HostId vSgHostId, String serviceVlan,
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800313 Map<IpAddress, MacAddress> vSgs) {
Hyunsun Moon98025542016-03-08 04:36:02 -0800314 Host vSgHost = hostService.getHost(vSgHostId);
315 if (vSgHost == null || !vSgHost.annotations().value(S_TAG).equals(serviceVlan)) {
Hyunsun Moon6d247342016-02-12 12:48:47 -0800316 log.debug("Invalid vSG updates for {}", serviceVlan);
317 return;
318 }
319
Hyunsun Moon98025542016-03-08 04:36:02 -0800320 log.info("Updates vSGs in {} with {}", vSgHost.id(), vSgs.toString());
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800321 vSgs.entrySet().stream()
Hyunsun Moon98025542016-03-08 04:36:02 -0800322 .filter(entry -> hostService.getHostsByMac(entry.getValue()).isEmpty())
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800323 .forEach(entry -> addVirtualSubscriberGateway(
Hyunsun Moon98025542016-03-08 04:36:02 -0800324 vSgHost,
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800325 entry.getKey(),
326 entry.getValue(),
327 serviceVlan));
328
Hyunsun Moon98025542016-03-08 04:36:02 -0800329 hostService.getConnectedHosts(vSgHost.location()).stream()
330 .filter(host -> !host.mac().equals(vSgHost.mac()))
Hyunsun Moon2a225162016-02-17 19:00:50 -0800331 .filter(host -> !vSgs.values().contains(host.mac()))
332 .forEach(host -> {
333 log.info("Removed vSG {}", host.toString());
334 hostProvider.hostVanished(host.id());
335 });
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800336 }
337
338 /**
339 * Adds virtual subscriber gateway to the system.
340 *
341 * @param vSgHost host virtual machine of this vSG
342 * @param vSgIp vSG ip address
343 * @param vSgMac vSG mac address
344 * @param serviceVlan service vlan
345 */
Hyunsun Moon2a225162016-02-17 19:00:50 -0800346 private void addVirtualSubscriberGateway(Host vSgHost, IpAddress vSgIp, MacAddress vSgMac,
347 String serviceVlan) {
Hyunsun Moon98025542016-03-08 04:36:02 -0800348 log.info("vSG with IP({}) MAC({}) added", vSgIp.toString(), vSgMac.toString());
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800349
Hyunsun Moon98025542016-03-08 04:36:02 -0800350 HostId hostId = HostId.hostId(vSgMac);
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800351 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
Hyunsun Moon98025542016-03-08 04:36:02 -0800352 .set(S_TAG, serviceVlan)
Hyunsun Moond35420f2016-03-08 21:59:13 -0800353 .set(VSG_HOST_ID, vSgHost.id().toString())
354 .set(CREATED_TIME, String.valueOf(System.currentTimeMillis()));
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800355
356 HostDescription hostDesc = new DefaultHostDescription(
357 vSgMac,
358 VlanId.NONE,
359 vSgHost.location(),
360 Sets.newHashSet(vSgIp),
361 annotations.build());
362
363 hostProvider.hostDetected(hostId, hostDesc, false);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800364 }
365
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800366 /**
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800367 * Returns public ip addresses of vSGs running inside a give vSG host.
368 *
369 * @param vSgHost vSG host
370 * @return map of ip and mac address, or empty map
371 */
372 private Map<IpAddress, MacAddress> getSubscriberGateways(Host vSgHost) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700373 checkNotNull(osAccess, "OpenStack access is not set");
374
375 String osPortId = vSgHost.annotations().value(OPENSTACK_PORT_ID);
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800376 String serviceVlan = vSgHost.annotations().value(S_TAG);
377
Hyunsun Moon576d6872016-04-14 19:04:23 -0700378 OSClient osClient = OSFactory.clientFromAccess(osAccess);
379 org.openstack4j.model.network.Port osPort = osClient.networking().port().get(osPortId);
380 if (osPort == null) {
381 log.warn("Failed to get OpenStack port {} for VM {}", osPortId, vSgHost.id());
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800382 return Maps.newHashMap();
383 }
384
Hyunsun Moon576d6872016-04-14 19:04:23 -0700385 if (!serviceVlan.equals(getServiceVlan(osPort))) {
386 log.error("Host({}) s-tag does not match with OpenStack port s-tag", vSgHost.id());
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800387 return Maps.newHashMap();
388 }
389
Hyunsun Moon576d6872016-04-14 19:04:23 -0700390 Map<IpAddress, MacAddress> addressPairs = Maps.newHashMap();
391 osPort.getAllowedAddressPairs()
392 .stream().forEach(p -> addressPairs.put(
393 IpAddress.valueOf(p.getIpAddress()),
394 MacAddress.valueOf(p.getMacAddress())));
395
396 return addressPairs;
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800397 }
398
399 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800400 * Returns CordService by service ID.
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800401 *
402 * @param serviceId service id
403 * @return cord service, or null if it fails to get network from OpenStack
404 */
405 private CordService getCordService(CordServiceId serviceId) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700406 checkNotNull(osAccess, "OpenStack access is not set");
407
408 OSClient osClient = OSFactory.clientFromAccess(osAccess);
409 Network osNet = osClient.networking().network().get(serviceId.id());
410 if (osNet == null) {
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800411 log.warn("Couldn't find OpenStack network for service {}", serviceId.id());
412 return null;
413 }
414
Hyunsun Moon576d6872016-04-14 19:04:23 -0700415 // here it assumes all cord service networks has only one subnet
416 Subnet osSubnet = osNet.getNeutronSubnets().stream()
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800417 .findFirst()
418 .orElse(null);
Hyunsun Moon576d6872016-04-14 19:04:23 -0700419 if (osSubnet == null) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800420 log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id());
421 return null;
422 }
423
424 Set<CordServiceId> tServices = Sets.newHashSet();
425 // TODO get tenant services from XOS
426
Hyunsun Moon576d6872016-04-14 19:04:23 -0700427 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(osNet)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800428 .stream()
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800429 .collect(Collectors.toMap(host -> host, this::getTunnelIp));
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800430
Hyunsun Moon576d6872016-04-14 19:04:23 -0700431 return new CordService(osNet, osSubnet, hosts, tServices);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800432 }
433
434 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800435 * Returns CordService by OpenStack network.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800436 *
Hyunsun Moon576d6872016-04-14 19:04:23 -0700437 * @param osNet OpenStack network
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800438 * @return cord service
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800439 */
Hyunsun Moon576d6872016-04-14 19:04:23 -0700440 private CordService getCordService(Network osNet) {
441 checkNotNull(osNet);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800442
Hyunsun Moon576d6872016-04-14 19:04:23 -0700443 CordServiceId serviceId = CordServiceId.of(osNet.getId());
444 // here it assumes all cord service networks has only one subnet
445 Subnet osSubnet = osNet.getNeutronSubnets().stream()
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800446 .findFirst()
447 .orElse(null);
Hyunsun Moon576d6872016-04-14 19:04:23 -0700448 if (osSubnet == null) {
449 log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800450 return null;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800451 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800452
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800453 Set<CordServiceId> tServices = Sets.newHashSet();
454 // TODO get tenant services from XOS
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800455
Hyunsun Moon576d6872016-04-14 19:04:23 -0700456 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(osNet)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800457 .stream()
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800458 .collect(Collectors.toMap(host -> host, this::getTunnelIp));
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800459
Hyunsun Moon576d6872016-04-14 19:04:23 -0700460 return new CordService(osNet, osSubnet, hosts, tServices);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800461 }
462
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800463 /**
464 * Returns IP address for tunneling for a given host.
465 *
466 * @param host host
Hyunsun Moon6d247342016-02-12 12:48:47 -0800467 * @return ip address, or null
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800468 */
469 private IpAddress getTunnelIp(Host host) {
Hyunsun Moon6d247342016-02-12 12:48:47 -0800470 String ip = host.annotations().value(DATA_PLANE_IP);
471 return ip == null ? null : IpAddress.valueOf(ip);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800472 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700473
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800474 /**
475 * Returns port name.
476 *
477 * @param port port
478 * @return port name
479 */
480 private String getPortName(Port port) {
481 return port.annotations().value("portName");
482 }
Hyunsun Moon8539b042015-11-07 22:08:43 -0800483
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800484 /**
Hyunsun Moon6d247342016-02-12 12:48:47 -0800485 * Returns s-tag from a given OpenStack port.
486 *
Hyunsun Moon576d6872016-04-14 19:04:23 -0700487 * @param osPort openstack port
Hyunsun Moon6d247342016-02-12 12:48:47 -0800488 * @return s-tag string
489 */
Hyunsun Moon576d6872016-04-14 19:04:23 -0700490 private String getServiceVlan(org.openstack4j.model.network.Port osPort) {
491 checkNotNull(osPort);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800492
Hyunsun Moon576d6872016-04-14 19:04:23 -0700493 String portName = osPort.getName();
494 if (portName != null && portName.startsWith(S_TAG)) {
495 return portName.split("-")[1];
Hyunsun Moon6d247342016-02-12 12:48:47 -0800496 } else {
497 return null;
498 }
499 }
500
501 /**
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800502 * Returns service ID of this host.
503 *
504 * @param host host
505 * @return service id, or null if not found
506 */
507 private String getServiceId(Host host) {
508 return host.annotations().value(SERVICE_ID);
509 }
510
511 /**
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800512 * Returns hosts associated with a given OpenStack network.
513 *
Hyunsun Moon576d6872016-04-14 19:04:23 -0700514 * @param osNet openstack network
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800515 * @return set of hosts
516 */
Hyunsun Moon576d6872016-04-14 19:04:23 -0700517 private Set<Host> getHostsWithOpenstackNetwork(Network osNet) {
518 checkNotNull(osNet);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700519
Hyunsun Moon576d6872016-04-14 19:04:23 -0700520 String osNetId = osNet.getId();
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800521 return StreamSupport.stream(hostService.getHosts().spliterator(), false)
Hyunsun Moon576d6872016-04-14 19:04:23 -0700522 .filter(host -> Objects.equals(osNetId, getServiceId(host)))
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800523 .collect(Collectors.toSet());
Hyunsun Moon6d247342016-02-12 12:48:47 -0800524 }
525
526 /**
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800527 * Registers static DHCP lease for a given host.
528 *
529 * @param host host
530 * @param service cord service
531 */
532 private void registerDhcpLease(Host host, CordService service) {
533 List<Ip4Address> options = Lists.newArrayList();
534 options.add(Ip4Address.makeMaskPrefix(service.serviceIpRange().prefixLength()));
535 options.add(service.serviceIp().getIp4Address());
536 options.add(service.serviceIp().getIp4Address());
537 options.add(DEFAULT_DNS);
538
539 log.debug("Set static DHCP mapping for {}", host.mac());
540 dhcpService.setStaticMapping(host.mac(),
541 host.ipAddresses().stream().findFirst().get().getIp4Address(),
542 true,
543 options);
544 }
545
546 /**
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800547 * Handles VM detected situation.
548 *
549 * @param host host
550 */
551 private void serviceVmAdded(Host host) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700552 checkNotNull(osAccess, "OpenStack access is not set");
553
Hyunsun Moon98025542016-03-08 04:36:02 -0800554 String serviceVlan = host.annotations().value(S_TAG);
555 if (serviceVlan != null) {
556 virtualSubscriberGatewayAdded(host, serviceVlan);
557 }
558
Hyunsun Moon576d6872016-04-14 19:04:23 -0700559 String osNetId = host.annotations().value(SERVICE_ID);
560 if (osNetId == null) {
Hyunsun Moon2a225162016-02-17 19:00:50 -0800561 // ignore this host, it is not the service VM, or it's a vSG
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800562 return;
563 }
564
Hyunsun Moon576d6872016-04-14 19:04:23 -0700565 OSClient osClient = OSFactory.clientFromAccess(osAccess);
566 Network osNet = osClient.networking().network().get(osNetId);
567 if (osNet == null) {
Hyunsun Moond35420f2016-03-08 21:59:13 -0800568 log.warn("Failed to get OpenStack network {} for VM {}.",
Hyunsun Moon576d6872016-04-14 19:04:23 -0700569 osNetId, host.id());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800570 return;
571 }
572
Hyunsun Moond35420f2016-03-08 21:59:13 -0800573 log.info("VM is detected, MAC: {} IP: {}",
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800574 host.mac(),
575 host.ipAddresses().stream().findFirst().get());
576
Hyunsun Moon576d6872016-04-14 19:04:23 -0700577 CordService service = getCordService(osNet);
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800578 if (service == null) {
579 return;
580 }
581
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800582 switch (service.serviceType()) {
583 case MANAGEMENT:
584 ruleInstaller.populateManagementNetworkRules(host, service);
585 break;
586 case PRIVATE:
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800587 arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
Hyunsun Moon098cda82016-03-03 13:27:44 -0800588 case PUBLIC:
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800589 default:
590 // TODO check if the service needs an update on its group buckets after done CORD-433
591 ruleInstaller.updateServiceGroup(service);
592 // sends gratuitous ARP here for the case of adding existing VMs
593 // when ONOS or cordvtn app is restarted
594 arpProxy.sendGratuitousArpForGateway(service.serviceIp(), Sets.newHashSet(host));
595 break;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800596 }
597
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800598 registerDhcpLease(host, service);
Hyunsun Moon576d6872016-04-14 19:04:23 -0700599 ruleInstaller.populateBasicConnectionRules(host, getTunnelIp(host), osNet);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800600 }
601
602 /**
603 * Handles VM removed situation.
604 *
605 * @param host host
606 */
607 private void serviceVmRemoved(Host host) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700608 checkNotNull(osAccess, "OpenStack access is not set");
609
Hyunsun Moon98025542016-03-08 04:36:02 -0800610 String serviceVlan = host.annotations().value(S_TAG);
611 if (serviceVlan != null) {
612 virtualSubscriberGatewayRemoved(host);
613 }
614
Hyunsun Moon576d6872016-04-14 19:04:23 -0700615 String osNetId = host.annotations().value(SERVICE_ID);
616 if (osNetId == null) {
Hyunsun Moon2a225162016-02-17 19:00:50 -0800617 // ignore it, it's not the service VM or it's a vSG
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800618 return;
619 }
620
Hyunsun Moon576d6872016-04-14 19:04:23 -0700621 OSClient osClient = OSFactory.clientFromAccess(osAccess);
622 Network osNet = osClient.networking().network().get(osNetId);
623 if (osNet == null) {
Hyunsun Moond35420f2016-03-08 21:59:13 -0800624 log.warn("Failed to get OpenStack network {} for VM {}",
Hyunsun Moon576d6872016-04-14 19:04:23 -0700625 osNetId, host.id());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800626 return;
627 }
628
Hyunsun Moond35420f2016-03-08 21:59:13 -0800629 log.info("VM is vanished, MAC: {} IP: {}",
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800630 host.mac(),
631 host.ipAddresses().stream().findFirst().get());
632
633 ruleInstaller.removeBasicConnectionRules(host);
Hyunsun Moonfb631b42016-02-03 14:44:06 -0800634 dhcpService.removeStaticMapping(host.mac());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800635
Hyunsun Moon576d6872016-04-14 19:04:23 -0700636 CordService service = getCordService(osNet);
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800637 if (service == null) {
638 return;
639 }
640
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800641 switch (service.serviceType()) {
642 case MANAGEMENT:
643 ruleInstaller.removeManagementNetworkRules(host, service);
644 break;
645 case PRIVATE:
Hyunsun Moon576d6872016-04-14 19:04:23 -0700646 if (getHostsWithOpenstackNetwork(osNet).isEmpty()) {
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800647 arpProxy.removeGateway(service.serviceIp());
648 }
Hyunsun Moon098cda82016-03-03 13:27:44 -0800649 case PUBLIC:
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800650 default:
651 // TODO check if the service needs an update on its group buckets after done CORD-433
652 ruleInstaller.updateServiceGroup(service);
653 break;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700654 }
655 }
656
Hyunsun Moon98025542016-03-08 04:36:02 -0800657
658 /**
659 * Handles virtual subscriber gateway VM or container.
660 *
661 * @param host new host with stag, it can be vsg VM or vsg
662 * @param serviceVlan service vlan
663 */
664 private void virtualSubscriberGatewayAdded(Host host, String serviceVlan) {
665 Map<IpAddress, MacAddress> vSgs;
666 Host vSgHost;
667
668 String vSgHostId = host.annotations().value(VSG_HOST_ID);
669 if (vSgHostId == null) {
670 log.debug("vSG VM detected {}", host.id());
671
672 vSgHost = host;
673 vSgs = getSubscriberGateways(vSgHost);
674 vSgs.entrySet().stream().forEach(entry -> addVirtualSubscriberGateway(
675 vSgHost,
676 entry.getKey(),
677 entry.getValue(),
678 serviceVlan));
679 } else {
680 vSgHost = hostService.getHost(HostId.hostId(vSgHostId));
681 if (vSgHost == null) {
682 return;
683 }
684
685 log.debug("vSG detected {}", host.id());
686 vSgs = getSubscriberGateways(vSgHost);
687 }
688
689 ruleInstaller.populateSubscriberGatewayRules(vSgHost, vSgs.keySet());
690 }
691
692 /**
693 * Handles virtual subscriber gateway removed.
694 *
695 * @param vSg vsg host to remove
696 */
697 private void virtualSubscriberGatewayRemoved(Host vSg) {
698 String vSgHostId = vSg.annotations().value(VSG_HOST_ID);
699 if (vSgHostId == null) {
700 return;
701 }
702
703 Host vSgHost = hostService.getHost(HostId.hostId(vSgHostId));
704 if (vSgHost == null) {
705 return;
706 }
707
708 log.info("vSG removed {}", vSg.id());
709 Map<IpAddress, MacAddress> vSgs = getSubscriberGateways(vSgHost);
710 ruleInstaller.populateSubscriberGatewayRules(vSgHost, vSgs.keySet());
711 }
712
Hyunsun Moon746956f2016-01-24 21:47:06 -0800713 /**
714 * Sets service network gateway MAC address and sends out gratuitous ARP to all
715 * VMs to update the gateway MAC address.
716 *
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800717 * @param newMac mac address to update
Hyunsun Moon746956f2016-01-24 21:47:06 -0800718 */
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800719 private void setPrivateGatewayMac(MacAddress newMac) {
720 if (newMac == null || newMac.equals(privateGatewayMac)) {
721 // no updates, do nothing
722 return;
Hyunsun Moon746956f2016-01-24 21:47:06 -0800723 }
724
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800725 privateGatewayMac = newMac;
726 log.debug("Set service gateway MAC address to {}", privateGatewayMac.toString());
727
Hyunsun Moon746956f2016-01-24 21:47:06 -0800728 // TODO get existing service list from XOS and replace the loop below
729 Set<String> vNets = Sets.newHashSet();
730 hostService.getHosts().forEach(host -> vNets.add(host.annotations().value(SERVICE_ID)));
731 vNets.remove(null);
732
733 vNets.stream().forEach(vNet -> {
734 CordService service = getCordService(CordServiceId.of(vNet));
735 if (service != null) {
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800736 arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
737 arpProxy.sendGratuitousArpForGateway(service.serviceIp(), service.hosts().keySet());
Hyunsun Moon746956f2016-01-24 21:47:06 -0800738 }
739 });
740 }
741
742 /**
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800743 * Sets public gateway MAC address.
744 *
745 * @param publicGateways gateway ip and mac address pairs
746 */
747 private void setPublicGatewayMac(Map<IpAddress, MacAddress> publicGateways) {
748 publicGateways.entrySet()
749 .stream()
750 .forEach(entry -> {
751 arpProxy.addGateway(entry.getKey(), entry.getValue());
Hyunsun Moon576d6872016-04-14 19:04:23 -0700752 log.debug("Added public gateway IP {}, MAC {}",
753 entry.getKey().toString(), entry.getValue().toString());
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800754 });
755 // TODO notice gateway MAC change to VMs holds this gateway IP
756 }
757
758 /**
Hyunsun Moon576d6872016-04-14 19:04:23 -0700759 * Sets OpenStack access information.
760 * Access is the entity returned when authenticated and provides a singleton client
761 * between multiple threads.
762 *
763 * @param osConfig openstack config
764 */
765 private void setOpenstackAccess(CordVtnConfig.OpenStackConfig osConfig) {
766 log.debug("Get OpenStack access with Endpoint: {} Tenant: {} User: {} Passwd: {}",
767 osConfig.endpoint(),
768 osConfig.tenant(),
769 osConfig.user(),
770 osConfig.password());
771 try {
772 osAccess = OSFactory.builder()
773 .endpoint(osConfig.endpoint())
774 .credentials(osConfig.user(), osConfig.password())
775 .tenantName(osConfig.tenant())
776 .authenticate()
777 .getAccess();
778 } catch (AuthenticationException e) {
779 log.error("Failed to get OpenStack Access");
780 }
781 }
782
783 /**
Hyunsun Moon746956f2016-01-24 21:47:06 -0800784 * Updates configurations.
785 */
786 private void readConfiguration() {
787 CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
788 if (config == null) {
789 log.debug("No configuration found");
790 return;
791 }
792
Hyunsun Moon576d6872016-04-14 19:04:23 -0700793 setOpenstackAccess(config.openstackConfig());
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800794 setPrivateGatewayMac(config.privateGatewayMac());
795 setPublicGatewayMac(config.publicGateways());
Hyunsun Moon576d6872016-04-14 19:04:23 -0700796 }
Hyunsun Moon746956f2016-01-24 21:47:06 -0800797
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700798 private class InternalHostListener implements HostListener {
799
800 @Override
801 public void event(HostEvent event) {
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800802 Host host = event.subject();
Hyunsun Moond35420f2016-03-08 21:59:13 -0800803 if (!mastershipService.isLocalMaster(host.location().deviceId())) {
804 // do not allow to proceed without mastership
805 return;
806 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700807
808 switch (event.type()) {
Hyunsun Moond35420f2016-03-08 21:59:13 -0800809 case HOST_UPDATED:
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700810 case HOST_ADDED:
Hyunsun Moond35420f2016-03-08 21:59:13 -0800811 eventExecutor.submit(() -> serviceVmAdded(host));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700812 break;
813 case HOST_REMOVED:
Hyunsun Moond35420f2016-03-08 21:59:13 -0800814 eventExecutor.submit(() -> serviceVmRemoved(host));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700815 break;
816 default:
817 break;
818 }
819 }
820 }
821
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800822 private class InternalPacketProcessor implements PacketProcessor {
823
824 @Override
825 public void process(PacketContext context) {
826 if (context.isHandled()) {
827 return;
828 }
829
830 Ethernet ethPacket = context.inPacket().parsed();
Hyunsun Moon746956f2016-01-24 21:47:06 -0800831 if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800832 return;
833 }
834
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800835 arpProxy.processArpPacket(context, ethPacket);
Hyunsun Moon746956f2016-01-24 21:47:06 -0800836 }
837 }
838
839 private class InternalConfigListener implements NetworkConfigListener {
840
841 @Override
842 public void event(NetworkConfigEvent event) {
843 if (!event.configClass().equals(CordVtnConfig.class)) {
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800844 return;
845 }
846
Hyunsun Moon746956f2016-01-24 21:47:06 -0800847 switch (event.type()) {
848 case CONFIG_ADDED:
849 case CONFIG_UPDATED:
850 log.info("Network configuration changed");
851 eventExecutor.execute(CordVtn.this::readConfiguration);
852 break;
853 default:
854 break;
855 }
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800856 }
857 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700858}