blob: f694019aa43cf2fa9480891a8b44b4d41da1417f [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 Moon4c396632016-05-13 04:17:53 -070069import org.onosproject.xosclient.api.VtnServiceApi;
70import org.onosproject.xosclient.api.VtnServiceId;
Hyunsun Moondd91be22016-04-24 17:43:32 -070071import org.onosproject.xosclient.api.XosAccess;
72import org.onosproject.xosclient.api.XosClientService;
Hyunsun Moon576d6872016-04-14 19:04:23 -070073import org.openstack4j.api.OSClient;
74import org.openstack4j.api.exceptions.AuthenticationException;
75import org.openstack4j.model.identity.Access;
76import org.openstack4j.model.network.Network;
77import org.openstack4j.model.network.Subnet;
78import org.openstack4j.openstack.OSFactory;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070079import org.slf4j.Logger;
80
Hyunsun Moon1d3eac92016-02-03 00:11:11 -080081import java.util.List;
Hyunsun Moon1f145552015-10-08 22:25:30 -070082import java.util.Map;
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -080083import java.util.Objects;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080084import java.util.Set;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070085import java.util.concurrent.ExecutorService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080086import java.util.stream.Collectors;
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -080087import java.util.stream.StreamSupport;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070088
Hyunsun Moon1f145552015-10-08 22:25:30 -070089import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moon746956f2016-01-24 21:47:06 -080090import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070091import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070092import static org.slf4j.LoggerFactory.getLogger;
93
94/**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080095 * Provisions virtual tenant networks with service chaining capability
96 * in OpenStack environment.
Hyunsun Moond0e932a2015-09-15 22:39:16 -070097 */
98@Component(immediate = true)
99@Service
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800100public class CordVtn extends AbstractProvider implements CordVtnService, HostProvider {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700101
102 protected final Logger log = getLogger(getClass());
103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected CoreService coreService;
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon746956f2016-01-24 21:47:06 -0800108 protected NetworkConfigRegistry configRegistry;
109
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected NetworkConfigService configService;
112
113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800114 protected HostProviderRegistry hostProviderRegistry;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700115
116 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700117 protected DeviceService deviceService;
118
119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 protected HostService hostService;
121
Hyunsun Moon1f145552015-10-08 22:25:30 -0700122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800123 protected FlowRuleService flowRuleService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800124
125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800126 protected PacketService packetService;
127
128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800129 protected MastershipService mastershipService;
130
131 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
132 protected GroupService groupService;
133
134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800135 protected DhcpService dhcpService;
136
Hyunsun Moondd91be22016-04-24 17:43:32 -0700137 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
138 protected XosClientService xosClient;
139
Hyunsun Moon746956f2016-01-24 21:47:06 -0800140 private final ConfigFactory configFactory =
141 new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
142 @Override
143 public CordVtnConfig createConfig() {
144 return new CordVtnConfig();
145 }
146 };
147
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800148 private static final String DEFAULT_TUNNEL = "vxlan";
149 private static final String SERVICE_ID = "serviceId";
Hyunsun Moon6d247342016-02-12 12:48:47 -0800150 private static final String OPENSTACK_PORT_ID = "openstackPortId";
151 private static final String DATA_PLANE_IP = "dataPlaneIp";
152 private static final String DATA_PLANE_INTF = "dataPlaneIntf";
153 private static final String S_TAG = "stag";
Hyunsun Moon98025542016-03-08 04:36:02 -0800154 private static final String VSG_HOST_ID = "vsgHostId";
Hyunsun Moond35420f2016-03-08 21:59:13 -0800155 private static final String CREATED_TIME = "createdTime";
Hyunsun Moon6d247342016-02-12 12:48:47 -0800156
157 private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800158
Hyunsun Moon746956f2016-01-24 21:47:06 -0800159 private final ExecutorService eventExecutor =
160 newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "event-handler"));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700161
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800162 private final PacketProcessor packetProcessor = new InternalPacketProcessor();
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800163 private final HostListener hostListener = new InternalHostListener();
Hyunsun Moon746956f2016-01-24 21:47:06 -0800164 private final NetworkConfigListener configListener = new InternalConfigListener();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700165
Hyunsun Moon746956f2016-01-24 21:47:06 -0800166 private ApplicationId appId;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800167 private HostProviderService hostProvider;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800168 private CordVtnRuleInstaller ruleInstaller;
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800169 private CordVtnArpProxy arpProxy;
Hyunsun Moon576d6872016-04-14 19:04:23 -0700170
Hyunsun Moon4c396632016-05-13 04:17:53 -0700171 private volatile XosAccess xosAccess = null;
Hyunsun Moon576d6872016-04-14 19:04:23 -0700172 private volatile Access osAccess = null;
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800173 private volatile MacAddress privateGatewayMac = MacAddress.NONE;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800174
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800175 /**
176 * Creates an cordvtn host location provider.
177 */
178 public CordVtn() {
179 super(new ProviderId("host", CORDVTN_APP_ID));
Hyunsun Moon8539b042015-11-07 22:08:43 -0800180 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700181
182 @Activate
183 protected void activate() {
Hyunsun Moon1d019182016-05-06 20:13:28 -0700184 appId = coreService.registerApplication(CordVtnService.CORDVTN_APP_ID);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800185 ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService,
186 deviceService,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800187 groupService,
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800188 configRegistry,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800189 DEFAULT_TUNNEL);
190
Hyunsun Moon9cf43db2016-02-12 15:59:53 -0800191 arpProxy = new CordVtnArpProxy(appId, packetService, hostService);
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800192 packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
193 arpProxy.requestPacket();
194
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700195 hostService.addListener(hostListener);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800196 hostProvider = hostProviderRegistry.register(this);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700197
Hyunsun Moon746956f2016-01-24 21:47:06 -0800198 configRegistry.registerConfigFactory(configFactory);
199 configService.addListener(configListener);
Hyunsun Moon746956f2016-01-24 21:47:06 -0800200
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700201 log.info("Started");
202 }
203
204 @Deactivate
205 protected void deactivate() {
Hyunsun Moon746956f2016-01-24 21:47:06 -0800206 hostProviderRegistry.unregister(this);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700207 hostService.removeListener(hostListener);
Hyunsun Moon746956f2016-01-24 21:47:06 -0800208
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800209 packetService.removeProcessor(packetProcessor);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700210
Hyunsun Moon746956f2016-01-24 21:47:06 -0800211 configRegistry.unregisterConfigFactory(configFactory);
212 configService.removeListener(configListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700213
Hyunsun Moon746956f2016-01-24 21:47:06 -0800214 eventExecutor.shutdown();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700215 log.info("Stopped");
216 }
217
218 @Override
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800219 public void triggerProbe(Host host) {
220 /*
221 * Note: In CORD deployment, we assume that all hosts are configured.
222 * Therefore no probe is required.
223 */
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800224 }
225
226 @Override
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800227 public void createServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId,
228 boolean isBidirectional) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800229 CordService tService = getCordService(tServiceId);
230 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800231
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800232 if (tService == null || pService == null) {
233 log.error("Failed to create CordService for {}", tServiceId.id());
234 return;
235 }
236
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800237 log.info("Service dependency from {} to {} created.", tService.id().id(), pService.id().id());
Hyunsun Moonc14be422016-04-27 15:06:56 -0500238 ruleInstaller.populateServiceDependencyRules(tService, pService, isBidirectional, true);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800239 }
240
241 @Override
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800242 public void removeServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId) {
243 CordService tService = getCordService(tServiceId);
244 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800245
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800246 if (tService == null || pService == null) {
247 log.error("Failed to create CordService for {}", tServiceId.id());
248 return;
249 }
250
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800251 log.info("Service dependency from {} to {} removed.", tService.id().id(), pService.id().id());
Hyunsun Moonc14be422016-04-27 15:06:56 -0500252 ruleInstaller.populateServiceDependencyRules(tService, pService, true, false);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800253 }
254
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800255 @Override
256 public void addServiceVm(CordVtnNode node, ConnectPoint connectPoint) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700257 checkNotNull(osAccess, "OpenStack access is not set");
258
259 OSClient osClient = OSFactory.clientFromAccess(osAccess);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800260 Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
Hyunsun Moon576d6872016-04-14 19:04:23 -0700261 org.openstack4j.model.network.Port osPort = osClient.networking().port().list()
262 .stream()
263 .filter(p -> p.getId().contains(getPortName(port).substring(3)))
264 .findFirst().orElse(null);
265 if (osPort == null) {
266 log.warn("Failed to get OpenStack port for {}", getPortName(port));
Hyunsun Moon8539b042015-11-07 22:08:43 -0800267 return;
268 }
269
Hyunsun Moon576d6872016-04-14 19:04:23 -0700270 MacAddress mac = MacAddress.valueOf(osPort.getMacAddress());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800271 HostId hostId = HostId.hostId(mac);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800272
Hyunsun Moond35420f2016-03-08 21:59:13 -0800273 Host existingHost = hostService.getHost(hostId);
274 if (existingHost != null) {
275 String serviceId = existingHost.annotations().value(SERVICE_ID);
Hyunsun Moon576d6872016-04-14 19:04:23 -0700276 if (serviceId == null || !serviceId.equals(osPort.getNetworkId())) {
Hyunsun Moond35420f2016-03-08 21:59:13 -0800277 // this host is not injected by cordvtn or a stale host, remove it
278 hostProvider.hostVanished(existingHost.id());
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800279 }
Hyunsun Moon8539b042015-11-07 22:08:43 -0800280 }
281
Hyunsun Moond35420f2016-03-08 21:59:13 -0800282 // Included CREATED_TIME to annotation intentionally to trigger HOST_UPDATED
283 // event so that the flow rule population for this host can happen.
284 // This ensures refreshing data plane by pushing network config always make
285 // the data plane synced.
Hyunsun Moon576d6872016-04-14 19:04:23 -0700286 Set<IpAddress> fixedIps = osPort.getFixedIps().stream()
287 .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
288 .collect(Collectors.toSet());
289
Hyunsun Moon6d247342016-02-12 12:48:47 -0800290 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
Hyunsun Moon576d6872016-04-14 19:04:23 -0700291 .set(SERVICE_ID, osPort.getNetworkId())
292 .set(OPENSTACK_PORT_ID, osPort.getId())
Hyunsun Moon6d247342016-02-12 12:48:47 -0800293 .set(DATA_PLANE_IP, node.dpIp().ip().toString())
Hyunsun Moond35420f2016-03-08 21:59:13 -0800294 .set(DATA_PLANE_INTF, node.dpIntf())
295 .set(CREATED_TIME, String.valueOf(System.currentTimeMillis()));
Hyunsun Moon6d247342016-02-12 12:48:47 -0800296
Hyunsun Moon576d6872016-04-14 19:04:23 -0700297 String serviceVlan = getServiceVlan(osPort);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800298 if (serviceVlan != null) {
299 annotations.set(S_TAG, serviceVlan);
300 }
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800301
302 HostDescription hostDesc = new DefaultHostDescription(
303 mac,
304 VlanId.NONE,
305 new HostLocation(connectPoint, System.currentTimeMillis()),
Hyunsun Moon576d6872016-04-14 19:04:23 -0700306 fixedIps,
Hyunsun Moon6d247342016-02-12 12:48:47 -0800307 annotations.build());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800308
309 hostProvider.hostDetected(hostId, hostDesc, false);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800310 }
311
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800312 @Override
313 public void removeServiceVm(ConnectPoint connectPoint) {
Hyunsun Moon2a225162016-02-17 19:00:50 -0800314 hostService.getConnectedHosts(connectPoint)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800315 .stream()
Hyunsun Moon2a225162016-02-17 19:00:50 -0800316 .forEach(host -> hostProvider.hostVanished(host.id()));
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800317 }
318
Hyunsun Moon6d247342016-02-12 12:48:47 -0800319 @Override
320 public void updateVirtualSubscriberGateways(HostId vSgHostId, String serviceVlan,
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800321 Map<IpAddress, MacAddress> vSgs) {
Hyunsun Moon98025542016-03-08 04:36:02 -0800322 Host vSgHost = hostService.getHost(vSgHostId);
323 if (vSgHost == null || !vSgHost.annotations().value(S_TAG).equals(serviceVlan)) {
Hyunsun Moon6d247342016-02-12 12:48:47 -0800324 log.debug("Invalid vSG updates for {}", serviceVlan);
325 return;
326 }
327
Hyunsun Moon98025542016-03-08 04:36:02 -0800328 log.info("Updates vSGs in {} with {}", vSgHost.id(), vSgs.toString());
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800329 vSgs.entrySet().stream()
Hyunsun Moon98025542016-03-08 04:36:02 -0800330 .filter(entry -> hostService.getHostsByMac(entry.getValue()).isEmpty())
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800331 .forEach(entry -> addVirtualSubscriberGateway(
Hyunsun Moon98025542016-03-08 04:36:02 -0800332 vSgHost,
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800333 entry.getKey(),
334 entry.getValue(),
335 serviceVlan));
336
Hyunsun Moon98025542016-03-08 04:36:02 -0800337 hostService.getConnectedHosts(vSgHost.location()).stream()
338 .filter(host -> !host.mac().equals(vSgHost.mac()))
Hyunsun Moon2a225162016-02-17 19:00:50 -0800339 .filter(host -> !vSgs.values().contains(host.mac()))
340 .forEach(host -> {
341 log.info("Removed vSG {}", host.toString());
342 hostProvider.hostVanished(host.id());
343 });
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800344 }
345
346 /**
347 * Adds virtual subscriber gateway to the system.
348 *
349 * @param vSgHost host virtual machine of this vSG
350 * @param vSgIp vSG ip address
351 * @param vSgMac vSG mac address
352 * @param serviceVlan service vlan
353 */
Hyunsun Moon2a225162016-02-17 19:00:50 -0800354 private void addVirtualSubscriberGateway(Host vSgHost, IpAddress vSgIp, MacAddress vSgMac,
355 String serviceVlan) {
Hyunsun Moon98025542016-03-08 04:36:02 -0800356 log.info("vSG with IP({}) MAC({}) added", vSgIp.toString(), vSgMac.toString());
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800357
Hyunsun Moon98025542016-03-08 04:36:02 -0800358 HostId hostId = HostId.hostId(vSgMac);
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800359 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
Hyunsun Moon98025542016-03-08 04:36:02 -0800360 .set(S_TAG, serviceVlan)
Hyunsun Moond35420f2016-03-08 21:59:13 -0800361 .set(VSG_HOST_ID, vSgHost.id().toString())
362 .set(CREATED_TIME, String.valueOf(System.currentTimeMillis()));
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800363
364 HostDescription hostDesc = new DefaultHostDescription(
365 vSgMac,
366 VlanId.NONE,
367 vSgHost.location(),
368 Sets.newHashSet(vSgIp),
369 annotations.build());
370
371 hostProvider.hostDetected(hostId, hostDesc, false);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800372 }
373
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800374 /**
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800375 * Returns public ip addresses of vSGs running inside a give vSG host.
376 *
377 * @param vSgHost vSG host
378 * @return map of ip and mac address, or empty map
379 */
380 private Map<IpAddress, MacAddress> getSubscriberGateways(Host vSgHost) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700381 checkNotNull(osAccess, "OpenStack access is not set");
382
383 String osPortId = vSgHost.annotations().value(OPENSTACK_PORT_ID);
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800384 String serviceVlan = vSgHost.annotations().value(S_TAG);
385
Hyunsun Moon576d6872016-04-14 19:04:23 -0700386 OSClient osClient = OSFactory.clientFromAccess(osAccess);
387 org.openstack4j.model.network.Port osPort = osClient.networking().port().get(osPortId);
388 if (osPort == null) {
389 log.warn("Failed to get OpenStack port {} for VM {}", osPortId, vSgHost.id());
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800390 return Maps.newHashMap();
391 }
392
Hyunsun Moon576d6872016-04-14 19:04:23 -0700393 if (!serviceVlan.equals(getServiceVlan(osPort))) {
394 log.error("Host({}) s-tag does not match with OpenStack port s-tag", vSgHost.id());
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800395 return Maps.newHashMap();
396 }
397
Hyunsun Moon576d6872016-04-14 19:04:23 -0700398 Map<IpAddress, MacAddress> addressPairs = Maps.newHashMap();
399 osPort.getAllowedAddressPairs()
400 .stream().forEach(p -> addressPairs.put(
401 IpAddress.valueOf(p.getIpAddress()),
402 MacAddress.valueOf(p.getMacAddress())));
403
404 return addressPairs;
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800405 }
406
407 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800408 * Returns CordService by service ID.
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800409 *
410 * @param serviceId service id
411 * @return cord service, or null if it fails to get network from OpenStack
412 */
413 private CordService getCordService(CordServiceId serviceId) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700414 checkNotNull(osAccess, "OpenStack access is not set");
415
416 OSClient osClient = OSFactory.clientFromAccess(osAccess);
417 Network osNet = osClient.networking().network().get(serviceId.id());
418 if (osNet == null) {
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800419 log.warn("Couldn't find OpenStack network for service {}", serviceId.id());
420 return null;
421 }
422
Hyunsun Moondd91be22016-04-24 17:43:32 -0700423 return getCordService(osNet);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800424 }
425
426 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800427 * Returns CordService by OpenStack network.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800428 *
Hyunsun Moon576d6872016-04-14 19:04:23 -0700429 * @param osNet OpenStack network
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800430 * @return cord service
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800431 */
Hyunsun Moon576d6872016-04-14 19:04:23 -0700432 private CordService getCordService(Network osNet) {
433 checkNotNull(osNet);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800434
Hyunsun Moon576d6872016-04-14 19:04:23 -0700435 CordServiceId serviceId = CordServiceId.of(osNet.getId());
436 // here it assumes all cord service networks has only one subnet
437 Subnet osSubnet = osNet.getNeutronSubnets().stream()
Hyunsun Moonc14be422016-04-27 15:06:56 -0500438 .findFirst().orElse(null);
Hyunsun Moon576d6872016-04-14 19:04:23 -0700439 if (osSubnet == null) {
Hyunsun Moonc14be422016-04-27 15:06:56 -0500440 log.warn("Couldn't find OpenStack subnet for network {}", serviceId.id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800441 return null;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800442 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800443
Hyunsun Moon576d6872016-04-14 19:04:23 -0700444 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(osNet)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800445 .stream()
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800446 .collect(Collectors.toMap(host -> host, this::getTunnelIp));
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800447
Hyunsun Moondd91be22016-04-24 17:43:32 -0700448 // allows working without XOS for now
449 Set<CordServiceId> tServices = Sets.newHashSet();
450 Set<CordServiceId> pServices = Sets.newHashSet();
451
Hyunsun Moon4c396632016-05-13 04:17:53 -0700452 if (xosAccess != null) {
453 VtnServiceApi vtnServiceApi = xosClient.getClient(xosAccess).vtnService();
454 tServices = vtnServiceApi.tenantServices(VtnServiceId.of(serviceId.id()))
Hyunsun Moondd91be22016-04-24 17:43:32 -0700455 .stream()
Hyunsun Moon4c396632016-05-13 04:17:53 -0700456 .map(id -> CordServiceId.of(id.id()))
Hyunsun Moondd91be22016-04-24 17:43:32 -0700457 .collect(Collectors.toSet());
458
Hyunsun Moon4c396632016-05-13 04:17:53 -0700459 pServices = vtnServiceApi.providerServices(VtnServiceId.of(serviceId.id()))
Hyunsun Moondd91be22016-04-24 17:43:32 -0700460 .stream()
Hyunsun Moon4c396632016-05-13 04:17:53 -0700461 .map(id -> CordServiceId.of(id.id()))
Hyunsun Moondd91be22016-04-24 17:43:32 -0700462 .collect(Collectors.toSet());
463 }
464
465 return new CordService(osNet, osSubnet, hosts, tServices, pServices);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800466 }
467
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800468 /**
469 * Returns IP address for tunneling for a given host.
470 *
471 * @param host host
Hyunsun Moon6d247342016-02-12 12:48:47 -0800472 * @return ip address, or null
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800473 */
474 private IpAddress getTunnelIp(Host host) {
Hyunsun Moon6d247342016-02-12 12:48:47 -0800475 String ip = host.annotations().value(DATA_PLANE_IP);
476 return ip == null ? null : IpAddress.valueOf(ip);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800477 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700478
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800479 /**
480 * Returns port name.
481 *
482 * @param port port
483 * @return port name
484 */
485 private String getPortName(Port port) {
486 return port.annotations().value("portName");
487 }
Hyunsun Moon8539b042015-11-07 22:08:43 -0800488
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800489 /**
Hyunsun Moon6d247342016-02-12 12:48:47 -0800490 * Returns s-tag from a given OpenStack port.
491 *
Hyunsun Moon576d6872016-04-14 19:04:23 -0700492 * @param osPort openstack port
Hyunsun Moon6d247342016-02-12 12:48:47 -0800493 * @return s-tag string
494 */
Hyunsun Moon576d6872016-04-14 19:04:23 -0700495 private String getServiceVlan(org.openstack4j.model.network.Port osPort) {
496 checkNotNull(osPort);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800497
Hyunsun Moon576d6872016-04-14 19:04:23 -0700498 String portName = osPort.getName();
499 if (portName != null && portName.startsWith(S_TAG)) {
500 return portName.split("-")[1];
Hyunsun Moon6d247342016-02-12 12:48:47 -0800501 } else {
502 return null;
503 }
504 }
505
506 /**
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800507 * Returns service ID of this host.
508 *
509 * @param host host
510 * @return service id, or null if not found
511 */
512 private String getServiceId(Host host) {
513 return host.annotations().value(SERVICE_ID);
514 }
515
516 /**
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800517 * Returns hosts associated with a given OpenStack network.
518 *
Hyunsun Moon576d6872016-04-14 19:04:23 -0700519 * @param osNet openstack network
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800520 * @return set of hosts
521 */
Hyunsun Moon576d6872016-04-14 19:04:23 -0700522 private Set<Host> getHostsWithOpenstackNetwork(Network osNet) {
523 checkNotNull(osNet);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700524
Hyunsun Moon576d6872016-04-14 19:04:23 -0700525 String osNetId = osNet.getId();
Hyunsun Moon32f3b8e2016-03-02 19:27:26 -0800526 return StreamSupport.stream(hostService.getHosts().spliterator(), false)
Hyunsun Moon576d6872016-04-14 19:04:23 -0700527 .filter(host -> Objects.equals(osNetId, getServiceId(host)))
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800528 .collect(Collectors.toSet());
Hyunsun Moon6d247342016-02-12 12:48:47 -0800529 }
530
531 /**
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800532 * Registers static DHCP lease for a given host.
533 *
534 * @param host host
535 * @param service cord service
536 */
537 private void registerDhcpLease(Host host, CordService service) {
538 List<Ip4Address> options = Lists.newArrayList();
539 options.add(Ip4Address.makeMaskPrefix(service.serviceIpRange().prefixLength()));
540 options.add(service.serviceIp().getIp4Address());
541 options.add(service.serviceIp().getIp4Address());
542 options.add(DEFAULT_DNS);
543
544 log.debug("Set static DHCP mapping for {}", host.mac());
545 dhcpService.setStaticMapping(host.mac(),
546 host.ipAddresses().stream().findFirst().get().getIp4Address(),
547 true,
548 options);
549 }
550
551 /**
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800552 * Handles VM detected situation.
553 *
554 * @param host host
555 */
556 private void serviceVmAdded(Host host) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700557 checkNotNull(osAccess, "OpenStack access is not set");
558
Hyunsun Moon98025542016-03-08 04:36:02 -0800559 String serviceVlan = host.annotations().value(S_TAG);
560 if (serviceVlan != null) {
561 virtualSubscriberGatewayAdded(host, serviceVlan);
562 }
563
Hyunsun Moonc14be422016-04-27 15:06:56 -0500564 String serviceId = host.annotations().value(SERVICE_ID);
565 if (serviceId == null) {
566 // ignore this host, it is not a service VM
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800567 return;
568 }
569
Hyunsun Moonc14be422016-04-27 15:06:56 -0500570 log.info("VM is detected, MAC: {} IP: {}", host.mac(), host.ipAddresses());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800571
Hyunsun Moonc14be422016-04-27 15:06:56 -0500572 CordService service = getCordService(CordServiceId.of(serviceId));
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800573 if (service == null) {
Hyunsun Moonc14be422016-04-27 15:06:56 -0500574 log.warn("Failed to get CordService for {}", serviceId);
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800575 return;
576 }
577
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800578 switch (service.serviceType()) {
579 case MANAGEMENT:
580 ruleInstaller.populateManagementNetworkRules(host, service);
581 break;
582 case PRIVATE:
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800583 arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
Hyunsun Moon098cda82016-03-03 13:27:44 -0800584 case PUBLIC:
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800585 default:
Hyunsun Moondd91be22016-04-24 17:43:32 -0700586 // TODO get bidirectional information from XOS once XOS supports
587 service.tenantServices().stream().forEach(
588 tServiceId -> createServiceDependency(tServiceId, service.id(), true));
589 service.providerServices().stream().forEach(
590 pServiceId -> createServiceDependency(service.id(), pServiceId, true));
591
Hyunsun Moonc14be422016-04-27 15:06:56 -0500592 ruleInstaller.updateProviderServiceGroup(service);
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800593 // sends gratuitous ARP here for the case of adding existing VMs
594 // when ONOS or cordvtn app is restarted
595 arpProxy.sendGratuitousArpForGateway(service.serviceIp(), Sets.newHashSet(host));
596 break;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800597 }
598
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800599 registerDhcpLease(host, service);
Hyunsun Moonc14be422016-04-27 15:06:56 -0500600 ruleInstaller.populateBasicConnectionRules(host, service, true);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800601 }
602
603 /**
604 * Handles VM removed situation.
605 *
606 * @param host host
607 */
608 private void serviceVmRemoved(Host host) {
Hyunsun Moon576d6872016-04-14 19:04:23 -0700609 checkNotNull(osAccess, "OpenStack access is not set");
610
Hyunsun Moonc14be422016-04-27 15:06:56 -0500611 if (host.annotations().value(S_TAG) != null) {
Hyunsun Moon98025542016-03-08 04:36:02 -0800612 virtualSubscriberGatewayRemoved(host);
613 }
614
Hyunsun Moonc14be422016-04-27 15:06:56 -0500615 String serviceId = host.annotations().value(SERVICE_ID);
616 if (serviceId == null) {
617 // ignore it, it's not a service VM
Hyunsun Moon1d3eac92016-02-03 00:11:11 -0800618 return;
619 }
620
Hyunsun Moonc14be422016-04-27 15:06:56 -0500621 log.info("VM is vanished, MAC: {} IP: {}", host.mac(), host.ipAddresses());
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800622
Hyunsun Moonc14be422016-04-27 15:06:56 -0500623 CordService service = getCordService(CordServiceId.of(serviceId));
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800624 if (service == null) {
Hyunsun Moonc14be422016-04-27 15:06:56 -0500625 log.warn("Failed to get CORD service for {}", serviceId);
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800626 return;
627 }
Hyunsun Moonc14be422016-04-27 15:06:56 -0500628 // TODO need to consider the case that the network is removed also
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800629
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800630 switch (service.serviceType()) {
631 case MANAGEMENT:
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800632 break;
633 case PRIVATE:
Hyunsun Moonc14be422016-04-27 15:06:56 -0500634 if (service.hosts().isEmpty()) {
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800635 arpProxy.removeGateway(service.serviceIp());
636 }
Hyunsun Moon098cda82016-03-03 13:27:44 -0800637 case PUBLIC:
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800638 default:
Hyunsun Moondd91be22016-04-24 17:43:32 -0700639 if (!service.tenantServices().isEmpty()) {
Hyunsun Moonc14be422016-04-27 15:06:56 -0500640 ruleInstaller.updateProviderServiceGroup(service);
641 }
642 if (!service.providerServices().isEmpty()) {
643 ruleInstaller.updateTenantServiceVm(host, service);
Hyunsun Moondd91be22016-04-24 17:43:32 -0700644 }
Hyunsun Moon1e5caeb2016-03-01 16:36:23 -0800645 break;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700646 }
Hyunsun Moonc14be422016-04-27 15:06:56 -0500647
648 dhcpService.removeStaticMapping(host.mac());
649 ruleInstaller.populateBasicConnectionRules(host, service, false);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700650 }
651
Hyunsun Moon98025542016-03-08 04:36:02 -0800652
653 /**
654 * Handles virtual subscriber gateway VM or container.
655 *
656 * @param host new host with stag, it can be vsg VM or vsg
657 * @param serviceVlan service vlan
658 */
659 private void virtualSubscriberGatewayAdded(Host host, String serviceVlan) {
660 Map<IpAddress, MacAddress> vSgs;
661 Host vSgHost;
662
663 String vSgHostId = host.annotations().value(VSG_HOST_ID);
664 if (vSgHostId == null) {
665 log.debug("vSG VM detected {}", host.id());
666
667 vSgHost = host;
668 vSgs = getSubscriberGateways(vSgHost);
669 vSgs.entrySet().stream().forEach(entry -> addVirtualSubscriberGateway(
670 vSgHost,
671 entry.getKey(),
672 entry.getValue(),
673 serviceVlan));
674 } else {
675 vSgHost = hostService.getHost(HostId.hostId(vSgHostId));
676 if (vSgHost == null) {
677 return;
678 }
679
680 log.debug("vSG detected {}", host.id());
681 vSgs = getSubscriberGateways(vSgHost);
682 }
683
684 ruleInstaller.populateSubscriberGatewayRules(vSgHost, vSgs.keySet());
685 }
686
687 /**
688 * Handles virtual subscriber gateway removed.
689 *
690 * @param vSg vsg host to remove
691 */
692 private void virtualSubscriberGatewayRemoved(Host vSg) {
693 String vSgHostId = vSg.annotations().value(VSG_HOST_ID);
694 if (vSgHostId == null) {
695 return;
696 }
697
698 Host vSgHost = hostService.getHost(HostId.hostId(vSgHostId));
699 if (vSgHost == null) {
700 return;
701 }
702
703 log.info("vSG removed {}", vSg.id());
704 Map<IpAddress, MacAddress> vSgs = getSubscriberGateways(vSgHost);
705 ruleInstaller.populateSubscriberGatewayRules(vSgHost, vSgs.keySet());
706 }
707
Hyunsun Moon746956f2016-01-24 21:47:06 -0800708 /**
709 * Sets service network gateway MAC address and sends out gratuitous ARP to all
710 * VMs to update the gateway MAC address.
711 *
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800712 * @param newMac mac address to update
Hyunsun Moon746956f2016-01-24 21:47:06 -0800713 */
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800714 private void setPrivateGatewayMac(MacAddress newMac) {
Hyunsun Moondd91be22016-04-24 17:43:32 -0700715 checkNotNull(osAccess, "OpenStack access is not set");
716
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800717 if (newMac == null || newMac.equals(privateGatewayMac)) {
718 // no updates, do nothing
719 return;
Hyunsun Moon746956f2016-01-24 21:47:06 -0800720 }
721
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800722 privateGatewayMac = newMac;
723 log.debug("Set service gateway MAC address to {}", privateGatewayMac.toString());
724
Hyunsun Moondd91be22016-04-24 17:43:32 -0700725 OSClient osClient = OSFactory.clientFromAccess(osAccess);
726 List<Network> vNets = Lists.newArrayList(osClient.networking().network().list().iterator());
Hyunsun Moon746956f2016-01-24 21:47:06 -0800727
728 vNets.stream().forEach(vNet -> {
Hyunsun Moondd91be22016-04-24 17:43:32 -0700729 CordService service = getCordService(vNet);
Hyunsun Moon746956f2016-01-24 21:47:06 -0800730 if (service != null) {
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800731 arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
732 arpProxy.sendGratuitousArpForGateway(service.serviceIp(), service.hosts().keySet());
Hyunsun Moon746956f2016-01-24 21:47:06 -0800733 }
734 });
735 }
736
737 /**
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800738 * Sets public gateway MAC address.
739 *
740 * @param publicGateways gateway ip and mac address pairs
741 */
742 private void setPublicGatewayMac(Map<IpAddress, MacAddress> publicGateways) {
743 publicGateways.entrySet()
744 .stream()
745 .forEach(entry -> {
746 arpProxy.addGateway(entry.getKey(), entry.getValue());
Hyunsun Moon576d6872016-04-14 19:04:23 -0700747 log.debug("Added public gateway IP {}, MAC {}",
748 entry.getKey().toString(), entry.getValue().toString());
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800749 });
750 // TODO notice gateway MAC change to VMs holds this gateway IP
751 }
752
753 /**
Hyunsun Moon576d6872016-04-14 19:04:23 -0700754 * Sets OpenStack access information.
755 * Access is the entity returned when authenticated and provides a singleton client
756 * between multiple threads.
757 *
758 * @param osConfig openstack config
759 */
760 private void setOpenstackAccess(CordVtnConfig.OpenStackConfig osConfig) {
Hyunsun Moondd91be22016-04-24 17:43:32 -0700761 checkNotNull(osConfig, "OpenStack access is not configured");
762
Hyunsun Moon576d6872016-04-14 19:04:23 -0700763 log.debug("Get OpenStack access with Endpoint: {} Tenant: {} User: {} Passwd: {}",
764 osConfig.endpoint(),
765 osConfig.tenant(),
766 osConfig.user(),
767 osConfig.password());
768 try {
769 osAccess = OSFactory.builder()
770 .endpoint(osConfig.endpoint())
771 .credentials(osConfig.user(), osConfig.password())
772 .tenantName(osConfig.tenant())
773 .authenticate()
774 .getAccess();
775 } catch (AuthenticationException e) {
776 log.error("Failed to get OpenStack Access");
777 }
778 }
779
780 /**
Hyunsun Moondd91be22016-04-24 17:43:32 -0700781 * Sets XOS access information.
782 *
783 * @param xosAccess xos access
784 */
785 private void setXosAccess(XosAccess xosAccess) {
Hyunsun Moondbd7ffd2016-05-04 16:51:34 -0700786 if (xosAccess == null) {
787 log.warn("XOS access is not configured");
788 return;
789 }
Hyunsun Moondd91be22016-04-24 17:43:32 -0700790
791 log.debug("Set XOS access with Endpoint: {} User: {} Passwd: {}",
792 xosAccess.endpoint(),
793 xosAccess.username(),
794 xosAccess.password());
Hyunsun Moon4c396632016-05-13 04:17:53 -0700795 this.xosAccess = xosAccess;
Hyunsun Moondd91be22016-04-24 17:43:32 -0700796 }
797
798 /**
Hyunsun Moon746956f2016-01-24 21:47:06 -0800799 * Updates configurations.
800 */
801 private void readConfiguration() {
802 CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
803 if (config == null) {
804 log.debug("No configuration found");
805 return;
806 }
807
Hyunsun Moondd91be22016-04-24 17:43:32 -0700808 setXosAccess(config.xosAccess());
Hyunsun Moon576d6872016-04-14 19:04:23 -0700809 setOpenstackAccess(config.openstackConfig());
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800810 setPrivateGatewayMac(config.privateGatewayMac());
811 setPublicGatewayMac(config.publicGateways());
Hyunsun Moon576d6872016-04-14 19:04:23 -0700812 }
Hyunsun Moon746956f2016-01-24 21:47:06 -0800813
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700814 private class InternalHostListener implements HostListener {
815
816 @Override
817 public void event(HostEvent event) {
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800818 Host host = event.subject();
Hyunsun Moond35420f2016-03-08 21:59:13 -0800819 if (!mastershipService.isLocalMaster(host.location().deviceId())) {
820 // do not allow to proceed without mastership
821 return;
822 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700823
824 switch (event.type()) {
Hyunsun Moond35420f2016-03-08 21:59:13 -0800825 case HOST_UPDATED:
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700826 case HOST_ADDED:
Hyunsun Moond35420f2016-03-08 21:59:13 -0800827 eventExecutor.submit(() -> serviceVmAdded(host));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700828 break;
829 case HOST_REMOVED:
Hyunsun Moond35420f2016-03-08 21:59:13 -0800830 eventExecutor.submit(() -> serviceVmRemoved(host));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700831 break;
832 default:
833 break;
834 }
835 }
836 }
837
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800838 private class InternalPacketProcessor implements PacketProcessor {
839
840 @Override
841 public void process(PacketContext context) {
842 if (context.isHandled()) {
843 return;
844 }
845
846 Ethernet ethPacket = context.inPacket().parsed();
Hyunsun Moon746956f2016-01-24 21:47:06 -0800847 if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800848 return;
849 }
850
Hyunsun Moonae39ae82016-02-17 15:02:06 -0800851 arpProxy.processArpPacket(context, ethPacket);
Hyunsun Moon746956f2016-01-24 21:47:06 -0800852 }
853 }
854
855 private class InternalConfigListener implements NetworkConfigListener {
856
857 @Override
858 public void event(NetworkConfigEvent event) {
859 if (!event.configClass().equals(CordVtnConfig.class)) {
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800860 return;
861 }
862
Hyunsun Moon746956f2016-01-24 21:47:06 -0800863 switch (event.type()) {
864 case CONFIG_ADDED:
865 case CONFIG_UPDATED:
866 log.info("Network configuration changed");
867 eventExecutor.execute(CordVtn.this::readConfiguration);
868 break;
869 default:
870 break;
871 }
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800872 }
873 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700874}