blob: 5f51b58b98fbca44459b3bddc46d54026fd720bd [file] [log] [blame]
HIGUCHI Yutaed49ef72013-06-12 11:34:10 -07001package net.onrc.onos.ofcontroller.core.internal;
Pankaj Berde3200ea02013-01-04 15:48:36 -08002
Pavlin Radoslavov64647d22013-11-04 19:07:03 -08003import java.util.ArrayList;
4import java.util.List;
5
Pankaj Berdebbd38612013-06-22 05:59:12 -07006import net.floodlightcontroller.core.IOFSwitch;
Pankaj Berde38646d62013-06-21 11:34:04 -07007import net.onrc.onos.graph.GraphDBConnection;
8import net.onrc.onos.graph.GraphDBOperation;
Jonathan Hart1a6f1d62013-11-14 11:33:46 -08009import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
HIGUCHI Yuta20514902013-06-12 11:24:16 -070010import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
11import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
Jonathan Hart1a6f1d62013-11-14 11:33:46 -080012import net.onrc.onos.ofcontroller.core.ISwitchStorage;
Pankaj Berdeafb20532013-01-08 15:05:24 -080013
Pankaj Berde3200ea02013-01-04 15:48:36 -080014import org.openflow.protocol.OFPhysicalPort;
Pankaj Berde6a4075d2013-01-22 16:42:54 -080015import org.openflow.protocol.OFPhysicalPort.OFPortConfig;
16import org.openflow.protocol.OFPhysicalPort.OFPortState;
Pankaj Berde15193092013-03-21 17:30:14 -070017import org.slf4j.Logger;
18import org.slf4j.LoggerFactory;
Pankaj Berde3200ea02013-01-04 15:48:36 -080019
Teruef33dc32013-06-20 09:54:37 -070020/**
Naoki Shiota987a5722013-10-23 11:59:36 -070021 * This is the class for storing the information of switches into GraphDB
Teruef33dc32013-06-20 09:54:37 -070022 */
Pankaj Berde3200ea02013-01-04 15:48:36 -080023public class SwitchStorageImpl implements ISwitchStorage {
Toshio Koide4f3d9eb2013-06-13 13:20:55 -070024 protected GraphDBOperation op;
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070025 protected final static Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
Teruef33dc32013-06-20 09:54:37 -070026
27 /***
28 * Initialize function. Before you use this class, please call this method
29 * @param conf configuration file for Cassandra DB
30 */
Pankaj Berde3200ea02013-01-04 15:48:36 -080031 @Override
Teruef33dc32013-06-20 09:54:37 -070032 public void init(String conf) {
33 GraphDBConnection conn = GraphDBConnection.getInstance(conf);
34 op = new GraphDBOperation(conn);
35 }
Pankaj Berde3200ea02013-01-04 15:48:36 -080036
Teruef33dc32013-06-20 09:54:37 -070037 /***
38 * Finalize/close function. After you use this class, please call this method.
39 * It will close the DB connection.
40 */
41 public void finalize() {
42 close();
43 }
44
45 /***
46 * Finalize/close function. After you use this class, please call this method.
Pavlin Radoslavovef0cb002013-06-21 14:55:23 -070047 * It will close the DB connection. This is for Java garbage collection.
Teruef33dc32013-06-20 09:54:37 -070048 */
49 @Override
50 public void close() {
51 op.close();
52 }
53
Naoki Shiota987a5722013-10-23 11:59:36 -070054 // Method designing policy:
55 // op.commit() and op.rollback() MUST called in public (first-class) methods.
56 // A first-class method MUST NOT call other first-class method.
57 // Routine process should be implemented in private method.
58 // A private method MUST NOT call commit or rollback.
59
Teruef33dc32013-06-20 09:54:37 -070060 /***
Teruef33dc32013-06-20 09:54:37 -070061 * This function is for updating the switch into the DB.
62 * @param dpid The switch dpid you want to update from the DB
63 * @param state The state of the switch like ACTIVE, INACTIVE
64 * @param dmope The DM_OPERATION of the switch
65 */
Jonathan Hartadc63892013-11-08 14:03:55 -080066 /*
67 * Jono, 11/8/2013
68 * We don't need this update method that demultiplexes DM_OPERATIONS,
69 * we can have clients just call the required methods directly.
70 * We especially don't need this update method to re-implement
71 * the functions of other methods.
72 */
73 @Deprecated
Teruef33dc32013-06-20 09:54:37 -070074 @Override
Naoki Shiota987a5722013-10-23 11:59:36 -070075 public boolean updateSwitch(String dpid, SwitchState state, DM_OPERATION dmope) {
76 boolean success = false;
77 ISwitchObject sw = null;
78
79 log.info("SwitchStorage:update {} dpid:{}", dmope, dpid);
Naoki Shiotab2d17e82013-10-18 18:08:16 -070080 switch(dmope) {
81 case UPDATE:
Naoki Shiota987a5722013-10-23 11:59:36 -070082 try {
83 sw = op.searchSwitch(dpid);
84 if (sw != null) {
85 setSwitchStateImpl(sw, state);
86 op.commit();
87 success = true;
88 }
89 } catch (Exception e) {
90 op.rollback();
91 e.printStackTrace();
92 log.info("SwitchStorage:update {} dpid:{} failed", dmope, dpid);
93 }
94 break;
Naoki Shiotab2d17e82013-10-18 18:08:16 -070095 case INSERT:
96 case CREATE:
Naoki Shiota987a5722013-10-23 11:59:36 -070097 try {
98 sw = addSwitchImpl(dpid);
99 if (sw != null) {
100 if (state != SwitchState.ACTIVE) {
101 setSwitchStateImpl(sw, state);
102 }
103 op.commit();
104 success = true;
105 }
106 } catch (Exception e) {
107 op.rollback();
108 e.printStackTrace();
109 log.info("SwitchStorage:update {} dpid:{} failed", dmope, dpid);
110 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700111 break;
112 case DELETE:
Naoki Shiota987a5722013-10-23 11:59:36 -0700113 try {
114 sw = op.searchSwitch(dpid);
115 if (sw != null) {
116 deleteSwitchImpl(sw);
117 op.commit();
118 success = true;
119 }
120 } catch (Exception e) {
121 op.rollback();
122 e.printStackTrace();
123 log.info("SwitchStorage:update {} dpid:{} failed", dmope, dpid);
124 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700125 break;
126 default:
127 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700128
129 return success;
130 }
131
132 @Override
133 public boolean addSwitch(IOFSwitch sw) {
134 boolean success = false;
135
136 String dpid = sw.getStringId();
137 log.info("SwitchStorage:addSwitch(): dpid {} ", dpid);
138
139 try {
140 ISwitchObject curr = op.searchSwitch(dpid);
141 if (curr != null) {
142 //If existing the switch. set The SW state ACTIVE.
143 log.info("SwitchStorage:addSwitch dpid:{} already exists", dpid);
144 setSwitchStateImpl(curr, SwitchState.ACTIVE);
145 } else {
146 curr = addSwitchImpl(dpid);
147 }
148
149 for (OFPhysicalPort port: sw.getPorts()) {
Jonathan Hart4cfd1932013-11-19 16:42:25 -0800150 //addPort(dpid, port);
151 addPortImpl(curr, port);
152
Naoki Shiota987a5722013-10-23 11:59:36 -0700153 }
Jonathan Hart4cfd1932013-11-19 16:42:25 -0800154
155 // XXX for now delete devices when we change a port to prevent
156 // having stale devices.
157 DeviceStorageImpl deviceStorage = new DeviceStorageImpl();
158 deviceStorage.init("");
159 for (IPortObject portObject : curr.getPorts()) {
160 for (IDeviceObject deviceObject : portObject.getDevices()) {
161 // The deviceStorage has to remove on the object gained by its own
162 // FramedGraph, it can't use our objects from here
163 deviceStorage.removeDeviceImpl(deviceStorage.getDeviceByMac(deviceObject.getMACAddress()));
164 }
165 }
166
Naoki Shiota987a5722013-10-23 11:59:36 -0700167 op.commit();
168 success = true;
169 } catch (Exception e) {
170 op.rollback();
Jonathan Hart4cfd1932013-11-19 16:42:25 -0800171 log.error("SwitchStorage:addSwitch dpid:{} failed", dpid, e);
Naoki Shiota987a5722013-10-23 11:59:36 -0700172 }
173
174 return success;
175 }
176
177 /***
178 * This function is for adding the switch into the DB.
179 * @param dpid The switch dpid you want to add into the DB.
180 */
Jonathan Hart13ccdca2013-10-30 15:23:28 -0700181 // This method is only called by tests, so we probably don't need it.
182 // If we need both addSwitch interfaces, one should call the other
183 // rather than implementing the same logic twice.
184 @Deprecated
Naoki Shiota987a5722013-10-23 11:59:36 -0700185 @Override
186 public boolean addSwitch(String dpid) {
187 boolean success = false;
188
189 log.info("SwitchStorage:addSwitch(): dpid {} ", dpid);
190 try {
191 ISwitchObject sw = op.searchSwitch(dpid);
192 if (sw != null) {
193 //If existing the switch. set The SW state ACTIVE.
194 log.info("SwitchStorage:addSwitch dpid:{} already exists", dpid);
195 setSwitchStateImpl(sw, SwitchState.ACTIVE);
196 } else {
197 addSwitchImpl(dpid);
198 }
199 op.commit();
200 success = true;
201 } catch (Exception e) {
202 op.rollback();
203 e.printStackTrace();
Jonathan Hartadc63892013-11-08 14:03:55 -0800204 log.error("SwitchStorage:addSwitch dpid:{} failed", dpid, e);
Naoki Shiota987a5722013-10-23 11:59:36 -0700205 }
206
207 return success;
208 }
209
210 /***
211 * This function is for deleting the switch into the DB.
212 * @param dpid The switch dpid you want to delete from the DB.
213 */
214 @Override
215 public boolean deleteSwitch(String dpid) {
216 boolean success = false;
217
218 try {
219 ISwitchObject sw = op.searchSwitch(dpid);
220 if (sw != null) {
221 deleteSwitchImpl(sw);
222 op.commit();
223 }
224 success = true;
225 } catch (Exception e) {
226 op.rollback();
227 e.printStackTrace();
228 log.error("SwitchStorage:deleteSwitch {} failed", dpid);
229 }
230
231 return success;
232 }
Jonathan Hartadc63892013-11-08 14:03:55 -0800233
234 public boolean deactivateSwitch(String dpid) {
235 boolean success = false;
236
237 try {
238 ISwitchObject switchObject = op.searchSwitch(dpid);
239 if (switchObject != null) {
240 setSwitchStateImpl(switchObject, SwitchState.INACTIVE);
241
242 for (IPortObject portObject : switchObject.getPorts()) {
243 portObject.setState("INACTIVE");
244 }
245 op.commit();
246 success = true;
247 }
248 else {
249 log.warn("Switch {} not found when trying to deactivate", dpid);
250 }
251 } catch (Exception e) {
252 // TODO what type of exception is thrown when we can't commit?
253 op.rollback();
254 log.error("SwitchStorage:deactivateSwitch {} failed", dpid, e);
255 }
256
257 return success;
258 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700259
260 public boolean updatePort(String dpid, short portNum, int state, String desc) {
261 boolean success = false;
262
263 try {
264 ISwitchObject sw = op.searchSwitch(dpid);
265
266 if (sw != null) {
267 IPortObject p = sw.getPort(portNum);
268 log.info("SwitchStorage:updatePort dpid:{} port:{}", dpid, portNum);
269 if (p != null) {
270 setPortStateImpl(p, state, desc);
Pavlin Radoslavove86bbfc2013-11-05 08:32:14 -0800271 op.commit();
Naoki Shiota987a5722013-10-23 11:59:36 -0700272 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700273 success = true;
274 } else {
275 log.error("SwitchStorage:updatePort dpid:{} port:{} : failed switch does not exist", dpid, portNum);
276 }
277 } catch (Exception e) {
278 op.rollback();
279 e.printStackTrace();
280 log.error("SwitchStorage:addPort dpid:{} port:{} failed", dpid, portNum);
281 }
282
283 return success;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700284 }
285
286 /***
287 * This function is for adding the switch port into the DB.
288 * @param dpid The switch dpid that has the port.
Naoki Shiota987a5722013-10-23 11:59:36 -0700289 * @param phport The port you want to add the switch.
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700290 */
291 @Override
Naoki Shiota987a5722013-10-23 11:59:36 -0700292 public boolean addPort(String dpid, OFPhysicalPort phport) {
293 boolean success = false;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700294
Naoki Shiota987a5722013-10-23 11:59:36 -0700295 if(((OFPortConfig.OFPPC_PORT_DOWN.getValue() & phport.getConfig()) > 0) ||
296 ((OFPortState.OFPPS_LINK_DOWN.getValue() & phport.getState()) > 0)) {
297 // just dispatch to deletePort()
Jonathan Hartadc63892013-11-08 14:03:55 -0800298 // TODO This is wrong. We need to make sure the port is in the
299 // DB with the correct info and port state.
Naoki Shiota987a5722013-10-23 11:59:36 -0700300 return deletePort(dpid, phport.getPortNumber());
301 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700302
303 try {
304 ISwitchObject sw = op.searchSwitch(dpid);
305
306 if (sw != null) {
Jonathan Hart4cfd1932013-11-19 16:42:25 -0800307 IPortObject portObject = addPortImpl(sw, phport);
308
309 // XXX for now delete devices when we change a port to prevent
310 // having stale devices.
311 DeviceStorageImpl deviceStorage = new DeviceStorageImpl();
312 deviceStorage.init("");
313
314 for (IDeviceObject deviceObject : portObject.getDevices()) {
315 deviceStorage.removeDevice(deviceObject);
316 }
317
Naoki Shiota987a5722013-10-23 11:59:36 -0700318 op.commit();
319 success = true;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700320 } else {
Naoki Shiota987a5722013-10-23 11:59:36 -0700321 log.error("SwitchStorage:addPort dpid:{} port:{} : failed switch does not exist", dpid, phport.getPortNumber());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700322 }
323 } catch (Exception e) {
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700324 op.rollback();
Naoki Shiota987a5722013-10-23 11:59:36 -0700325 e.printStackTrace();
326 log.error("SwitchStorage:addPort dpid:{} port:{} failed", dpid, phport.getPortNumber());
Jonathan Hart4cfd1932013-11-19 16:42:25 -0800327 }
328
Naoki Shiota987a5722013-10-23 11:59:36 -0700329 return success;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700330 }
331
332 /***
333 * This function is for deleting the switch port from the DB.
334 * @param dpid The switch dpid that has the port.
335 * @param port The port you want to delete the switch.
336 */
337 @Override
Naoki Shiota987a5722013-10-23 11:59:36 -0700338 public boolean deletePort(String dpid, short port) {
339 boolean success = false;
340
Jonathan Hart1a6f1d62013-11-14 11:33:46 -0800341 DeviceStorageImpl deviceStorage = new DeviceStorageImpl();
342 deviceStorage.init("");
343
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700344 try {
345 ISwitchObject sw = op.searchSwitch(dpid);
346
347 if (sw != null) {
Naoki Shiota987a5722013-10-23 11:59:36 -0700348 IPortObject p = sw.getPort(port);
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700349 if (p != null) {
350 log.info("SwitchStorage:deletePort dpid:{} port:{} found and set INACTIVE", dpid, port);
Jonathan Hartadc63892013-11-08 14:03:55 -0800351 p.setState("INACTIVE");
Jonathan Hart1a6f1d62013-11-14 11:33:46 -0800352
353 // XXX for now delete devices when we change a port to prevent
354 // having stale devices.
355 for (IDeviceObject d : p.getDevices()) {
356 deviceStorage.removeDevice(d);
357 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700358 op.commit();
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700359 }
360 }
Jonathan Hart1a6f1d62013-11-14 11:33:46 -0800361
362 success = true;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700363 } catch (Exception e) {
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700364 op.rollback();
Naoki Shiota987a5722013-10-23 11:59:36 -0700365 e.printStackTrace();
Jonathan Hartadc63892013-11-08 14:03:55 -0800366 log.error("SwitchStorage:deletePort dpid:{} port:{} failed", dpid, port);
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700367 }
368
Naoki Shiota987a5722013-10-23 11:59:36 -0700369 return success;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700370 }
371
Pavlin Radoslavov64647d22013-11-04 19:07:03 -0800372 /**
373 * Get list of all ports on the switch specified by given DPID.
374 *
375 * @param dpid DPID of desired switch.
376 * @return List of port IDs. Empty list if no port was found.
377 */
378 @Override
379 public List<Short> getPorts(String dpid) {
380 List<Short> ports = new ArrayList<Short>();
381
382 ISwitchObject srcSw = op.searchSwitch(dpid);
383 if (srcSw != null) {
384 for (IPortObject srcPort : srcSw.getPorts()) {
385 ports.add(srcPort.getNumber());
386 }
387 }
388
389 return ports;
390 }
391
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700392 private ISwitchObject addSwitchImpl(String dpid) {
Naoki Shiota987a5722013-10-23 11:59:36 -0700393 if (dpid != null) {
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700394 ISwitchObject sw = op.newSwitch(dpid);
Naoki Shiota987a5722013-10-23 11:59:36 -0700395 sw.setState(SwitchState.ACTIVE.toString());
396 log.info("SwitchStorage:addSwitchImpl dpid:{} added", dpid);
397 return sw;
398 } else {
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700399 return null;
400 }
401 }
402
403 private void setSwitchStateImpl(ISwitchObject sw, SwitchState state) {
404 if (sw != null && state != null) {
405 sw.setState(state.toString());
Naoki Shiota987a5722013-10-23 11:59:36 -0700406 log.info("SwitchStorage:setSwitchStateImpl dpid:{} updated {}",
407 sw.getDPID(), state.toString());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700408 }
Pankaj Berde3200ea02013-01-04 15:48:36 -0800409 }
Teruef33dc32013-06-20 09:54:37 -0700410
Naoki Shiota987a5722013-10-23 11:59:36 -0700411 private void deleteSwitchImpl(ISwitchObject sw) {
412 if (sw != null) {
413 op.removeSwitch(sw);
414 log.info("SwitchStorage:DeleteSwitchImpl dpid:{} done",
415 sw.getDPID());
416 }
417 }
418
Jonathan Hart4cfd1932013-11-19 16:42:25 -0800419
420 private IPortObject addPortImpl(ISwitchObject sw, OFPhysicalPort phport) {
421 IPortObject portObject = op.searchPort(sw.getDPID(), phport.getPortNumber());
422
423 log.info("SwitchStorage:addPort dpid:{} port:{}",
424 sw.getDPID(), phport.getPortNumber());
425
426 if (portObject != null) {
427 setPortStateImpl(portObject, phport.getState(), phport.getName());
428 portObject.setState("ACTIVE");
429
430 // This a convoluted way of checking if the port is attached
431 // or not, but doing it this way avoids using the
432 // ISwitchObject.getPort method which uses GremlinGroovy query
433 // and takes forever.
434 boolean attached = false;
435 for (IPortObject portsOnSwitch : sw.getPorts()) {
436 if (portsOnSwitch.getPortId() == portObject.getPortId()) {
437 attached = true;
438 break;
439 }
440 }
441
442 if (!attached) {
443 sw.addPort(portObject);
444 }
445
446 /*
447 if (sw.getPort(phport.getPortNumber()) == null) {
448 // The port exists but the switch has no "on" link to it
449 sw.addPort(portObject);
450 }*/
451
452 log.info("SwitchStorage:addPort dpid:{} port:{} exists setting as ACTIVE",
453 sw.getDPID(), phport.getPortNumber());
454 } else {
455 //addPortImpl(sw, phport.getPortNumber());
456 portObject = op.newPort(sw.getDPID(), phport.getPortNumber());
457 portObject.setState("ACTIVE");
458 setPortStateImpl(portObject, phport.getState(), phport.getName());
459 sw.addPort(portObject);
460 log.info("SwitchStorage:addPort dpid:{} port:{} done",
461 sw.getDPID(), phport.getPortNumber());
462 }
463
464 return portObject;
465 }
Jonathan Hartd6ed62b2013-11-01 13:18:25 -0700466 // TODO There's an issue here where a port with that ID could already
467 // exist when we try to add this one (because it's left over from an
468 // old topology). We need to remove an old port with the same ID when
469 // we add the new port. Also it seems that old ports like this are
470 // never cleaned up and will remain in the DB in the ACTIVE state forever.
Jonathan Hart4cfd1932013-11-19 16:42:25 -0800471 /*private IPortObject addPortImpl(ISwitchObject sw, short portNum) {
Naoki Shiota987a5722013-10-23 11:59:36 -0700472 IPortObject p = op.newPort(sw.getDPID(), portNum);
473 p.setState("ACTIVE");
474 sw.addPort(p);
475 log.info("SwitchStorage:addPortImpl dpid:{} port:{} done",
476 sw.getDPID(), portNum);
477
478 return p;
Jonathan Hart4cfd1932013-11-19 16:42:25 -0800479 }*/
Naoki Shiota987a5722013-10-23 11:59:36 -0700480
481 private void setPortStateImpl(IPortObject port, Integer state, String desc) {
482 if (port != null) {
483 if (state != null) {
484 port.setPortState(state);
485 }
486 if (desc != null) {
487 port.setDesc(desc);
488 }
489
490 log.info("SwitchStorage:setPortStateImpl port:{} state:{} desc:{} done",
491 new Object[] {port.getPortId(), state, desc});
492 }
493 }
Teru4fd58642013-06-21 07:54:49 -0700494}