blob: 52a6ab721855bf353231899060f437f3efdd51fb [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 Hart062a2e82014-02-03 09:41:57 -08008import net.onrc.onos.datastore.topology.RCSwitch;
9
10import org.slf4j.Logger;
11import org.slf4j.LoggerFactory;
12
13import edu.stanford.ramcloud.JRamCloud.ObjectDoesntExistException;
14import edu.stanford.ramcloud.JRamCloud.ObjectExistsException;
15import edu.stanford.ramcloud.JRamCloud.WrongVersionException;
16
17/**
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080018 * The southbound interface to the network graph which allows clients to
Jonathan Hart062a2e82014-02-03 09:41:57 -080019 * mutate the graph. This class will maintain the invariants of the network
20 * graph. The southbound discovery modules will use this interface to update
21 * the network graph as they learn about the state of the network.
22 *
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080023 * Modification to the Network Map by this module will:
24 * 1. Writes to Cluster-wide DataStore.
25 * 2. Update ONOS instance In-memory Network Map.
26 * 3. Send-out Notification. (TBD)
27 * (XXX: To update other instances In-memory Network Map,
28 * notification should be triggered here.
29 * But if we want to aggregate notification to minimize notification,
30 * It might be better for the caller to trigger notification.)
31 *
Jonathan Hart062a2e82014-02-03 09:41:57 -080032 */
Jonathan Hartfa01c242014-02-11 10:03:03 -080033public class NetworkGraphDatastore {
34 private static final Logger log = LoggerFactory.getLogger(NetworkGraphDatastore.class);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080035
Jonathan Hart062a2e82014-02-03 09:41:57 -080036 private static final int NUM_RETRIES = 10;
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080037
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080038 private final NetworkGraphImpl graph;
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080039
Jonathan Hartfa01c242014-02-11 10:03:03 -080040 public NetworkGraphDatastore(NetworkGraphImpl graph) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080041 this.graph = graph;
42 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080043
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080044 public void addSwitch(SwitchEvent sw) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080045 log.debug("Adding switch {}", sw);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080046 ArrayList<WriteOp> groupOp = new ArrayList<>();
47
Jonathan Hart062a2e82014-02-03 09:41:57 -080048 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
49 rcSwitch.setStatus(RCSwitch.STATUS.ACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080050
51 // XXX Is ForceCreating Switch on DB OK here?
52 // If ForceCreating, who ever is calling this method needs
53 // to assure that DPID is unique cluster-wide, etc.
54 groupOp.add(WriteOp.ForceCreate(rcSwitch));
55
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080056// for (Port port : sw.getPorts()) {
57// RCPort rcPort = new RCPort(sw.getDpid(), (long)port.getNumber());
58// rcPort.setStatus(RCPort.STATUS.ACTIVE);
59// rcSwitch.addPortId(rcPort.getId());
60//
61// groupOp.add(WriteOp.ForceCreate(rcPort));
62// }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080063
64 boolean failed = RCObject.multiWrite( groupOp );
65
66 if ( failed ) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080067 log.error("Adding Switch {} and its ports failed.", sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080068 for ( WriteOp op : groupOp ) {
69 log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus() );
70
71 // If we changed the operation from ForceCreate to
72 // Conditional operation (Create/Update) then we should retry here.
73 }
74 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080075 else {
76 // Publish event to the in-memory cache
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080077// graph.addSwitch(sw);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080078 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080079
Jonathan Hart062a2e82014-02-03 09:41:57 -080080 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080081
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080082 public void deactivateSwitch(SwitchEvent sw) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080083 log.debug("Deactivating switch {}", sw);
Jonathan Hart062a2e82014-02-03 09:41:57 -080084 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080085
Jonathan Hart062a2e82014-02-03 09:41:57 -080086 List<RCObject> objectsToDeactive = new ArrayList<RCObject>();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080087
Jonathan Hart062a2e82014-02-03 09:41:57 -080088 for (int i = 0; i < NUM_RETRIES; i++) {
89 try {
90 rcSwitch.read();
91 rcSwitch.setStatus(RCSwitch.STATUS.INACTIVE);
92 objectsToDeactive.add(rcSwitch);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080093
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080094// for (Port p : sw.getPorts()) {
95// RCPort rcPort = new RCPort(sw.getDpid(), (long)p.getNumber());
96// rcPort.read();
97// rcPort.setStatus(RCPort.STATUS.INACTIVE);
98// objectsToDeactive.add(rcPort);
99// }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800100 } catch (ObjectDoesntExistException e) {
101 log.warn("Trying to deactivate an object that doesn't exist", e);
102 // We don't care to much if the object wasn't there, it's
103 // being deactivated anyway
104 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800105
Jonathan Hart062a2e82014-02-03 09:41:57 -0800106 try {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800107 for (RCObject rcObject : objectsToDeactive) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800108 rcObject.update();
109 }
110 break;
111 } catch (ObjectDoesntExistException e) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800112 // Unlikely, and we don't care anyway.
Jonathan Hart062a2e82014-02-03 09:41:57 -0800113 // TODO But, this will cause everything else to fail
114 log.warn("Trying to deactivate object that doesn't exist", e);
115 } catch (WrongVersionException e) {
116 // Need to re-read and retry
117 }
118 }
119 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800120
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800121 public void addPort(PortEvent port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800122 log.debug("Adding port {}", port);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800123// RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
124//
125// try {
126// rcSwitch.read();
127// } catch (ObjectDoesntExistException e) {
128// log.warn("Add port failed because switch {} doesn't exist", sw.getDpid(), e);
129// return;
130// }
131//
132// RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
133// rcPort.setStatus(RCPort.STATUS.ACTIVE);
134// // TODO add description into RCPort
135// //rcPort.setDescription(port.getDescription());
136// rcSwitch.addPortId(rcPort.getId());
137//
138// writeObject(rcPort);
139// writeObject(rcSwitch);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800140 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800141
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800142 public void deactivatePort(PortEvent port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800143 log.debug("Deactivating port {}", port);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800144// RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
145//
146// for (int i = 0; i < NUM_RETRIES; i++) {
147// try {
148// rcPort.read();
149// } catch (ObjectDoesntExistException e) {
150// // oh well, we were deactivating anyway
151// log.warn("Trying to deactivate a port that doesn't exist: {}", port);
152// return;
153// }
154//
155// rcPort.setStatus(RCPort.STATUS.INACTIVE);
156//
157// try {
158// rcPort.update();
159// break;
160// } catch (ObjectDoesntExistException | WrongVersionException e) {
161// // retry
162// }
163// }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800164 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800165
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800166 public void addLink(LinkEvent link) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800167 log.debug("Adding link {}", link);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800168// RCLink rcLink = new RCLink(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber(),
169// link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
170//
171// RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
172// RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
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 {}", link);
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(link);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800206 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800207
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800208 public void removeLink(LinkEvent link) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800209 log.debug("Removing link {}", link);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800210// RCLink rcLink = new RCLink(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber(),
211// link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
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 {}", link, 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 {}", link, 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}