blob: a77a53dcc2d97adf379a974db2c100ff8eb14e7b [file] [log] [blame]
Michele Santuari03df2a52016-11-24 10:35:13 +01001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Michele Santuari03df2a52016-11-24 10:35:13 +01003 *
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 */
16
17package org.onosproject.net.domain.impl;
18
19import com.google.common.collect.Lists;
20import com.google.common.collect.Maps;
Michele Santuari03df2a52016-11-24 10:35:13 +010021import org.onlab.util.ItemNotFoundException;
22import org.onosproject.net.DeviceId;
23import org.onosproject.net.behaviour.DomainIntentConfigurable;
24import org.onosproject.net.device.DeviceService;
25import org.onosproject.net.domain.DomainIntent;
26import org.onosproject.net.domain.DomainIntentOperation;
27import org.onosproject.net.domain.DomainIntentOperations;
28import org.onosproject.net.domain.DomainIntentService;
29import org.onosproject.net.driver.DriverHandler;
30import org.onosproject.net.driver.DriverService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070031import org.osgi.service.component.annotations.Activate;
32import org.osgi.service.component.annotations.Component;
33import org.osgi.service.component.annotations.Deactivate;
34import org.osgi.service.component.annotations.Reference;
35import org.osgi.service.component.annotations.ReferenceCardinality;
Michele Santuari03df2a52016-11-24 10:35:13 +010036import org.slf4j.Logger;
37import org.slf4j.LoggerFactory;
38
39import java.util.List;
40import java.util.Map;
41import java.util.Objects;
42import java.util.Optional;
43import java.util.concurrent.ExecutorService;
44
45import static com.google.common.base.Preconditions.checkNotNull;
46import static java.util.concurrent.Executors.newFixedThreadPool;
47import static org.onlab.util.Tools.groupedThreads;
48import static org.onosproject.net.domain.DomainIntentOperation.Type.ADD;
49import static org.onosproject.net.domain.DomainIntentOperation.Type.REMOVE;
50
51/**
52 * {@link DomainIntentService} implementation class.
53 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070054@Component(immediate = true, service = DomainIntentService.class)
Michele Santuari03df2a52016-11-24 10:35:13 +010055public class DomainIntentManager implements DomainIntentService {
56
57 private final Logger log = LoggerFactory.getLogger(getClass());
58
Ray Milkeyd84f89b2018-08-17 14:54:17 -070059 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Michele Santuari03df2a52016-11-24 10:35:13 +010060 protected DeviceService deviceService;
61
Ray Milkeyd84f89b2018-08-17 14:54:17 -070062 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Michele Santuari03df2a52016-11-24 10:35:13 +010063 protected DriverService driverService;
64
65 private ExecutorService executorService =
66 newFixedThreadPool(Runtime.getRuntime().availableProcessors(),
67 groupedThreads("onos/domain-intent-mgmt", "%d", log));
68
69 private final Map<DeviceId, DriverHandler> driverHandlers = Maps.newConcurrentMap();
70 private final Map<DeviceId, DomainIntentConfigurable> driversMap = Maps.newConcurrentMap();
71
72 @Activate
73 public void activate() {
74 log.info("Started");
75 }
76
77 @Deactivate
78 public void deactivate() {
79 log.info("Stopped");
80 }
81
82 @Override
83 public void sumbit(DomainIntentOperations domainOperations) {
84 executorService.execute(new DomainIntentProcessor(domainOperations));
85 }
86
87 private class DomainIntentProcessor implements Runnable {
88 private final DomainIntentOperations idos;
89
90 private final List<DomainIntentOperation> stages;
91 private boolean hasFailed = false;
92
93 public DomainIntentProcessor(DomainIntentOperations dios) {
94 this.idos = checkNotNull(dios);
95 this.stages = Lists.newArrayList(checkNotNull(dios.stages()));
96 }
97
98 @Override
99 public synchronized void run() {
100 if (stages.size() > 0) {
101 process(stages.remove(0));
102 } else if (!hasFailed) {
103 idos.callback().onSuccess(idos);
104 }
105 }
106
107
108 private void process(DomainIntentOperation dio) {
109 Optional<DomainIntentConfigurable> config =
110 dio.intent().filteredIngressPoints().stream()
111 .map(x -> getDomainIntentConfigurable(x.connectPoint().deviceId()))
112 .filter(Objects::nonNull)
113 .findAny();
114 DomainIntent domainIntent = null;
115 if (config.isPresent()) {
116 if (dio.type() == ADD) {
117 domainIntent = config.get().sumbit(dio.intent());
118 } else if (dio.type() == REMOVE) {
119 domainIntent = config.get().remove(dio.intent());
120 }
121 executorService.execute(this);
122 } else {
123 log.error("Ingresses devices does not support " +
124 "DomainIntentConfigurable. Installation failed");
125 hasFailed = true;
126 }
127 if (domainIntent == null) {
128 log.error("Installation failed for Domain Intent {}", dio.intent());
129 hasFailed = true;
130 }
131 if (hasFailed) {
132 DomainIntentOperations failedBuilder = DomainIntentOperations.builder()
133 .add(dio.intent()).build();
134 idos.callback().onError(failedBuilder);
135 executorService.execute(this);
136 }
137 }
138
139 }
140
141 private DomainIntentConfigurable getDomainIntentConfigurable(DeviceId deviceId) {
142 return driversMap.computeIfAbsent(deviceId, this::initDomainIntentDriver);
143 }
144
145 private DomainIntentConfigurable initDomainIntentDriver(DeviceId deviceId) {
146
147 // Attempt to lookup the handler in the cache
148 DriverHandler handler = driverHandlers.get(deviceId);
149 if (handler == null) {
150 try {
151 // Otherwise create it and if it has DomainIntentConfig behaviour, cache it
152 handler = driverService.createHandler(deviceId);
153
154 if (!handler.driver().hasBehaviour(DomainIntentConfigurable.class)) {
155 log.warn("DomainIntentConfig behaviour not supported for device {}",
156 deviceId);
157 return null;
158 }
159 } catch (ItemNotFoundException e) {
160 log.warn("No applicable driver for device {}", deviceId);
161 return null;
162 }
163 driverHandlers.put(deviceId, handler);
164 }
165 // Always (re)initialize the pipeline behaviour
166 log.info("Driver {} bound to device {} ... initializing driver",
167 handler.driver().name(), deviceId);
168
169 return handler.behaviour(DomainIntentConfigurable.class);
170 }
171}