blob: 0a7b77d155eddabf0010a4cfc6562efdb723d056 [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 Moondd91be22016-04-24 17:43:32 -070069import org.onosproject.xosclient.api.XosAccess;
70import org.onosproject.xosclient.api.XosClientService;
Hyunsun Moon576d6872016-04-14 19:04:23 -070071import 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 Moond0e932a2015-09-15 22:39:16 -070077import org.slf4j.Logger;
78
Hyunsun Moon1d3eac92016-02-03 00:11:11 -080079import java.util.List;
Hyunsun Moon1f145552015-10-08 22:25:30 -070080import java.util.Map;
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -080081import java.util.Objects;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080082import java.util.Set;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070083import java.util.concurrent.ExecutorService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080084import java.util.stream.Collectors;
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -080085import java.util.stream.StreamSupport;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070086
Hyunsun Moon1f145552015-10-08 22:25:30 -070087import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moon746956f2016-01-24 21:47:06 -080088import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070089import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070090import static org.slf4j.LoggerFactory.getLogger;
91
92/**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080093 * Provisions virtual tenant networks with service chaining capability
94 * in OpenStack environment.
Hyunsun Moond0e932a2015-09-15 22:39:16 -070095 */
96@Component(immediate = true)
97@Service
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080098public class CordVtn extends AbstractProvider implements CordVtnService, HostProvider {
Hyunsun Moond0e932a2015-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 Moon746956f2016-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 Moonb77b60f2016-01-15 20:03:18 -0800112 protected HostProviderRegistry hostProviderRegistry;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700113
114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700115 protected DeviceService deviceService;
116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected HostService hostService;
119
Hyunsun Moon1f145552015-10-08 22:25:30 -0700120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800121 protected FlowRuleService flowRuleService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800124 protected PacketService packetService;
125
126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800127 protected MastershipService mastershipService;
128
129 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
130 protected GroupService groupService;
131
132 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800133 protected DhcpService dhcpService;
134
Hyunsun Moondd91be22016-04-24 17:43:32 -0700135 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
136 protected XosClientService xosClient;
137
Hyunsun Moon746956f2016-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 Moonb77b60f2016-01-15 20:03:18 -0800146 private static final String DEFAULT_TUNNEL = "vxlan";
147 private static final String SERVICE_ID = "serviceId";
Hyunsun Moon6d247342016-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 Moon98025542016-03-08 04:36:02 -0800152 private static final String VSG_HOST_ID = "vsgHostId";
Hyunsun Moond35420f2016-03-08 21:59:13 -0800153 private static final String CREATED_TIME = "createdTime";
Hyunsun Moon6d247342016-02-12 12:48:47 -0800154
155 private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800156
Hyunsun Moon746956f2016-01-24 21:47:06 -0800157 private final ExecutorService eventExecutor =
158 newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "event-handler"));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700159
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800160 private final PacketProcessor packetProcessor = new InternalPacketProcessor();
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800161 private final HostListener hostListener = new InternalHostListener();
Hyunsun Moon746956f2016-01-24 21:47:06 -0800162 private final NetworkConfigListener configListener = new InternalConfigListener();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700163
Hyunsun Moon746956f2016-01-24 21:47:06 -0800164 private ApplicationId appId;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800165 private HostProviderService hostProvider;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800166 private CordVtnRuleInstaller ruleInstaller;
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800167 private CordVtnArpProxy arpProxy;
Hyunsun Moon576d6872016-04-14 19:04:23 -0700168
169 private volatile Access osAccess = null;
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800170 private volatile MacAddress privateGatewayMac = MacAddress.NONE;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800171
Hyunsun Moonb77b60f2016-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 Moon8539b042015-11-07 22:08:43 -0800177 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700178
179 @Activate
180 protected void activate() {
Hyunsun Moon746956f2016-01-24 21:47:06 -0800181 appId = coreService.registerApplication("org.onosproject.cordvtn");
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800182 ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService,
183 deviceService,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800184 groupService,
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800185 configRegistry,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800186 DEFAULT_TUNNEL);
187
Hyunsun Moon9cf43db2016-02-12 15:59:53 -0800188 arpProxy = new CordVtnArpProxy(appId, packetService, hostService);
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800189 packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
190 arpProxy.requestPacket();
191
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700192 hostService.addListener(hostListener);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800193 hostProvider = hostProviderRegistry.register(this);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700194
Hyunsun Moon746956f2016-01-24 21:47:06 -0800195 configRegistry.registerConfigFactory(configFactory);
196 configService.addListener(configListener);
Hyunsun Moon746956f2016-01-24 21:47:06 -0800197
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700198 log.info("Started");
199 }
200
201 @Deactivate
202 protected void deactivate() {
Hyunsun Moon746956f2016-01-24 21:47:06 -0800203 hostProviderRegistry.unregister(this);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700204 hostService.removeListener(hostListener);
Hyunsun Moon746956f2016-01-24 21:47:06 -0800205
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800206 packetService.removeProcessor(packetProcessor);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700207
Hyunsun Moon746956f2016-01-24 21:47:06 -0800208 configRegistry.unregisterConfigFactory(configFactory);
209 configService.removeListener(configListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700210
Hyunsun Moon746956f2016-01-24 21:47:06 -0800211 eventExecutor.shutdown();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700212 log.info("Stopped");
213 }
214
215 @Override
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800216 public void triggerProbe(Host host) {
217 /*
218 * Note: In CORD deployment, we assume that all hosts are configured.
219 * Therefore no probe is required.
220 */
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800221 }
222
223 @Override
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800224 public void createServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId,
225 boolean isBidirectional) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800226 CordService tService = getCordService(tServiceId);
227 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800228
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800229 if (tService == null || pService == null) {
230 log.error("Failed to create CordService for {}", tServiceId.id());
231 return;
232 }
233
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800234 log.info("Service dependency from {} to {} created.", tService.id().id(), pService.id().id());
Hyunsun Moonc14be422016-04-27 15:06:56 -0500235 ruleInstaller.populateServiceDependencyRules(tService, pService, isBidirectional, true);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800236 }
237
238 @Override
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800239 public void removeServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId) {
240 CordService tService = getCordService(tServiceId);
241 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800242
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800243 if (tService == null || pService == null) {
244 log.error("Failed to create CordService for {}", tServiceId.id());
245 return;
246 }
247
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800248 log.info("Service dependency from {} to {} removed.", tService.id().id(), pService.id().id());
Hyunsun Moonc14be422016-04-27 15:06:56 -0500249 ruleInstaller.populateServiceDependencyRules(tService, pService, true, false);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800250 }
251
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800252 @Override
253 public void addServiceVm(CordVtnNode node, ConnectPoint connectPoint) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700254 checkNotNull(osAccess, "OpenStack access is not set");
255
256 OSClient osClient = OSFactory.clientFromAccess(osAccess);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800257 Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
Hyunsun Moon576d6872016-04-14 19:04:23 -0700258 org.openstack4j.model.network.Port osPort = osClient.networking().port().list()
259 .stream()
260 .filter(p -> p.getId().contains(getPortName(port).substring(3)))
261 .findFirst().orElse(null);
262 if (osPort == null) {
263 log.warn("Failed to get OpenStack port for {}", getPortName(port));
Hyunsun Moon8539b042015-11-07 22:08:43 -0800264 return;
265 }
266
Hyunsun Moon576d6872016-04-14 19:04:23 -0700267 MacAddress mac = MacAddress.valueOf(osPort.getMacAddress());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800268 HostId hostId = HostId.hostId(mac);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800269
Hyunsun Moond35420f2016-03-08 21:59:13 -0800270 Host existingHost = hostService.getHost(hostId);
271 if (existingHost != null) {
272 String serviceId = existingHost.annotations().value(SERVICE_ID);
Hyunsun Moon576d6872016-04-14 19:04:23 -0700273 if (serviceId == null || !serviceId.equals(osPort.getNetworkId())) {
Hyunsun Moond35420f2016-03-08 21:59:13 -0800274 // this host is not injected by cordvtn or a stale host, remove it
275 hostProvider.hostVanished(existingHost.id());
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800276 }
Hyunsun Moon8539b042015-11-07 22:08:43 -0800277 }
278
Hyunsun Moond35420f2016-03-08 21:59:13 -0800279 // Included CREATED_TIME to annotation intentionally to trigger HOST_UPDATED
280 // event so that the flow rule population for this host can happen.
281 // This ensures refreshing data plane by pushing network config always make
282 // the data plane synced.
Hyunsun Moon576d6872016-04-14 19:04:23 -0700283 Set<IpAddress> fixedIps = osPort.getFixedIps().stream()
284 .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
285 .collect(Collectors.toSet());
286
Hyunsun Moon6d247342016-02-12 12:48:47 -0800287 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
Hyunsun Moon576d6872016-04-14 19:04:23 -0700288 .set(SERVICE_ID, osPort.getNetworkId())
289 .set(OPENSTACK_PORT_ID, osPort.getId())
Hyunsun Moon6d247342016-02-12 12:48:47 -0800290 .set(DATA_PLANE_IP, node.dpIp().ip().toString())
Hyunsun Moond35420f2016-03-08 21:59:13 -0800291 .set(DATA_PLANE_INTF, node.dpIntf())
292 .set(CREATED_TIME, String.valueOf(System.currentTimeMillis()));
Hyunsun Moon6d247342016-02-12 12:48:47 -0800293
Hyunsun Moon576d6872016-04-14 19:04:23 -0700294 String serviceVlan = getServiceVlan(osPort);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800295 if (serviceVlan != null) {
296 annotations.set(S_TAG, serviceVlan);
297 }
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800298
299 HostDescription hostDesc = new DefaultHostDescription(
300 mac,
301 VlanId.NONE,
302 new HostLocation(connectPoint, System.currentTimeMillis()),
Hyunsun Moon576d6872016-04-14 19:04:23 -0700303 fixedIps,
Hyunsun Moon6d247342016-02-12 12:48:47 -0800304 annotations.build());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800305
306 hostProvider.hostDetected(hostId, hostDesc, false);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800307 }
308
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800309 @Override
310 public void removeServiceVm(ConnectPoint connectPoint) {
Hyunsun Moon2a225162016-02-17 19:00:50 -0800311 hostService.getConnectedHosts(connectPoint)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800312 .stream()
Hyunsun Moon2a225162016-02-17 19:00:50 -0800313 .forEach(host -> hostProvider.hostVanished(host.id()));
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800314 }
315
Hyunsun Moon6d247342016-02-12 12:48:47 -0800316 @Override
317 public void updateVirtualSubscriberGateways(HostId vSgHostId, String serviceVlan,
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800318 Map<IpAddress, MacAddress> vSgs) {
Hyunsun Moon98025542016-03-08 04:36:02 -0800319 Host vSgHost = hostService.getHost(vSgHostId);
320 if (vSgHost == null || !vSgHost.annotations().value(S_TAG).equals(serviceVlan)) {
Hyunsun Moon6d247342016-02-12 12:48:47 -0800321 log.debug("Invalid vSG updates for {}", serviceVlan);
322 return;
323 }
324
Hyunsun Moon98025542016-03-08 04:36:02 -0800325 log.info("Updates vSGs in {} with {}", vSgHost.id(), vSgs.toString());
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800326 vSgs.entrySet().stream()
Hyunsun Moon98025542016-03-08 04:36:02 -0800327 .filter(entry -> hostService.getHostsByMac(entry.getValue()).isEmpty())
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800328 .forEach(entry -> addVirtualSubscriberGateway(
Hyunsun Moon98025542016-03-08 04:36:02 -0800329 vSgHost,
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800330 entry.getKey(),
331 entry.getValue(),
332 serviceVlan));
333
Hyunsun Moon98025542016-03-08 04:36:02 -0800334 hostService.getConnectedHosts(vSgHost.location()).stream()
335 .filter(host -> !host.mac().equals(vSgHost.mac()))
Hyunsun Moon2a225162016-02-17 19:00:50 -0800336 .filter(host -> !vSgs.values().contains(host.mac()))
337 .forEach(host -> {
338 log.info("Removed vSG {}", host.toString());
339 hostProvider.hostVanished(host.id());
340 });
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800341 }
342
343 /**
344 * Adds virtual subscriber gateway to the system.
345 *
346 * @param vSgHost host virtual machine of this vSG
347 * @param vSgIp vSG ip address
348 * @param vSgMac vSG mac address
349 * @param serviceVlan service vlan
350 */
Hyunsun Moon2a225162016-02-17 19:00:50 -0800351 private void addVirtualSubscriberGateway(Host vSgHost, IpAddress vSgIp, MacAddress vSgMac,
352 String serviceVlan) {
Hyunsun Moon98025542016-03-08 04:36:02 -0800353 log.info("vSG with IP({}) MAC({}) added", vSgIp.toString(), vSgMac.toString());
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800354
Hyunsun Moon98025542016-03-08 04:36:02 -0800355 HostId hostId = HostId.hostId(vSgMac);
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800356 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
Hyunsun Moon98025542016-03-08 04:36:02 -0800357 .set(S_TAG, serviceVlan)
Hyunsun Moond35420f2016-03-08 21:59:13 -0800358 .set(VSG_HOST_ID, vSgHost.id().toString())
359 .set(CREATED_TIME, String.valueOf(System.currentTimeMillis()));
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800360
361 HostDescription hostDesc = new DefaultHostDescription(
362 vSgMac,
363 VlanId.NONE,
364 vSgHost.location(),
365 Sets.newHashSet(vSgIp),
366 annotations.build());
367
368 hostProvider.hostDetected(hostId, hostDesc, false);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800369 }
370
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800371 /**
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800372 * Returns public ip addresses of vSGs running inside a give vSG host.
373 *
374 * @param vSgHost vSG host
375 * @return map of ip and mac address, or empty map
376 */
377 private Map<IpAddress, MacAddress> getSubscriberGateways(Host vSgHost) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700378 checkNotNull(osAccess, "OpenStack access is not set");
379
380 String osPortId = vSgHost.annotations().value(OPENSTACK_PORT_ID);
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800381 String serviceVlan = vSgHost.annotations().value(S_TAG);
382
Hyunsun Moon576d6872016-04-14 19:04:23 -0700383 OSClient osClient = OSFactory.clientFromAccess(osAccess);
384 org.openstack4j.model.network.Port osPort = osClient.networking().port().get(osPortId);
385 if (osPort == null) {
386 log.warn("Failed to get OpenStack port {} for VM {}", osPortId, vSgHost.id());
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800387 return Maps.newHashMap();
388 }
389
Hyunsun Moon576d6872016-04-14 19:04:23 -0700390 if (!serviceVlan.equals(getServiceVlan(osPort))) {
391 log.error("Host({}) s-tag does not match with OpenStack port s-tag", vSgHost.id());
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800392 return Maps.newHashMap();
393 }
394
Hyunsun Moon576d6872016-04-14 19:04:23 -0700395 Map<IpAddress, MacAddress> addressPairs = Maps.newHashMap();
396 osPort.getAllowedAddressPairs()
397 .stream().forEach(p -> addressPairs.put(
398 IpAddress.valueOf(p.getIpAddress()),
399 MacAddress.valueOf(p.getMacAddress())));
400
401 return addressPairs;
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800402 }
403
404 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800405 * Returns CordService by service ID.
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800406 *
407 * @param serviceId service id
408 * @return cord service, or null if it fails to get network from OpenStack
409 */
410 private CordService getCordService(CordServiceId serviceId) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700411 checkNotNull(osAccess, "OpenStack access is not set");
412
413 OSClient osClient = OSFactory.clientFromAccess(osAccess);
414 Network osNet = osClient.networking().network().get(serviceId.id());
415 if (osNet == null) {
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800416 log.warn("Couldn't find OpenStack network for service {}", serviceId.id());
417 return null;
418 }
419
Hyunsun Moondd91be22016-04-24 17:43:32 -0700420 return getCordService(osNet);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800421 }
422
423 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800424 * Returns CordService by OpenStack network.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800425 *
Hyunsun Moon576d6872016-04-14 19:04:23 -0700426 * @param osNet OpenStack network
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800427 * @return cord service
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800428 */
Hyunsun Moon576d6872016-04-14 19:04:23 -0700429 private CordService getCordService(Network osNet) {
430 checkNotNull(osNet);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800431
Hyunsun Moon576d6872016-04-14 19:04:23 -0700432 CordServiceId serviceId = CordServiceId.of(osNet.getId());
433 // here it assumes all cord service networks has only one subnet
434 Subnet osSubnet = osNet.getNeutronSubnets().stream()
Hyunsun Moonc14be422016-04-27 15:06:56 -0500435 .findFirst().orElse(null);
Hyunsun Moon576d6872016-04-14 19:04:23 -0700436 if (osSubnet == null) {
Hyunsun Moonc14be422016-04-27 15:06:56 -0500437 log.warn("Couldn't find OpenStack subnet for network {}", serviceId.id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800438 return null;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800439 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800440
Hyunsun Moon576d6872016-04-14 19:04:23 -0700441 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(osNet)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800442 .stream()
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800443 .collect(Collectors.toMap(host -> host, this::getTunnelIp));
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800444
Hyunsun Moondd91be22016-04-24 17:43:32 -0700445 // allows working without XOS for now
446 Set<CordServiceId> tServices = Sets.newHashSet();
447 Set<CordServiceId> pServices = Sets.newHashSet();
448
Hyunsun Moonc14be422016-04-27 15:06:56 -0500449 if (xosClient.access() != null) {
Hyunsun Moondd91be22016-04-24 17:43:32 -0700450 tServices = xosClient.vtnServiceApi().getTenantServices(serviceId.id())
451 .stream()
452 .map(CordServiceId::of)
453 .collect(Collectors.toSet());
454
455 pServices = xosClient.vtnServiceApi().getProviderServices(serviceId.id())
456 .stream()
457 .map(CordServiceId::of)
458 .collect(Collectors.toSet());
459 }
460
461 return new CordService(osNet, osSubnet, hosts, tServices, pServices);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800462 }
463
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800464 /**
465 * Returns IP address for tunneling for a given host.
466 *
467 * @param host host
Hyunsun Moon6d247342016-02-12 12:48:47 -0800468 * @return ip address, or null
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800469 */
470 private IpAddress getTunnelIp(Host host) {
Hyunsun Moon6d247342016-02-12 12:48:47 -0800471 String ip = host.annotations().value(DATA_PLANE_IP);
472 return ip == null ? null : IpAddress.valueOf(ip);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800473 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700474
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800475 /**
476 * Returns port name.
477 *
478 * @param port port
479 * @return port name
480 */
481 private String getPortName(Port port) {
482 return port.annotations().value("portName");
483 }
Hyunsun Moon8539b042015-11-07 22:08:43 -0800484
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800485 /**
Hyunsun Moon6d247342016-02-12 12:48:47 -0800486 * Returns s-tag from a given OpenStack port.
487 *
Hyunsun Moon576d6872016-04-14 19:04:23 -0700488 * @param osPort openstack port
Hyunsun Moon6d247342016-02-12 12:48:47 -0800489 * @return s-tag string
490 */
Hyunsun Moon576d6872016-04-14 19:04:23 -0700491 private String getServiceVlan(org.openstack4j.model.network.Port osPort) {
492 checkNotNull(osPort);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800493
Hyunsun Moon576d6872016-04-14 19:04:23 -0700494 String portName = osPort.getName();
495 if (portName != null && portName.startsWith(S_TAG)) {
496 return portName.split("-")[1];
Hyunsun Moon6d247342016-02-12 12:48:47 -0800497 } else {
498 return null;
499 }
500 }
501
502 /**
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800503 * Returns service ID of this host.
504 *
505 * @param host host
506 * @return service id, or null if not found
507 */
508 private String getServiceId(Host host) {
509 return host.annotations().value(SERVICE_ID);
510 }
511
512 /**
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800513 * Returns hosts associated with a given OpenStack network.
514 *
Hyunsun Moon576d6872016-04-14 19:04:23 -0700515 * @param osNet openstack network
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800516 * @return set of hosts
517 */
Hyunsun Moon576d6872016-04-14 19:04:23 -0700518 private Set<Host> getHostsWithOpenstackNetwork(Network osNet) {
519 checkNotNull(osNet);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700520
Hyunsun Moon576d6872016-04-14 19:04:23 -0700521 String osNetId = osNet.getId();
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800522 return StreamSupport.stream(hostService.getHosts().spliterator(), false)
Hyunsun Moon576d6872016-04-14 19:04:23 -0700523 .filter(host -> Objects.equals(osNetId, getServiceId(host)))
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800524 .collect(Collectors.toSet());
Hyunsun Moon6d247342016-02-12 12:48:47 -0800525 }
526
527 /**
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800528 * Registers static DHCP lease for a given host.
529 *
530 * @param host host
531 * @param service cord service
532 */
533 private void registerDhcpLease(Host host, CordService service) {
534 List<Ip4Address> options = Lists.newArrayList();
535 options.add(Ip4Address.makeMaskPrefix(service.serviceIpRange().prefixLength()));
536 options.add(service.serviceIp().getIp4Address());
537 options.add(service.serviceIp().getIp4Address());
538 options.add(DEFAULT_DNS);
539
540 log.debug("Set static DHCP mapping for {}", host.mac());
541 dhcpService.setStaticMapping(host.mac(),
542 host.ipAddresses().stream().findFirst().get().getIp4Address(),
543 true,
544 options);
545 }
546
547 /**
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800548 * Handles VM detected situation.
549 *
550 * @param host host
551 */
552 private void serviceVmAdded(Host host) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700553 checkNotNull(osAccess, "OpenStack access is not set");
554
Hyunsun Moon98025542016-03-08 04:36:02 -0800555 String serviceVlan = host.annotations().value(S_TAG);
556 if (serviceVlan != null) {
557 virtualSubscriberGatewayAdded(host, serviceVlan);
558 }
559
Hyunsun Moonc14be422016-04-27 15:06:56 -0500560 String serviceId = host.annotations().value(SERVICE_ID);
561 if (serviceId == null) {
562 // ignore this host, it is not a service VM
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800563 return;
564 }
565
Hyunsun Moonc14be422016-04-27 15:06:56 -0500566 log.info("VM is detected, MAC: {} IP: {}", host.mac(), host.ipAddresses());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800567
Hyunsun Moonc14be422016-04-27 15:06:56 -0500568 CordService service = getCordService(CordServiceId.of(serviceId));
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800569 if (service == null) {
Hyunsun Moonc14be422016-04-27 15:06:56 -0500570 log.warn("Failed to get CordService for {}", serviceId);
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800571 return;
572 }
573
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800574 switch (service.serviceType()) {
575 case MANAGEMENT:
576 ruleInstaller.populateManagementNetworkRules(host, service);
577 break;
578 case PRIVATE:
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800579 arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
Hyunsun Moon098cda82016-03-03 13:27:44 -0800580 case PUBLIC:
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800581 default:
Hyunsun Moondd91be22016-04-24 17:43:32 -0700582 // TODO get bidirectional information from XOS once XOS supports
583 service.tenantServices().stream().forEach(
584 tServiceId -> createServiceDependency(tServiceId, service.id(), true));
585 service.providerServices().stream().forEach(
586 pServiceId -> createServiceDependency(service.id(), pServiceId, true));
587
Hyunsun Moonc14be422016-04-27 15:06:56 -0500588 ruleInstaller.updateProviderServiceGroup(service);
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800589 // sends gratuitous ARP here for the case of adding existing VMs
590 // when ONOS or cordvtn app is restarted
591 arpProxy.sendGratuitousArpForGateway(service.serviceIp(), Sets.newHashSet(host));
592 break;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800593 }
594
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800595 registerDhcpLease(host, service);
Hyunsun Moonc14be422016-04-27 15:06:56 -0500596 ruleInstaller.populateBasicConnectionRules(host, service, true);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800597 }
598
599 /**
600 * Handles VM removed situation.
601 *
602 * @param host host
603 */
604 private void serviceVmRemoved(Host host) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700605 checkNotNull(osAccess, "OpenStack access is not set");
606
Hyunsun Moonc14be422016-04-27 15:06:56 -0500607 if (host.annotations().value(S_TAG) != null) {
Hyunsun Moon98025542016-03-08 04:36:02 -0800608 virtualSubscriberGatewayRemoved(host);
609 }
610
Hyunsun Moonc14be422016-04-27 15:06:56 -0500611 String serviceId = host.annotations().value(SERVICE_ID);
612 if (serviceId == null) {
613 // ignore it, it's not a service VM
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800614 return;
615 }
616
Hyunsun Moonc14be422016-04-27 15:06:56 -0500617 log.info("VM is vanished, MAC: {} IP: {}", host.mac(), host.ipAddresses());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800618
Hyunsun Moonc14be422016-04-27 15:06:56 -0500619 CordService service = getCordService(CordServiceId.of(serviceId));
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800620 if (service == null) {
Hyunsun Moonc14be422016-04-27 15:06:56 -0500621 log.warn("Failed to get CORD service for {}", serviceId);
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800622 return;
623 }
Hyunsun Moonc14be422016-04-27 15:06:56 -0500624 // TODO need to consider the case that the network is removed also
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800625
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800626 switch (service.serviceType()) {
627 case MANAGEMENT:
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800628 break;
629 case PRIVATE:
Hyunsun Moonc14be422016-04-27 15:06:56 -0500630 if (service.hosts().isEmpty()) {
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800631 arpProxy.removeGateway(service.serviceIp());
632 }
Hyunsun Moon098cda82016-03-03 13:27:44 -0800633 case PUBLIC:
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800634 default:
Hyunsun Moondd91be22016-04-24 17:43:32 -0700635 if (!service.tenantServices().isEmpty()) {
Hyunsun Moonc14be422016-04-27 15:06:56 -0500636 ruleInstaller.updateProviderServiceGroup(service);
637 }
638 if (!service.providerServices().isEmpty()) {
639 ruleInstaller.updateTenantServiceVm(host, service);
Hyunsun Moondd91be22016-04-24 17:43:32 -0700640 }
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800641 break;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700642 }
Hyunsun Moonc14be422016-04-27 15:06:56 -0500643
644 dhcpService.removeStaticMapping(host.mac());
645 ruleInstaller.populateBasicConnectionRules(host, service, false);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700646 }
647
Hyunsun Moon98025542016-03-08 04:36:02 -0800648
649 /**
650 * Handles virtual subscriber gateway VM or container.
651 *
652 * @param host new host with stag, it can be vsg VM or vsg
653 * @param serviceVlan service vlan
654 */
655 private void virtualSubscriberGatewayAdded(Host host, String serviceVlan) {
656 Map<IpAddress, MacAddress> vSgs;
657 Host vSgHost;
658
659 String vSgHostId = host.annotations().value(VSG_HOST_ID);
660 if (vSgHostId == null) {
661 log.debug("vSG VM detected {}", host.id());
662
663 vSgHost = host;
664 vSgs = getSubscriberGateways(vSgHost);
665 vSgs.entrySet().stream().forEach(entry -> addVirtualSubscriberGateway(
666 vSgHost,
667 entry.getKey(),
668 entry.getValue(),
669 serviceVlan));
670 } else {
671 vSgHost = hostService.getHost(HostId.hostId(vSgHostId));
672 if (vSgHost == null) {
673 return;
674 }
675
676 log.debug("vSG detected {}", host.id());
677 vSgs = getSubscriberGateways(vSgHost);
678 }
679
680 ruleInstaller.populateSubscriberGatewayRules(vSgHost, vSgs.keySet());
681 }
682
683 /**
684 * Handles virtual subscriber gateway removed.
685 *
686 * @param vSg vsg host to remove
687 */
688 private void virtualSubscriberGatewayRemoved(Host vSg) {
689 String vSgHostId = vSg.annotations().value(VSG_HOST_ID);
690 if (vSgHostId == null) {
691 return;
692 }
693
694 Host vSgHost = hostService.getHost(HostId.hostId(vSgHostId));
695 if (vSgHost == null) {
696 return;
697 }
698
699 log.info("vSG removed {}", vSg.id());
700 Map<IpAddress, MacAddress> vSgs = getSubscriberGateways(vSgHost);
701 ruleInstaller.populateSubscriberGatewayRules(vSgHost, vSgs.keySet());
702 }
703
Hyunsun Moon746956f2016-01-24 21:47:06 -0800704 /**
705 * Sets service network gateway MAC address and sends out gratuitous ARP to all
706 * VMs to update the gateway MAC address.
707 *
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800708 * @param newMac mac address to update
Hyunsun Moon746956f2016-01-24 21:47:06 -0800709 */
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800710 private void setPrivateGatewayMac(MacAddress newMac) {
Hyunsun Moondd91be22016-04-24 17:43:32 -0700711 checkNotNull(osAccess, "OpenStack access is not set");
712
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800713 if (newMac == null || newMac.equals(privateGatewayMac)) {
714 // no updates, do nothing
715 return;
Hyunsun Moon746956f2016-01-24 21:47:06 -0800716 }
717
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800718 privateGatewayMac = newMac;
719 log.debug("Set service gateway MAC address to {}", privateGatewayMac.toString());
720
Hyunsun Moondd91be22016-04-24 17:43:32 -0700721 OSClient osClient = OSFactory.clientFromAccess(osAccess);
722 List<Network> vNets = Lists.newArrayList(osClient.networking().network().list().iterator());
Hyunsun Moon746956f2016-01-24 21:47:06 -0800723
724 vNets.stream().forEach(vNet -> {
Hyunsun Moondd91be22016-04-24 17:43:32 -0700725 CordService service = getCordService(vNet);
Hyunsun Moon746956f2016-01-24 21:47:06 -0800726 if (service != null) {
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800727 arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
728 arpProxy.sendGratuitousArpForGateway(service.serviceIp(), service.hosts().keySet());
Hyunsun Moon746956f2016-01-24 21:47:06 -0800729 }
730 });
731 }
732
733 /**
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800734 * Sets public gateway MAC address.
735 *
736 * @param publicGateways gateway ip and mac address pairs
737 */
738 private void setPublicGatewayMac(Map<IpAddress, MacAddress> publicGateways) {
739 publicGateways.entrySet()
740 .stream()
741 .forEach(entry -> {
742 arpProxy.addGateway(entry.getKey(), entry.getValue());
Hyunsun Moon576d6872016-04-14 19:04:23 -0700743 log.debug("Added public gateway IP {}, MAC {}",
744 entry.getKey().toString(), entry.getValue().toString());
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800745 });
746 // TODO notice gateway MAC change to VMs holds this gateway IP
747 }
748
749 /**
Hyunsun Moon576d6872016-04-14 19:04:23 -0700750 * Sets OpenStack access information.
751 * Access is the entity returned when authenticated and provides a singleton client
752 * between multiple threads.
753 *
754 * @param osConfig openstack config
755 */
756 private void setOpenstackAccess(CordVtnConfig.OpenStackConfig osConfig) {
Hyunsun Moondd91be22016-04-24 17:43:32 -0700757 checkNotNull(osConfig, "OpenStack access is not configured");
758
Hyunsun Moon576d6872016-04-14 19:04:23 -0700759 log.debug("Get OpenStack access with Endpoint: {} Tenant: {} User: {} Passwd: {}",
760 osConfig.endpoint(),
761 osConfig.tenant(),
762 osConfig.user(),
763 osConfig.password());
764 try {
765 osAccess = OSFactory.builder()
766 .endpoint(osConfig.endpoint())
767 .credentials(osConfig.user(), osConfig.password())
768 .tenantName(osConfig.tenant())
769 .authenticate()
770 .getAccess();
771 } catch (AuthenticationException e) {
772 log.error("Failed to get OpenStack Access");
773 }
774 }
775
776 /**
Hyunsun Moondd91be22016-04-24 17:43:32 -0700777 * Sets XOS access information.
778 *
779 * @param xosAccess xos access
780 */
781 private void setXosAccess(XosAccess xosAccess) {
782 checkNotNull(xosAccess, "XOS access is not configured");
783
784 log.debug("Set XOS access with Endpoint: {} User: {} Passwd: {}",
785 xosAccess.endpoint(),
786 xosAccess.username(),
787 xosAccess.password());
788
789 xosClient.setAccess(xosAccess);
790 }
791
792 /**
Hyunsun Moon746956f2016-01-24 21:47:06 -0800793 * Updates configurations.
794 */
795 private void readConfiguration() {
796 CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
797 if (config == null) {
798 log.debug("No configuration found");
799 return;
800 }
801
Hyunsun Moondd91be22016-04-24 17:43:32 -0700802 setXosAccess(config.xosAccess());
Hyunsun Moon576d6872016-04-14 19:04:23 -0700803 setOpenstackAccess(config.openstackConfig());
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800804 setPrivateGatewayMac(config.privateGatewayMac());
805 setPublicGatewayMac(config.publicGateways());
Hyunsun Moon576d6872016-04-14 19:04:23 -0700806 }
Hyunsun Moon746956f2016-01-24 21:47:06 -0800807
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700808 private class InternalHostListener implements HostListener {
809
810 @Override
811 public void event(HostEvent event) {
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800812 Host host = event.subject();
Hyunsun Moond35420f2016-03-08 21:59:13 -0800813 if (!mastershipService.isLocalMaster(host.location().deviceId())) {
814 // do not allow to proceed without mastership
815 return;
816 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700817
818 switch (event.type()) {
Hyunsun Moond35420f2016-03-08 21:59:13 -0800819 case HOST_UPDATED:
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700820 case HOST_ADDED:
Hyunsun Moond35420f2016-03-08 21:59:13 -0800821 eventExecutor.submit(() -> serviceVmAdded(host));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700822 break;
823 case HOST_REMOVED:
Hyunsun Moond35420f2016-03-08 21:59:13 -0800824 eventExecutor.submit(() -> serviceVmRemoved(host));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700825 break;
826 default:
827 break;
828 }
829 }
830 }
831
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800832 private class InternalPacketProcessor implements PacketProcessor {
833
834 @Override
835 public void process(PacketContext context) {
836 if (context.isHandled()) {
837 return;
838 }
839
840 Ethernet ethPacket = context.inPacket().parsed();
Hyunsun Moon746956f2016-01-24 21:47:06 -0800841 if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800842 return;
843 }
844
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800845 arpProxy.processArpPacket(context, ethPacket);
Hyunsun Moon746956f2016-01-24 21:47:06 -0800846 }
847 }
848
849 private class InternalConfigListener implements NetworkConfigListener {
850
851 @Override
852 public void event(NetworkConfigEvent event) {
853 if (!event.configClass().equals(CordVtnConfig.class)) {
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800854 return;
855 }
856
Hyunsun Moon746956f2016-01-24 21:47:06 -0800857 switch (event.type()) {
858 case CONFIG_ADDED:
859 case CONFIG_UPDATED:
860 log.info("Network configuration changed");
861 eventExecutor.execute(CordVtn.this::readConfiguration);
862 break;
863 default:
864 break;
865 }
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800866 }
867 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700868}