blob: c8f4d8d554a4137d12e6ff960290ef4aaea83c4e [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;
5
6import net.onrc.onos.datastore.RCObject;
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -08007import net.onrc.onos.datastore.RCObject.WriteOp;
Jonathan Hart369875b2014-02-13 10:00:31 -08008import net.onrc.onos.datastore.topology.RCLink;
Jonathan Hart69864df2014-02-13 10:44:12 -08009import net.onrc.onos.datastore.topology.RCPort;
Jonathan Hart062a2e82014-02-03 09:41:57 -080010import net.onrc.onos.datastore.topology.RCSwitch;
11
12import org.slf4j.Logger;
13import org.slf4j.LoggerFactory;
14
15import edu.stanford.ramcloud.JRamCloud.ObjectDoesntExistException;
16import edu.stanford.ramcloud.JRamCloud.ObjectExistsException;
17import edu.stanford.ramcloud.JRamCloud.WrongVersionException;
18
19/**
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
Jonathan Hart062a2e82014-02-03 09:41:57 -080038 private static final int NUM_RETRIES = 10;
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080039
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080040 private final NetworkGraphImpl graph;
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080041
Jonathan Hartfa01c242014-02-11 10:03:03 -080042 public NetworkGraphDatastore(NetworkGraphImpl graph) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080043 this.graph = graph;
44 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080045
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080046 public void addSwitch(SwitchEvent sw) {
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
Jonathan Hart062a2e82014-02-03 09:41:57 -080050 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
51 rcSwitch.setStatus(RCSwitch.STATUS.ACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080052
53 // XXX Is ForceCreating Switch on DB OK here?
54 // If ForceCreating, who ever is calling this method needs
55 // to assure that DPID is unique cluster-wide, etc.
56 groupOp.add(WriteOp.ForceCreate(rcSwitch));
57
Jonathan Hart69864df2014-02-13 10:44:12 -080058 //for (Port port : sw.getPorts()) {
59 for (PortEvent portEvent : sw.getPorts()) {
60 RCPort rcPort = new RCPort(sw.getDpid(), portEvent.getNumber());
61 rcPort.setStatus(RCPort.STATUS.ACTIVE);
62 //rcSwitch.addPortId(rcPort.getId());
63
64 groupOp.add(WriteOp.ForceCreate(rcPort));
65 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080066
Jonathan Hart369875b2014-02-13 10:00:31 -080067 boolean failed = RCObject.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 }
78
Jonathan Hart062a2e82014-02-03 09:41:57 -080079 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080080
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080081 public void deactivateSwitch(SwitchEvent sw) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080082 log.debug("Deactivating switch {}", sw);
Jonathan Hart062a2e82014-02-03 09:41:57 -080083 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080084
Jonathan Hart062a2e82014-02-03 09:41:57 -080085 List<RCObject> objectsToDeactive = new ArrayList<RCObject>();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080086
Jonathan Hart062a2e82014-02-03 09:41:57 -080087 for (int i = 0; i < NUM_RETRIES; i++) {
88 try {
89 rcSwitch.read();
90 rcSwitch.setStatus(RCSwitch.STATUS.INACTIVE);
91 objectsToDeactive.add(rcSwitch);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080092
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080093// for (Port p : sw.getPorts()) {
94// RCPort rcPort = new RCPort(sw.getDpid(), (long)p.getNumber());
95// rcPort.read();
96// rcPort.setStatus(RCPort.STATUS.INACTIVE);
97// objectsToDeactive.add(rcPort);
98// }
Jonathan Hart062a2e82014-02-03 09:41:57 -080099 } catch (ObjectDoesntExistException e) {
100 log.warn("Trying to deactivate an object that doesn't exist", e);
101 // We don't care to much if the object wasn't there, it's
102 // being deactivated anyway
103 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800104
Jonathan Hart062a2e82014-02-03 09:41:57 -0800105 try {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800106 for (RCObject rcObject : objectsToDeactive) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800107 rcObject.update();
108 }
109 break;
110 } catch (ObjectDoesntExistException e) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800111 // Unlikely, and we don't care anyway.
Jonathan Hart062a2e82014-02-03 09:41:57 -0800112 // TODO But, this will cause everything else to fail
113 log.warn("Trying to deactivate object that doesn't exist", e);
114 } catch (WrongVersionException e) {
115 // Need to re-read and retry
116 }
117 }
118 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800119
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800120 public void addPort(PortEvent port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800121 log.debug("Adding port {}", port);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800122// RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
123//
124// try {
125// rcSwitch.read();
126// } catch (ObjectDoesntExistException e) {
127// log.warn("Add port failed because switch {} doesn't exist", sw.getDpid(), e);
128// return;
129// }
130//
131// RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
132// rcPort.setStatus(RCPort.STATUS.ACTIVE);
133// // TODO add description into RCPort
134// //rcPort.setDescription(port.getDescription());
135// rcSwitch.addPortId(rcPort.getId());
136//
137// writeObject(rcPort);
138// writeObject(rcSwitch);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800139 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800140
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800141 public void deactivatePort(PortEvent port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800142 log.debug("Deactivating port {}", port);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800143// RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
144//
145// for (int i = 0; i < NUM_RETRIES; i++) {
146// try {
147// rcPort.read();
148// } catch (ObjectDoesntExistException e) {
149// // oh well, we were deactivating anyway
150// log.warn("Trying to deactivate a port that doesn't exist: {}", port);
151// return;
152// }
153//
154// rcPort.setStatus(RCPort.STATUS.INACTIVE);
155//
156// try {
157// rcPort.update();
158// break;
159// } catch (ObjectDoesntExistException | WrongVersionException e) {
160// // retry
161// }
162// }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800163 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800164
Jonathan Hart369875b2014-02-13 10:00:31 -0800165 public void addLink(LinkEvent linkEvent) {
166 log.debug("Adding link {}", linkEvent);
167
168 RCLink rcLink = new RCLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(),
169 linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
170
171 //RCPort rcSrcPort = new RCPort(link.getSrc().getDpid(), link.getSrc().getNumber());
172 //RCPort rcDstPort = new RCPort(link.getDst().getDpid(), link.getDst().getNumber());
173
174 for (int i = 0; i < NUM_RETRIES; i++) {
175 try {
176 //rcSrcPort.read();
177 //rcDstPort.read();
178 rcLink.create();
179 //} catch (ObjectDoesntExistException e) {
180 // port doesn't exist
181 //log.error("Add link failed {}", link, e);
182 //return;
183 } catch (ObjectExistsException e) {
184 log.debug("Link already exists {}", linkEvent);
185 return;
186 }
187
188 //rcSrcPort.addLinkId(rcLink.getId());
189 //rcDstPort.addLinkId(rcLink.getId());
190
191 rcLink.setStatus(RCLink.STATUS.ACTIVE);
192
193 try {
194 rcLink.update();
195 //rcSrcPort.update();
196 //rcDstPort.update();
197 break;
198 } catch (ObjectDoesntExistException | WrongVersionException e) {
199 log.debug(" ", e);
200 // retry
201 }
202 }
203
204 // Publish event to in-memory cache
205 graph.putLink(linkEvent);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800206 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800207
Jonathan Hart369875b2014-02-13 10:00:31 -0800208 public void removeLink(LinkEvent linkEvent) {
209 log.debug("Removing link {}", linkEvent);
210 RCLink rcLink = new RCLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(),
211 linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
212
213 //RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
214 //RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
215
216 for (int i = 0; i < NUM_RETRIES; i++) {
217 try {
218 //rcSrcPort.read();
219 //rcDstPort.read();
220 rcLink.read();
221 } catch (ObjectDoesntExistException e) {
222 log.error("Remove link failed {}", linkEvent, e);
223 return;
224 }
225
226 //rcSrcPort.removeLinkId(rcLink.getId());
227 //rcDstPort.removeLinkId(rcLink.getId());
228
229 try {
230 //rcSrcPort.update();
231 //rcDstPort.update();
232 rcLink.delete();
233 } catch (ObjectDoesntExistException e) {
234 log.error("Remove link failed {}", linkEvent, e);
235 return;
236 } catch (WrongVersionException e) {
237 // retry
238 }
239 }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800240 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800241
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800242 public void updateDevice(DeviceEvent device) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800243 // TODO implement
244 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800245
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800246 public void removeDevice(DeviceEvent device) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800247 // TODO implement
248 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800249
Jonathan Hart062a2e82014-02-03 09:41:57 -0800250 // TODO what happens if this fails? why could it fail?
251 private void writeObject(RCObject object) {
252 for (int i = 0; i < NUM_RETRIES; i++) {
253 try {
254 object.create();
255 } catch (ObjectExistsException e) {
256 try {
257 object.read();
258 } catch (ObjectDoesntExistException e1) {
259 // TODO Auto-generated catch block
260 log.error(" ", e);
261 return;
262 }
263 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800264
Jonathan Hart062a2e82014-02-03 09:41:57 -0800265 try {
266 // TODO check API for writing without caring what's there
267 object.update();
268 break;
269 } catch (ObjectDoesntExistException | WrongVersionException e) {
270 log.debug(" ", e);
271 // re-read and retry
272 }
273 }
274 }
275}