blob: 29868b455ab46693dcca1acdd0c435ddc626fb5b [file] [log] [blame]
Hyunsun Moon60a10672016-06-12 17:39:12 -07001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.opencord.cordvtn.impl;
17
18import org.onlab.osgi.DefaultServiceDirectory;
19import org.onlab.osgi.ServiceDirectory;
20import org.onosproject.core.ApplicationId;
21import org.onosproject.core.CoreService;
22import org.onosproject.mastership.MastershipService;
23import org.onosproject.net.Host;
24import org.onosproject.net.config.NetworkConfigEvent;
25import org.onosproject.net.config.NetworkConfigListener;
26import org.onosproject.net.config.NetworkConfigRegistry;
27import org.onosproject.net.host.HostEvent;
28import org.onosproject.net.host.HostListener;
29import org.onosproject.net.host.HostService;
30import org.onosproject.xosclient.api.OpenStackAccess;
31import org.onosproject.xosclient.api.VtnPort;
32import org.onosproject.xosclient.api.VtnPortApi;
33import org.onosproject.xosclient.api.VtnPortId;
34import org.onosproject.xosclient.api.VtnService;
35import org.onosproject.xosclient.api.VtnServiceApi;
36import org.onosproject.xosclient.api.VtnServiceApi.ServiceType;
37import org.onosproject.xosclient.api.VtnServiceId;
38import org.onosproject.xosclient.api.XosAccess;
39import org.onosproject.xosclient.api.XosClientService;
40import org.opencord.cordvtn.api.CordVtnConfig;
41import org.opencord.cordvtn.api.CordVtnService;
42import org.opencord.cordvtn.api.Instance;
43import org.opencord.cordvtn.api.InstanceHandler;
44import org.slf4j.Logger;
45
46import java.util.Objects;
47import java.util.Optional;
48import java.util.Set;
49import java.util.concurrent.ExecutorService;
50import java.util.stream.Collectors;
51import java.util.stream.StreamSupport;
52
53import static com.google.common.base.Preconditions.checkNotNull;
54import static org.slf4j.LoggerFactory.getLogger;
55
56/**
57 * Provides default virtual network connectivity for service instances.
58 */
59public abstract class AbstractInstanceHandler implements InstanceHandler {
60
61 protected final Logger log = getLogger(getClass());
62
63 protected CoreService coreService;
64 protected MastershipService mastershipService;
65 protected NetworkConfigRegistry configRegistry;
66 protected HostService hostService;
67 protected XosClientService xosClient;
68 protected CordVtnPipeline pipeline;
69 protected CordVtnNodeManager nodeManager;
70
71 protected ApplicationId appId;
72 protected ExecutorService eventExecutor;
73 protected Optional<ServiceType> serviceType = Optional.empty();
74 protected NetworkConfigListener configListener = new InternalConfigListener();
75 protected HostListener hostListener = new InternalHostListener();
76
77 private static final String OPENSTACK_ACCESS_ERROR = "OpenStack access is not configured";
78 private static final String XOS_ACCESS_ERROR = "XOS access is not configured";
79 private XosAccess xosAccess = null;
80 private OpenStackAccess osAccess = null;
81
82 protected void activate() {
83 ServiceDirectory services = new DefaultServiceDirectory();
84 coreService = services.get(CoreService.class);
85 configRegistry = services.get(NetworkConfigRegistry.class);
86 mastershipService = services.get(MastershipService.class);
87 hostService = services.get(HostService.class);
88 xosClient = services.get(XosClientService.class);
89 pipeline = services.get(CordVtnPipeline.class);
90 nodeManager = services.get(CordVtnNodeManager.class);
91
92 appId = coreService.registerApplication(CordVtnService.CORDVTN_APP_ID);
93 hostService.addListener(hostListener);
94 configRegistry.addListener(configListener);
95
96 log.info("Started");
97 }
98
99 protected void deactivate() {
100 hostService.removeListener(hostListener);
101 configRegistry.removeListener(configListener);
102 eventExecutor.shutdown();
103
104 log.info("Stopped");
105 }
106
107 protected VtnService getVtnService(VtnServiceId serviceId) {
108 checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
109 checkNotNull(xosAccess, XOS_ACCESS_ERROR);
110
111 // TODO remove openstack access when XOS provides all information
112 VtnServiceApi serviceApi = xosClient.getClient(xosAccess).vtnService();
113 VtnService service = serviceApi.service(serviceId, osAccess);
114 if (service == null) {
115 log.warn("Failed to get VtnService for {}", serviceId);
116 }
117 return service;
118 }
119
120 protected VtnPort getVtnPort(Instance instance) {
121 checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
122 checkNotNull(xosAccess, XOS_ACCESS_ERROR);
123
124 VtnPortId vtnPortId = instance.portId();
125 VtnPortApi portApi = xosClient.getClient(xosAccess).vtnPort();
126 VtnPort vtnPort = portApi.vtnPort(vtnPortId, osAccess);
127 if (vtnPort == null) {
128 log.warn("Failed to get port information of {}", instance);
129 return null;
130 }
131 return vtnPort;
132 }
133
134 protected Set<Instance> getInstances(VtnServiceId serviceId) {
135 return StreamSupport.stream(hostService.getHosts().spliterator(), false)
136 .filter(host -> Objects.equals(
137 serviceId.id(),
138 host.annotations().value(Instance.SERVICE_ID)))
139 .map(Instance::of)
140 .collect(Collectors.toSet());
141 }
142
143 protected void readConfiguration() {
144 CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
145 if (config == null) {
146 log.debug("No configuration found");
147 return;
148 }
149 osAccess = config.openstackAccess();
150 xosAccess = config.xosAccess();
151 }
152
153 private class InternalHostListener implements HostListener {
154
155 @Override
156 public void event(HostEvent event) {
157 Host host = event.subject();
158 if (!mastershipService.isLocalMaster(host.location().deviceId())) {
159 // do not allow to proceed without mastership
160 return;
161 }
162
163 Instance instance = Instance.of(host);
164 if (serviceType.isPresent() &&
165 !serviceType.get().equals(instance.serviceType())) {
166 // not my service instance, do nothing
167 return;
168 }
169
170 switch (event.type()) {
171 case HOST_UPDATED:
172 case HOST_ADDED:
173 eventExecutor.execute(() -> instanceDetected(instance));
174 break;
175 case HOST_REMOVED:
176 eventExecutor.execute(() -> instanceRemoved(instance));
177 break;
178 default:
179 break;
180 }
181 }
182 }
183
184 private class InternalConfigListener implements NetworkConfigListener {
185
186 @Override
187 public void event(NetworkConfigEvent event) {
188 if (!event.configClass().equals(CordVtnConfig.class)) {
189 return;
190 }
191
192 switch (event.type()) {
193 case CONFIG_ADDED:
194 case CONFIG_UPDATED:
195 readConfiguration();
196 break;
197 default:
198 break;
199 }
200 }
201 }
202}