blob: e26841b60b8783a23ccfb7fb47307f80f50d04f7 [file] [log] [blame]
Hyunsun Moon90163ba2016-10-12 13:35:14 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Hyunsun Moon90163ba2016-10-12 13:35:14 -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 */
16package org.onosproject.ofagent.impl;
17
Hyunsun Moon90163ba2016-10-12 13:35:14 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090021import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070023import org.apache.felix.scr.annotations.Service;
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090024import org.onosproject.cluster.ClusterService;
25import org.onosproject.cluster.LeadershipEvent;
26import org.onosproject.cluster.LeadershipEventListener;
27import org.onosproject.cluster.LeadershipService;
28import org.onosproject.cluster.NodeId;
29import org.onosproject.core.ApplicationId;
30import org.onosproject.core.CoreService;
31import org.onosproject.event.ListenerRegistry;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070032import org.onosproject.incubator.net.virtual.NetworkId;
33import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
34import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090035import org.onosproject.incubator.net.virtual.VirtualNetworkService;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070036import org.onosproject.ofagent.api.OFAgent;
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090037import org.onosproject.ofagent.api.OFAgentAdminService;
38import org.onosproject.ofagent.api.OFAgentEvent;
39import org.onosproject.ofagent.api.OFAgentListener;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070040import org.onosproject.ofagent.api.OFAgentService;
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090041import org.onosproject.ofagent.api.OFAgentStore;
42import org.onosproject.ofagent.api.OFAgentStoreDelegate;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070043import org.slf4j.Logger;
44import org.slf4j.LoggerFactory;
45
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090046import java.util.Objects;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070047import java.util.Set;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070048import java.util.concurrent.ExecutorService;
49
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090050import static com.google.common.base.Preconditions.checkNotNull;
51import static org.onlab.util.BoundedThreadPool.newSingleThreadExecutor;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070052import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090053import static org.onosproject.ofagent.api.OFAgent.State.STARTED;
54import static org.onosproject.ofagent.api.OFAgent.State.STOPPED;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070055
56/**
57 * Implementation of OpenFlow agent service.
58 */
59@Component(immediate = true)
60@Service
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090061public class OFAgentManager extends ListenerRegistry<OFAgentEvent, OFAgentListener>
62 implements OFAgentService, OFAgentAdminService {
Hyunsun Moon90163ba2016-10-12 13:35:14 -070063
64 private final Logger log = LoggerFactory.getLogger(getClass());
65
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090066 private static final String MSG_OFAGENT = "OFAgent for network %s %s";
67 private static final String MSG_CREATED = "created";
68 private static final String MSG_UPDATED = "updated";
69 private static final String MSG_REMOVED = "removed";
Hyunsun Moon53381e82017-03-28 19:58:28 +090070 private static final String MSG_STARTED = "started";
71 private static final String MSG_STOPPED = "stopped";
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090072 private static final String MSG_IN_STARTED = "is already in active state, do nothing";
73 private static final String MSG_IN_STOPPED = "is already in inactive state, do nothing";
Hyunsun Moon90163ba2016-10-12 13:35:14 -070074
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090075 private static final String ERR_NULL_OFAGENT = "OFAgent cannot be null";
76 private static final String ERR_NULL_NETID = "Network ID cannot be null";
77 private static final String ERR_NOT_EXIST = "does not exist";
78 private static final String ERR_IN_USE = "is in start state, stop the agent first";
79
80 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 protected CoreService coreService;
82
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected LeadershipService leadershipService;
85
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 protected ClusterService clusterService;
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected VirtualNetworkService virtualNetService;
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected OFAgentStore ofAgentStore;
94
95 private final ExecutorService eventExecutor = newSingleThreadExecutor(
96 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
97 private final LeadershipEventListener leadershipListener = new InternalLeadershipListener();
98 private final VirtualNetworkListener virtualNetListener = new InternalVirtualNetworkListener();
99 private final OFAgentStoreDelegate delegate = new InternalOFAgentStoreDelegate();
100
101 private ApplicationId appId;
102 private NodeId localId;
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700103
104 @Activate
105 protected void activate() {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900106 appId = coreService.registerApplication(APPLICATION_NAME);
107 localId = clusterService.getLocalNode().id();
108 leadershipService.runForLeadership(appId.name());
109
110 ofAgentStore.setDelegate(delegate);
111 virtualNetService.addListener(virtualNetListener);
112 leadershipService.addListener(leadershipListener);
113
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700114 log.info("Started");
115 }
116
117 @Deactivate
118 protected void deactivate() {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900119 leadershipService.removeListener(leadershipListener);
120 virtualNetService.removeListener(virtualNetListener);
121 ofAgentStore.unsetDelegate(delegate);
Hyunsun Moon53381e82017-03-28 19:58:28 +0900122 ofAgentStore.ofAgents().stream()
123 .filter(ofAgent -> ofAgent.state() == STARTED)
124 .forEach(ofAgent -> stopAgent(ofAgent.networkId()));
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900125
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700126 eventExecutor.shutdown();
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900127 leadershipService.withdraw(appId.name());
128
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700129 log.info("Stopped");
130 }
131
132 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900133 public void createAgent(OFAgent ofAgent) {
134 checkNotNull(ofAgent, ERR_NULL_OFAGENT);
135 if (ofAgent.state() == STARTED) {
136 log.warn(String.format(MSG_OFAGENT, ofAgent.networkId(), ERR_IN_USE));
137 return;
138 }
Hyunsun Moon53381e82017-03-28 19:58:28 +0900139 // TODO check if the virtual network exists
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900140 ofAgentStore.createOfAgent(ofAgent);
141 log.info(String.format(MSG_OFAGENT, ofAgent.networkId(), MSG_CREATED));
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700142 }
143
144 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900145 public void updateAgent(OFAgent ofAgent) {
146 checkNotNull(ofAgent, ERR_NULL_OFAGENT);
147 ofAgentStore.updateOfAgent(ofAgent);
148 log.info(String.format(MSG_OFAGENT, ofAgent.networkId(), MSG_UPDATED));
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700149 }
150
151 @Override
Hyunsun Moon53381e82017-03-28 19:58:28 +0900152 public OFAgent removeAgent(NetworkId networkId) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900153 checkNotNull(networkId, ERR_NULL_NETID);
154 synchronized (this) {
155 OFAgent existing = ofAgentStore.ofAgent(networkId);
156 if (existing == null) {
157 final String error = String.format(MSG_OFAGENT, networkId, ERR_NOT_EXIST);
158 throw new IllegalStateException(error);
159 }
160 if (existing.state() == STARTED) {
161 final String error = String.format(MSG_OFAGENT, networkId, ERR_IN_USE);
162 throw new IllegalStateException(error);
163 }
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900164 log.info(String.format(MSG_OFAGENT, networkId, MSG_REMOVED));
Hyunsun Moon53381e82017-03-28 19:58:28 +0900165 return ofAgentStore.removeOfAgent(networkId);
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900166 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700167 }
168
169 @Override
170 public void startAgent(NetworkId networkId) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900171 checkNotNull(networkId, ERR_NULL_NETID);
172 synchronized (this) {
173 OFAgent existing = ofAgentStore.ofAgent(networkId);
174 if (existing == null) {
175 final String error = String.format(MSG_OFAGENT, networkId, ERR_NOT_EXIST);
176 throw new IllegalStateException(error);
177 }
178 if (existing.state() == STARTED) {
Hyunsun Moon53381e82017-03-28 19:58:28 +0900179 final String error = String.format(MSG_OFAGENT, networkId, MSG_IN_STARTED);
180 throw new IllegalStateException(error);
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900181 }
Hyunsun Moon53381e82017-03-28 19:58:28 +0900182 OFAgent updated = DefaultOFAgent.builder()
183 .from(existing).state(STARTED).build();
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900184 ofAgentStore.updateOfAgent(updated);
Hyunsun Moon53381e82017-03-28 19:58:28 +0900185 log.info(String.format(MSG_OFAGENT, networkId, MSG_STARTED));
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900186 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700187 }
188
189 @Override
190 public void stopAgent(NetworkId networkId) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900191 checkNotNull(networkId, ERR_NULL_NETID);
192 synchronized (this) {
193 OFAgent existing = ofAgentStore.ofAgent(networkId);
194 if (existing == null) {
195 final String error = String.format(MSG_OFAGENT, networkId, ERR_NOT_EXIST);
196 throw new IllegalStateException(error);
197 }
198 if (existing.state() == STOPPED) {
Hyunsun Moon53381e82017-03-28 19:58:28 +0900199 final String error = String.format(MSG_OFAGENT, networkId, MSG_IN_STOPPED);
200 throw new IllegalStateException(error);
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900201 }
Hyunsun Moon53381e82017-03-28 19:58:28 +0900202 OFAgent updated = DefaultOFAgent.builder()
203 .from(existing).state(STOPPED).build();
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900204 ofAgentStore.updateOfAgent(updated);
Hyunsun Moon53381e82017-03-28 19:58:28 +0900205 log.info(String.format(MSG_OFAGENT, networkId, MSG_STOPPED));
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900206 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700207 }
208
209 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900210 public Set<OFAgent> agents() {
211 return ofAgentStore.ofAgents();
212 }
213
214 @Override
215 public OFAgent agent(NetworkId networkId) {
216 checkNotNull(networkId, ERR_NULL_NETID);
217 return ofAgentStore.ofAgent(networkId);
218 }
219
220 private class InternalLeadershipListener implements LeadershipEventListener {
221
222 @Override
223 public boolean isRelevant(LeadershipEvent event) {
224 // TODO check if local node is relevant to the leadership change event
225 return false;
226 }
227
228 @Override
229 public void event(LeadershipEvent event) {
230 switch (event.type()) {
231 case LEADER_CHANGED:
232 case LEADER_AND_CANDIDATES_CHANGED:
233 // TODO handle leadership changed events -> restart agents?
234 default:
235 break;
236 }
237 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700238 }
239
240 private class InternalVirtualNetworkListener implements VirtualNetworkListener {
241
242 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900243 public boolean isRelevant(VirtualNetworkEvent event) {
244 // do not allow without leadership
245 return Objects.equals(localId, leadershipService.getLeader(appId.name()));
246 }
247
248 @Override
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700249 public void event(VirtualNetworkEvent event) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900250 switch (event.type()) {
251 case NETWORK_UPDATED:
252 // TODO handle virtual network stopped -> stop agent
253 break;
254 case NETWORK_REMOVED:
255 // TODO remove related OFAgent -> stop agent
256 break;
257 case NETWORK_ADDED:
258 case VIRTUAL_DEVICE_ADDED:
259 case VIRTUAL_DEVICE_UPDATED:
260 case VIRTUAL_DEVICE_REMOVED:
261 case VIRTUAL_PORT_ADDED:
262 case VIRTUAL_PORT_UPDATED:
263 case VIRTUAL_PORT_REMOVED:
264 default:
265 // do nothing
266 break;
267 }
268 }
269 }
270
271 private class InternalOFAgentStoreDelegate implements OFAgentStoreDelegate {
272
273 @Override
274 public void notify(OFAgentEvent event) {
275 if (event != null) {
276 log.trace("send ofagent event {}", event);
277 process(event);
278 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700279 }
280 }
281}