blob: 30b2f73569a6e08b61d59568f554697bbfe13394 [file] [log] [blame]
Jonathan Hart062a2e82014-02-03 09:41:57 -08001package net.onrc.onos.ofcontroller.networkgraph;
2
3import java.util.ArrayList;
4import java.util.List;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08005import java.util.Collection;
Jonathan Hart062a2e82014-02-03 09:41:57 -08006
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -07007import net.onrc.onos.datastore.DataStoreClient;
8import net.onrc.onos.datastore.IKVClient;
9import net.onrc.onos.datastore.topology.KVLink;
10import net.onrc.onos.datastore.topology.KVPort;
11import net.onrc.onos.datastore.topology.KVPort.STATUS;
12import net.onrc.onos.datastore.topology.KVSwitch;
13import net.onrc.onos.datastore.utils.KVObject;
14import net.onrc.onos.datastore.utils.KVObject.WriteOp;
Jonathan Hart062a2e82014-02-03 09:41:57 -080015
16import org.slf4j.Logger;
17import org.slf4j.LoggerFactory;
18
Jonathan Hart062a2e82014-02-03 09:41:57 -080019/**
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080020 * The southbound interface to the network graph which allows clients to
Jonathan Hart062a2e82014-02-03 09:41:57 -080021 * mutate the graph. This class will maintain the invariants of the network
22 * graph. The southbound discovery modules will use this interface to update
23 * the network graph as they learn about the state of the network.
24 *
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080025 * Modification to the Network Map by this module will:
26 * 1. Writes to Cluster-wide DataStore.
27 * 2. Update ONOS instance In-memory Network Map.
28 * 3. Send-out Notification. (TBD)
29 * (XXX: To update other instances In-memory Network Map,
30 * notification should be triggered here.
31 * But if we want to aggregate notification to minimize notification,
32 * It might be better for the caller to trigger notification.)
33 *
Jonathan Hart062a2e82014-02-03 09:41:57 -080034 */
Jonathan Hartfa01c242014-02-11 10:03:03 -080035public class NetworkGraphDatastore {
36 private static final Logger log = LoggerFactory.getLogger(NetworkGraphDatastore.class);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080037
Pavlin Radoslavovca529072014-02-19 14:07:52 -080038 /**
39 * Add a switch to the database.
40 *
41 * @param sw the switch to add.
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080042 * @param portEvents the corresponding switch ports to add.
Pavlin Radoslavovca529072014-02-19 14:07:52 -080043 * @return true on success, otherwise false.
44 */
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080045 public boolean addSwitch(SwitchEvent sw,
46 Collection<PortEvent> portEvents) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080047 log.debug("Adding switch {}", sw);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080048 ArrayList<WriteOp> groupOp = new ArrayList<>();
49
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070050 KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
51 rcSwitch.setStatus(KVSwitch.STATUS.ACTIVE);
52
53 IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080054
55 // XXX Is ForceCreating Switch on DB OK here?
56 // If ForceCreating, who ever is calling this method needs
57 // to assure that DPID is unique cluster-wide, etc.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070058 groupOp.add(rcSwitch.forceCreateOp(client));
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080059
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080060 for (PortEvent portEvent : portEvents) {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070061 KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getNumber());
62 rcPort.setStatus(KVPort.STATUS.ACTIVE);
Jonathan Hart69864df2014-02-13 10:44:12 -080063
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070064 groupOp.add(rcPort.forceCreateOp(client));
Jonathan Hart69864df2014-02-13 10:44:12 -080065 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080066
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070067 boolean failed = KVObject.multiWrite(groupOp);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080068
Jonathan Hart369875b2014-02-13 10:00:31 -080069 if (failed) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080070 log.error("Adding Switch {} and its ports failed.", sw.getDpid());
Jonathan Hart369875b2014-02-13 10:00:31 -080071 for (WriteOp op : groupOp) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080072 log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus() );
73
74 // If we changed the operation from ForceCreate to
75 // Conditional operation (Create/Update) then we should retry here.
76 }
77 }
Jonathan Hartdaea86f2014-02-19 15:28:42 -080078 return !failed;
Jonathan Hart062a2e82014-02-03 09:41:57 -080079 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080080
Pavlin Radoslavovca529072014-02-19 14:07:52 -080081 /**
82 * Update a switch as inactive in the database.
83 *
84 * @param sw the switch to update.
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080085 * @param portEvents the corresponding switch ports to update.
Pavlin Radoslavovca529072014-02-19 14:07:52 -080086 * @return true on success, otherwise false.
87 */
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080088 public boolean deactivateSwitch(SwitchEvent sw,
89 Collection<PortEvent> portEvents) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080090 log.debug("Deactivating switch {}", sw);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070091 KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
92
93 IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080094
Jonathan Hartdaea86f2014-02-19 15:28:42 -080095 List<WriteOp> groupOp = new ArrayList<>();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070096 rcSwitch.setStatus(KVSwitch.STATUS.INACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080097
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070098 groupOp.add(rcSwitch.forceCreateOp(client));
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080099
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800100 for (PortEvent portEvent : portEvents) {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700101 KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getNumber());
102 rcPort.setStatus(KVPort.STATUS.INACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800103
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700104 groupOp.add(rcPort.forceCreateOp(client));
Jonathan Hart062a2e82014-02-03 09:41:57 -0800105 }
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800106
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700107 boolean failed = KVObject.multiWrite(groupOp);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800108
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800109 return !failed;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800110 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800111
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800112 /**
113 * Add a port to the database.
114 *
115 * @param port the port to add.
116 * @return true on success, otherwise false.
117 */
118 public boolean addPort(PortEvent port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800119 log.debug("Adding port {}", port);
Jonathan Hart4c263272014-02-13 17:41:05 -0800120
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700121 KVPort rcPort = new KVPort(port.getDpid(), port.getNumber());
122 rcPort.setStatus(KVPort.STATUS.ACTIVE);
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800123 rcPort.forceCreate();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700124 // TODO add description into KVPort
Jonathan Hart4c263272014-02-13 17:41:05 -0800125 //rcPort.setDescription(port.getDescription());
Jonathan Hart4c263272014-02-13 17:41:05 -0800126
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800127 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800128 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800129
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800130 /**
131 * Update a port as inactive in the database.
132 *
133 * @param port the port to update.
134 * @return true on success, otherwise false.
135 */
136 public boolean deactivatePort(PortEvent port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800137 log.debug("Deactivating port {}", port);
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -0800138
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700139 KVPort rcPort = new KVPort(port.getDpid(), port.getNumber());
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800140 rcPort.setStatus(STATUS.INACTIVE);
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -0800141
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800142 rcPort.forceCreate();
Jonathan Hart4c263272014-02-13 17:41:05 -0800143
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800144 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800145 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800146
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800147 /**
148 * Add a link to the database.
149 *
150 * @param link the link to add.
151 * @return true on success, otherwise false.
152 */
153 public boolean addLink(LinkEvent link) {
154 log.debug("Adding link {}", link);
Yuta HIGUCHI0a4bd192014-02-17 13:52:34 -0800155
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700156 KVLink rcLink = new KVLink(link.getSrc().getDpid(),
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800157 link.getSrc().getNumber(),
158 link.getDst().getDpid(),
159 link.getDst().getNumber());
Jonathan Hart369875b2014-02-13 10:00:31 -0800160
Yuta HIGUCHIef479672014-02-19 09:14:39 -0800161 // XXX This method is called only by discovery,
162 // which means what we are trying to write currently is the truth
163 // so we can force write here
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800164 //
165 // TODO: We need to check for errors
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700166 rcLink.setStatus(KVLink.STATUS.ACTIVE);
Yuta HIGUCHIef479672014-02-19 09:14:39 -0800167 rcLink.forceCreate();
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800168
169 return true; // Success
Jonathan Hart062a2e82014-02-03 09:41:57 -0800170 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800171
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800172 public boolean removeLink(LinkEvent linkEvent) {
173 log.debug("Removing link {}", linkEvent);
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -0800174
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700175 KVLink rcLink = new KVLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(),
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800176 linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
177 rcLink.forceDelete();
Jonathan Hart369875b2014-02-13 10:00:31 -0800178
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800179 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800180 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800181
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800182 /**
183 * Add a device to the database.
184 *
185 * @param device the device to add.
186 * @return true on success, otherwise false.
187 */
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800188 public boolean addDevice(DeviceEvent device) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800189 // TODO implement
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800190 return false; // Failure: not implemented yet
Jonathan Hart062a2e82014-02-03 09:41:57 -0800191 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800192
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800193 /**
194 * Remove a device from the database.
195 *
196 * @param device the device to remove.
197 * @return true on success, otherwise false.
198 */
199 public boolean removeDevice(DeviceEvent device) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800200 // TODO implement
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800201 return false; // Failure: not implemented yet
Jonathan Hart062a2e82014-02-03 09:41:57 -0800202 }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800203}