blob: b5f6b43144870e64bca48af381c23a9928372443 [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 Moonf4ba44f2017-03-14 03:25:52 +090018import org.onosproject.cluster.ClusterService;
19import org.onosproject.cluster.LeadershipEvent;
20import org.onosproject.cluster.LeadershipEventListener;
21import org.onosproject.cluster.LeadershipService;
22import org.onosproject.cluster.NodeId;
23import org.onosproject.core.ApplicationId;
24import org.onosproject.core.CoreService;
25import org.onosproject.event.ListenerRegistry;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070026import org.onosproject.incubator.net.virtual.NetworkId;
27import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
28import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090029import org.onosproject.incubator.net.virtual.VirtualNetworkService;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070030import org.onosproject.ofagent.api.OFAgent;
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090031import org.onosproject.ofagent.api.OFAgentAdminService;
32import org.onosproject.ofagent.api.OFAgentEvent;
33import org.onosproject.ofagent.api.OFAgentListener;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070034import org.onosproject.ofagent.api.OFAgentService;
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090035import org.onosproject.ofagent.api.OFAgentStore;
36import org.onosproject.ofagent.api.OFAgentStoreDelegate;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070037import org.osgi.service.component.annotations.Activate;
38import org.osgi.service.component.annotations.Component;
39import org.osgi.service.component.annotations.Deactivate;
40import org.osgi.service.component.annotations.Reference;
41import org.osgi.service.component.annotations.ReferenceCardinality;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070042import org.slf4j.Logger;
43import org.slf4j.LoggerFactory;
44
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090045import java.util.Objects;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070046import java.util.Set;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070047import java.util.concurrent.ExecutorService;
48
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090049import static com.google.common.base.Preconditions.checkNotNull;
50import static org.onlab.util.BoundedThreadPool.newSingleThreadExecutor;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070051import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090052import static org.onosproject.ofagent.api.OFAgent.State.STARTED;
53import static org.onosproject.ofagent.api.OFAgent.State.STOPPED;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070054
55/**
56 * Implementation of OpenFlow agent service.
57 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070058@Component(immediate = true, service = { OFAgentService.class, OFAgentAdminService.class })
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090059public class OFAgentManager extends ListenerRegistry<OFAgentEvent, OFAgentListener>
60 implements OFAgentService, OFAgentAdminService {
Hyunsun Moon90163ba2016-10-12 13:35:14 -070061
62 private final Logger log = LoggerFactory.getLogger(getClass());
63
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090064 private static final String MSG_OFAGENT = "OFAgent for network %s %s";
65 private static final String MSG_CREATED = "created";
66 private static final String MSG_UPDATED = "updated";
67 private static final String MSG_REMOVED = "removed";
Hyunsun Moon53381e82017-03-28 19:58:28 +090068 private static final String MSG_STARTED = "started";
69 private static final String MSG_STOPPED = "stopped";
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090070 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
Ray Milkeyd84f89b2018-08-17 14:54:17 -070078 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090079 protected CoreService coreService;
80
Ray Milkeyd84f89b2018-08-17 14:54:17 -070081 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090082 protected LeadershipService leadershipService;
83
Ray Milkeyd84f89b2018-08-17 14:54:17 -070084 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090085 protected ClusterService clusterService;
86
Ray Milkeyd84f89b2018-08-17 14:54:17 -070087 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090088 protected VirtualNetworkService virtualNetService;
89
Ray Milkeyd84f89b2018-08-17 14:54:17 -070090 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090091 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);
Hyunsun Moon53381e82017-03-28 19:58:28 +0900120 ofAgentStore.ofAgents().stream()
121 .filter(ofAgent -> ofAgent.state() == STARTED)
122 .forEach(ofAgent -> stopAgent(ofAgent.networkId()));
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900123
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700124 eventExecutor.shutdown();
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900125 leadershipService.withdraw(appId.name());
126
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700127 log.info("Stopped");
128 }
129
130 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900131 public void createAgent(OFAgent ofAgent) {
132 checkNotNull(ofAgent, ERR_NULL_OFAGENT);
133 if (ofAgent.state() == STARTED) {
134 log.warn(String.format(MSG_OFAGENT, ofAgent.networkId(), ERR_IN_USE));
135 return;
136 }
Hyunsun Moon53381e82017-03-28 19:58:28 +0900137 // TODO check if the virtual network exists
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900138 ofAgentStore.createOfAgent(ofAgent);
139 log.info(String.format(MSG_OFAGENT, ofAgent.networkId(), MSG_CREATED));
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700140 }
141
142 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900143 public void updateAgent(OFAgent ofAgent) {
144 checkNotNull(ofAgent, ERR_NULL_OFAGENT);
145 ofAgentStore.updateOfAgent(ofAgent);
146 log.info(String.format(MSG_OFAGENT, ofAgent.networkId(), MSG_UPDATED));
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700147 }
148
149 @Override
Hyunsun Moon53381e82017-03-28 19:58:28 +0900150 public OFAgent removeAgent(NetworkId networkId) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900151 checkNotNull(networkId, ERR_NULL_NETID);
152 synchronized (this) {
153 OFAgent existing = ofAgentStore.ofAgent(networkId);
154 if (existing == null) {
155 final String error = String.format(MSG_OFAGENT, networkId, ERR_NOT_EXIST);
156 throw new IllegalStateException(error);
157 }
158 if (existing.state() == STARTED) {
159 final String error = String.format(MSG_OFAGENT, networkId, ERR_IN_USE);
160 throw new IllegalStateException(error);
161 }
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900162 log.info(String.format(MSG_OFAGENT, networkId, MSG_REMOVED));
Hyunsun Moon53381e82017-03-28 19:58:28 +0900163 return ofAgentStore.removeOfAgent(networkId);
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900164 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700165 }
166
167 @Override
168 public void startAgent(NetworkId networkId) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900169 checkNotNull(networkId, ERR_NULL_NETID);
170 synchronized (this) {
171 OFAgent existing = ofAgentStore.ofAgent(networkId);
172 if (existing == null) {
173 final String error = String.format(MSG_OFAGENT, networkId, ERR_NOT_EXIST);
174 throw new IllegalStateException(error);
175 }
176 if (existing.state() == STARTED) {
Hyunsun Moon53381e82017-03-28 19:58:28 +0900177 final String error = String.format(MSG_OFAGENT, networkId, MSG_IN_STARTED);
178 throw new IllegalStateException(error);
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900179 }
Hyunsun Moon53381e82017-03-28 19:58:28 +0900180 OFAgent updated = DefaultOFAgent.builder()
181 .from(existing).state(STARTED).build();
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900182 ofAgentStore.updateOfAgent(updated);
Hyunsun Moon53381e82017-03-28 19:58:28 +0900183 log.info(String.format(MSG_OFAGENT, networkId, MSG_STARTED));
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900184 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700185 }
186
187 @Override
188 public void stopAgent(NetworkId networkId) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900189 checkNotNull(networkId, ERR_NULL_NETID);
190 synchronized (this) {
191 OFAgent existing = ofAgentStore.ofAgent(networkId);
192 if (existing == null) {
193 final String error = String.format(MSG_OFAGENT, networkId, ERR_NOT_EXIST);
194 throw new IllegalStateException(error);
195 }
196 if (existing.state() == STOPPED) {
Hyunsun Moon53381e82017-03-28 19:58:28 +0900197 final String error = String.format(MSG_OFAGENT, networkId, MSG_IN_STOPPED);
198 throw new IllegalStateException(error);
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900199 }
Hyunsun Moon53381e82017-03-28 19:58:28 +0900200 OFAgent updated = DefaultOFAgent.builder()
201 .from(existing).state(STOPPED).build();
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900202 ofAgentStore.updateOfAgent(updated);
Hyunsun Moon53381e82017-03-28 19:58:28 +0900203 log.info(String.format(MSG_OFAGENT, networkId, MSG_STOPPED));
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900204 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700205 }
206
207 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900208 public Set<OFAgent> agents() {
209 return ofAgentStore.ofAgents();
210 }
211
212 @Override
213 public OFAgent agent(NetworkId networkId) {
214 checkNotNull(networkId, ERR_NULL_NETID);
215 return ofAgentStore.ofAgent(networkId);
216 }
217
218 private class InternalLeadershipListener implements LeadershipEventListener {
219
220 @Override
221 public boolean isRelevant(LeadershipEvent event) {
222 // TODO check if local node is relevant to the leadership change event
223 return false;
224 }
225
226 @Override
227 public void event(LeadershipEvent event) {
228 switch (event.type()) {
229 case LEADER_CHANGED:
230 case LEADER_AND_CANDIDATES_CHANGED:
231 // TODO handle leadership changed events -> restart agents?
232 default:
233 break;
234 }
235 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700236 }
237
238 private class InternalVirtualNetworkListener implements VirtualNetworkListener {
239
240 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900241 public boolean isRelevant(VirtualNetworkEvent event) {
242 // do not allow without leadership
243 return Objects.equals(localId, leadershipService.getLeader(appId.name()));
244 }
245
246 @Override
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700247 public void event(VirtualNetworkEvent event) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900248 switch (event.type()) {
249 case NETWORK_UPDATED:
250 // TODO handle virtual network stopped -> stop agent
251 break;
252 case NETWORK_REMOVED:
253 // TODO remove related OFAgent -> stop agent
254 break;
255 case NETWORK_ADDED:
256 case VIRTUAL_DEVICE_ADDED:
257 case VIRTUAL_DEVICE_UPDATED:
258 case VIRTUAL_DEVICE_REMOVED:
259 case VIRTUAL_PORT_ADDED:
260 case VIRTUAL_PORT_UPDATED:
261 case VIRTUAL_PORT_REMOVED:
262 default:
263 // do nothing
264 break;
265 }
266 }
267 }
268
269 private class InternalOFAgentStoreDelegate implements OFAgentStoreDelegate {
270
271 @Override
272 public void notify(OFAgentEvent event) {
273 if (event != null) {
274 log.trace("send ofagent event {}", event);
275 process(event);
276 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700277 }
278 }
279}