blob: ce7c30fa628af74ddf06925f4ae8f8bf30d51fca [file] [log] [blame]
Hyunsun Moon90163ba2016-10-12 13:35:14 -07001/*
2 * Copyright 2017-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.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";
70 private static final String MSG_IN_STARTED = "is already in active state, do nothing";
71 private static final String MSG_IN_STOPPED = "is already in inactive state, do nothing";
Hyunsun Moon90163ba2016-10-12 13:35:14 -070072
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090073 private static final String ERR_NULL_OFAGENT = "OFAgent cannot be null";
74 private static final String ERR_NULL_NETID = "Network ID cannot be null";
75 private static final String ERR_NOT_EXIST = "does not exist";
76 private static final String ERR_IN_USE = "is in start state, stop the agent first";
77
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 protected CoreService coreService;
80
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected LeadershipService leadershipService;
83
84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected ClusterService clusterService;
86
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 protected VirtualNetworkService virtualNetService;
89
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 protected OFAgentStore ofAgentStore;
92
93 private final ExecutorService eventExecutor = newSingleThreadExecutor(
94 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
95 private final LeadershipEventListener leadershipListener = new InternalLeadershipListener();
96 private final VirtualNetworkListener virtualNetListener = new InternalVirtualNetworkListener();
97 private final OFAgentStoreDelegate delegate = new InternalOFAgentStoreDelegate();
98
99 private ApplicationId appId;
100 private NodeId localId;
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700101
102 @Activate
103 protected void activate() {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900104 appId = coreService.registerApplication(APPLICATION_NAME);
105 localId = clusterService.getLocalNode().id();
106 leadershipService.runForLeadership(appId.name());
107
108 ofAgentStore.setDelegate(delegate);
109 virtualNetService.addListener(virtualNetListener);
110 leadershipService.addListener(leadershipListener);
111
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700112 log.info("Started");
113 }
114
115 @Deactivate
116 protected void deactivate() {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900117 leadershipService.removeListener(leadershipListener);
118 virtualNetService.removeListener(virtualNetListener);
119 ofAgentStore.unsetDelegate(delegate);
120 ofAgentStore.ofAgents().forEach(ofAgent -> stopAgent(ofAgent.networkId()));
121
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700122 eventExecutor.shutdown();
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900123 leadershipService.withdraw(appId.name());
124
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700125 log.info("Stopped");
126 }
127
128 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900129 public void createAgent(OFAgent ofAgent) {
130 checkNotNull(ofAgent, ERR_NULL_OFAGENT);
131 if (ofAgent.state() == STARTED) {
132 log.warn(String.format(MSG_OFAGENT, ofAgent.networkId(), ERR_IN_USE));
133 return;
134 }
135 ofAgentStore.createOfAgent(ofAgent);
136 log.info(String.format(MSG_OFAGENT, ofAgent.networkId(), MSG_CREATED));
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700137 }
138
139 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900140 public void updateAgent(OFAgent ofAgent) {
141 checkNotNull(ofAgent, ERR_NULL_OFAGENT);
142 ofAgentStore.updateOfAgent(ofAgent);
143 log.info(String.format(MSG_OFAGENT, ofAgent.networkId(), MSG_UPDATED));
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700144 }
145
146 @Override
147 public void removeAgent(NetworkId networkId) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900148 checkNotNull(networkId, ERR_NULL_NETID);
149 synchronized (this) {
150 OFAgent existing = ofAgentStore.ofAgent(networkId);
151 if (existing == null) {
152 final String error = String.format(MSG_OFAGENT, networkId, ERR_NOT_EXIST);
153 throw new IllegalStateException(error);
154 }
155 if (existing.state() == STARTED) {
156 final String error = String.format(MSG_OFAGENT, networkId, ERR_IN_USE);
157 throw new IllegalStateException(error);
158 }
159 ofAgentStore.removeOfAgent(networkId);
160 log.info(String.format(MSG_OFAGENT, networkId, MSG_REMOVED));
161 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700162 }
163
164 @Override
165 public void startAgent(NetworkId networkId) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900166 checkNotNull(networkId, ERR_NULL_NETID);
167 synchronized (this) {
168 OFAgent existing = ofAgentStore.ofAgent(networkId);
169 if (existing == null) {
170 final String error = String.format(MSG_OFAGENT, networkId, ERR_NOT_EXIST);
171 throw new IllegalStateException(error);
172 }
173 if (existing.state() == STARTED) {
174 log.warn(String.format(MSG_OFAGENT, networkId, MSG_IN_STARTED));
175 return;
176 }
177 OFAgent updated = DefaultOFAgent.builder(existing).state(STARTED).build();
178 ofAgentStore.updateOfAgent(updated);
179 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700180 }
181
182 @Override
183 public void stopAgent(NetworkId networkId) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900184 checkNotNull(networkId, ERR_NULL_NETID);
185 synchronized (this) {
186 OFAgent existing = ofAgentStore.ofAgent(networkId);
187 if (existing == null) {
188 final String error = String.format(MSG_OFAGENT, networkId, ERR_NOT_EXIST);
189 throw new IllegalStateException(error);
190 }
191 if (existing.state() == STOPPED) {
192 log.warn(String.format(MSG_OFAGENT, networkId, MSG_IN_STOPPED));
193 return;
194 }
195 OFAgent updated = DefaultOFAgent.builder(existing).state(STOPPED).build();
196 ofAgentStore.updateOfAgent(updated);
197 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700198 }
199
200 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900201 public Set<OFAgent> agents() {
202 return ofAgentStore.ofAgents();
203 }
204
205 @Override
206 public OFAgent agent(NetworkId networkId) {
207 checkNotNull(networkId, ERR_NULL_NETID);
208 return ofAgentStore.ofAgent(networkId);
209 }
210
211 private class InternalLeadershipListener implements LeadershipEventListener {
212
213 @Override
214 public boolean isRelevant(LeadershipEvent event) {
215 // TODO check if local node is relevant to the leadership change event
216 return false;
217 }
218
219 @Override
220 public void event(LeadershipEvent event) {
221 switch (event.type()) {
222 case LEADER_CHANGED:
223 case LEADER_AND_CANDIDATES_CHANGED:
224 // TODO handle leadership changed events -> restart agents?
225 default:
226 break;
227 }
228 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700229 }
230
231 private class InternalVirtualNetworkListener implements VirtualNetworkListener {
232
233 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900234 public boolean isRelevant(VirtualNetworkEvent event) {
235 // do not allow without leadership
236 return Objects.equals(localId, leadershipService.getLeader(appId.name()));
237 }
238
239 @Override
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700240 public void event(VirtualNetworkEvent event) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900241 switch (event.type()) {
242 case NETWORK_UPDATED:
243 // TODO handle virtual network stopped -> stop agent
244 break;
245 case NETWORK_REMOVED:
246 // TODO remove related OFAgent -> stop agent
247 break;
248 case NETWORK_ADDED:
249 case VIRTUAL_DEVICE_ADDED:
250 case VIRTUAL_DEVICE_UPDATED:
251 case VIRTUAL_DEVICE_REMOVED:
252 case VIRTUAL_PORT_ADDED:
253 case VIRTUAL_PORT_UPDATED:
254 case VIRTUAL_PORT_REMOVED:
255 default:
256 // do nothing
257 break;
258 }
259 }
260 }
261
262 private class InternalOFAgentStoreDelegate implements OFAgentStoreDelegate {
263
264 @Override
265 public void notify(OFAgentEvent event) {
266 if (event != null) {
267 log.trace("send ofagent event {}", event);
268 process(event);
269 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700270 }
271 }
272}