blob: f1b772b60827789ae3187c731b07c73035d5e0e9 [file] [log] [blame]
Brian O'Connorce2d8b52015-07-29 16:24:13 -07001/*
2 * Copyright 2015 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.onosproject.incubator.net.domain.impl;
17
18import com.google.common.collect.HashMultimap;
19import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Maps;
21import com.google.common.collect.Multimap;
22import com.google.common.collect.Multimaps;
23import com.google.common.collect.Sets;
24import org.apache.felix.scr.annotations.Activate;
25import org.apache.felix.scr.annotations.Component;
26import org.apache.felix.scr.annotations.Deactivate;
27import org.apache.felix.scr.annotations.Reference;
28import org.apache.felix.scr.annotations.ReferenceCardinality;
29import org.apache.felix.scr.annotations.Service;
30import org.onlab.graph.AdjacencyListsGraph;
31import org.onlab.graph.Graph;
32import org.onosproject.core.ApplicationId;
33import org.onosproject.core.CoreService;
34import org.onosproject.incubator.net.config.NetworkConfigEvent;
35import org.onosproject.incubator.net.config.NetworkConfigListener;
36import org.onosproject.incubator.net.config.NetworkConfigService;
37import org.onosproject.incubator.net.domain.DomainEdge;
38import org.onosproject.incubator.net.domain.DomainVertex;
39import org.onosproject.incubator.net.domain.IntentDomain;
40import org.onosproject.incubator.net.domain.IntentDomainAdminService;
41import org.onosproject.incubator.net.domain.IntentDomainConfig;
42import org.onosproject.incubator.net.domain.IntentDomainId;
43import org.onosproject.incubator.net.domain.IntentDomainListener;
44import org.onosproject.incubator.net.domain.IntentDomainProvider;
45import org.onosproject.incubator.net.domain.IntentDomainService;
46import org.onosproject.net.ConnectPoint;
47import org.onosproject.net.DeviceId;
48import org.slf4j.Logger;
49import org.slf4j.LoggerFactory;
50
51import java.util.Map;
52import java.util.Set;
53import java.util.concurrent.ConcurrentMap;
54import java.util.stream.Collectors;
55
56/**
57 * Implementation of the intent domain service.
58 */
59@Component(immediate = true)
60@Service
61public class IntentDomainManager
62 implements IntentDomainService, IntentDomainAdminService {
63
64 private final Logger log = LoggerFactory.getLogger(getClass());
65
66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected CoreService coreService;
68
69 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 protected NetworkConfigService configService;
71
72 private NetworkConfigListener cfgListener = new InternalConfigListener();
73
74 private final ConcurrentMap<IntentDomainId, IntentDomain> domains = Maps.newConcurrentMap();
75
76 private final Multimap<String, IntentDomainId> appToDomain =
77 Multimaps.synchronizedSetMultimap(HashMultimap.<String, IntentDomainId>create());
78
79 private Graph<DomainVertex, DomainEdge> graph;
80
81 @Activate
82 protected void activate() {
83 configService.addListener(cfgListener);
84 configService.getSubjects(IntentDomainId.class, IntentDomainConfig.class)
85 .forEach(this::processConfig);
86 graph = buildGraph();
87 log.debug("Graph: {}", graph);
88 log.info("Started");
89 }
90
91 private void processConfig(IntentDomainId intentDomainId) {
92 IntentDomainConfig cfg = configService.getConfig(intentDomainId,
93 IntentDomainConfig.class);
94
95 domains.put(intentDomainId, createDomain(intentDomainId, cfg));
96 appToDomain.put(cfg.applicationName(), intentDomainId);
97 }
98
99 private IntentDomain createDomain(IntentDomainId id, IntentDomainConfig cfg) {
100 return new IntentDomain(id, cfg.domainName(), cfg.internalDevices(), cfg.edgePorts());
101 }
102
103 private Graph<DomainVertex, DomainEdge> buildGraph() {
104 Set<DomainVertex> vertices = Sets.newHashSet();
105 Set<DomainEdge> edges = Sets.newHashSet();
106
107 Map<DeviceId, DomainVertex> deviceVertices = Maps.newHashMap();
108 domains.forEach((id, domain) -> {
109 DomainVertex domainVertex = new DomainVertex(id);
110
111 // Add vertex for domain
112 vertices.add(domainVertex);
113
114 // Add vertices for connection devices
115 domain.edgePorts().stream()
116 .map(ConnectPoint::deviceId)
117 .collect(Collectors.toSet())
118 .forEach(did -> deviceVertices.putIfAbsent(did, new DomainVertex(did)));
119
120 // Add bi-directional edges between each domain and connection device
121 domain.edgePorts().forEach(cp -> {
122 DomainVertex deviceVertex = deviceVertices.get(cp.deviceId());
123 edges.add(new DomainEdge(domainVertex, deviceVertex, cp));
124 edges.add(new DomainEdge(deviceVertex, domainVertex, cp));
125 });
126 });
127
128 vertices.addAll(deviceVertices.values());
129 //FIXME verify graph integrity...
130 return new AdjacencyListsGraph<>(vertices, edges);
131 }
132
133 @Deactivate
134 protected void deactivate() {
135 configService.removeListener(cfgListener);
136 log.info("Stopped");
137 }
138
139 @Override
140 public IntentDomain getDomain(IntentDomainId id) {
141 return domains.get(id);
142 }
143
144 @Override
145 public Set<IntentDomain> getDomains() {
146 return ImmutableSet.copyOf(domains.values());
147 }
148
149 @Override
150 public Set<IntentDomain> getDomains(DeviceId deviceId) {
151 return domains.values().stream()
152 .filter(domain ->
153 domain.internalDevices().contains(deviceId) ||
154 domain.edgePorts().stream()
155 .map(ConnectPoint::deviceId)
156 .anyMatch(d -> d.equals(deviceId)))
157 .collect(Collectors.toSet());
158 }
159
160 @Override
161 public Graph<DomainVertex, DomainEdge> getDomainGraph() {
162 return graph;
163 }
164
165 @Override
166 public void addListener(IntentDomainListener listener) {
167 //TODO slide in AbstractListenerManager
168 }
169
170 @Override
171 public void removeListener(IntentDomainListener listener) {
172 //TODO slide in AbstractListenerManager
173 }
174
175 @Override
176 public void registerApplication(ApplicationId applicationId, IntentDomainProvider provider) {
177 appToDomain.get(applicationId.name()).forEach(d -> domains.get(d).setProvider(provider));
178 }
179
180 @Override
181 public void unregisterApplication(ApplicationId applicationId) {
182 appToDomain.get(applicationId.name()).forEach(d -> domains.get(d).unsetProvider());
183 }
184
185 private class InternalConfigListener implements NetworkConfigListener {
186 @Override
187 public void event(NetworkConfigEvent event) {
188 switch (event.type()) {
189 case CONFIG_ADDED:
190 case CONFIG_UPDATED:
191 processConfig((IntentDomainId) event.subject());
192 graph = buildGraph();
193 log.debug("Graph: {}", graph);
194 break;
195
196 case CONFIG_REGISTERED:
197 case CONFIG_UNREGISTERED:
198 case CONFIG_REMOVED:
199 default:
200 //TODO
201 break;
202 }
203 }
204
205 @Override
206 public boolean isRelevant(NetworkConfigEvent event) {
207 return event.configClass().equals(IntentDomainConfig.class);
208 }
209 }
210}