blob: a3069c3a740e95e858088859a022c032fff05cab [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 Hart062a2e82014-02-03 09:41:57 -08009import net.onrc.onos.datastore.topology.RCSwitch;
10
11import org.slf4j.Logger;
12import org.slf4j.LoggerFactory;
13
14import edu.stanford.ramcloud.JRamCloud.ObjectDoesntExistException;
15import edu.stanford.ramcloud.JRamCloud.ObjectExistsException;
16import edu.stanford.ramcloud.JRamCloud.WrongVersionException;
17
18/**
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080019 * The southbound interface to the network graph which allows clients to
Jonathan Hart062a2e82014-02-03 09:41:57 -080020 * mutate the graph. This class will maintain the invariants of the network
21 * graph. The southbound discovery modules will use this interface to update
22 * the network graph as they learn about the state of the network.
23 *
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080024 * Modification to the Network Map by this module will:
25 * 1. Writes to Cluster-wide DataStore.
26 * 2. Update ONOS instance In-memory Network Map.
27 * 3. Send-out Notification. (TBD)
28 * (XXX: To update other instances In-memory Network Map,
29 * notification should be triggered here.
30 * But if we want to aggregate notification to minimize notification,
31 * It might be better for the caller to trigger notification.)
32 *
Jonathan Hart062a2e82014-02-03 09:41:57 -080033 */
Jonathan Hartfa01c242014-02-11 10:03:03 -080034public class NetworkGraphDatastore {
35 private static final Logger log = LoggerFactory.getLogger(NetworkGraphDatastore.class);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080036
Jonathan Hart062a2e82014-02-03 09:41:57 -080037 private static final int NUM_RETRIES = 10;
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080038
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080039 private final NetworkGraphImpl graph;
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080040
Jonathan Hartfa01c242014-02-11 10:03:03 -080041 public NetworkGraphDatastore(NetworkGraphImpl graph) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080042 this.graph = graph;
43 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080044
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080045 public void addSwitch(SwitchEvent sw) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080046 log.debug("Adding switch {}", sw);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080047 ArrayList<WriteOp> groupOp = new ArrayList<>();
48
Jonathan Hart062a2e82014-02-03 09:41:57 -080049 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
50 rcSwitch.setStatus(RCSwitch.STATUS.ACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080051
52 // XXX Is ForceCreating Switch on DB OK here?
53 // If ForceCreating, who ever is calling this method needs
54 // to assure that DPID is unique cluster-wide, etc.
55 groupOp.add(WriteOp.ForceCreate(rcSwitch));
56
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080057// for (Port port : sw.getPorts()) {
58// RCPort rcPort = new RCPort(sw.getDpid(), (long)port.getNumber());
59// rcPort.setStatus(RCPort.STATUS.ACTIVE);
60// rcSwitch.addPortId(rcPort.getId());
61//
62// groupOp.add(WriteOp.ForceCreate(rcPort));
63// }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080064
Jonathan Hart369875b2014-02-13 10:00:31 -080065 boolean failed = RCObject.multiWrite(groupOp);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080066
Jonathan Hart369875b2014-02-13 10:00:31 -080067 if (failed) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080068 log.error("Adding Switch {} and its ports failed.", sw.getDpid());
Jonathan Hart369875b2014-02-13 10:00:31 -080069 for (WriteOp op : groupOp) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080070 log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus() );
71
72 // If we changed the operation from ForceCreate to
73 // Conditional operation (Create/Update) then we should retry here.
74 }
75 }
76
Jonathan Hart062a2e82014-02-03 09:41:57 -080077 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080078
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080079 public void deactivateSwitch(SwitchEvent sw) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080080 log.debug("Deactivating switch {}", sw);
Jonathan Hart062a2e82014-02-03 09:41:57 -080081 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080082
Jonathan Hart062a2e82014-02-03 09:41:57 -080083 List<RCObject> objectsToDeactive = new ArrayList<RCObject>();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080084
Jonathan Hart062a2e82014-02-03 09:41:57 -080085 for (int i = 0; i < NUM_RETRIES; i++) {
86 try {
87 rcSwitch.read();
88 rcSwitch.setStatus(RCSwitch.STATUS.INACTIVE);
89 objectsToDeactive.add(rcSwitch);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080090
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080091// for (Port p : sw.getPorts()) {
92// RCPort rcPort = new RCPort(sw.getDpid(), (long)p.getNumber());
93// rcPort.read();
94// rcPort.setStatus(RCPort.STATUS.INACTIVE);
95// objectsToDeactive.add(rcPort);
96// }
Jonathan Hart062a2e82014-02-03 09:41:57 -080097 } catch (ObjectDoesntExistException e) {
98 log.warn("Trying to deactivate an object that doesn't exist", e);
99 // We don't care to much if the object wasn't there, it's
100 // being deactivated anyway
101 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800102
Jonathan Hart062a2e82014-02-03 09:41:57 -0800103 try {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800104 for (RCObject rcObject : objectsToDeactive) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800105 rcObject.update();
106 }
107 break;
108 } catch (ObjectDoesntExistException e) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800109 // Unlikely, and we don't care anyway.
Jonathan Hart062a2e82014-02-03 09:41:57 -0800110 // TODO But, this will cause everything else to fail
111 log.warn("Trying to deactivate object that doesn't exist", e);
112 } catch (WrongVersionException e) {
113 // Need to re-read and retry
114 }
115 }
116 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800117
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800118 public void addPort(PortEvent port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800119 log.debug("Adding port {}", port);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800120// RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
121//
122// try {
123// rcSwitch.read();
124// } catch (ObjectDoesntExistException e) {
125// log.warn("Add port failed because switch {} doesn't exist", sw.getDpid(), e);
126// return;
127// }
128//
129// RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
130// rcPort.setStatus(RCPort.STATUS.ACTIVE);
131// // TODO add description into RCPort
132// //rcPort.setDescription(port.getDescription());
133// rcSwitch.addPortId(rcPort.getId());
134//
135// writeObject(rcPort);
136// writeObject(rcSwitch);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800137 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800138
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800139 public void deactivatePort(PortEvent port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800140 log.debug("Deactivating port {}", port);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800141// RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
142//
143// for (int i = 0; i < NUM_RETRIES; i++) {
144// try {
145// rcPort.read();
146// } catch (ObjectDoesntExistException e) {
147// // oh well, we were deactivating anyway
148// log.warn("Trying to deactivate a port that doesn't exist: {}", port);
149// return;
150// }
151//
152// rcPort.setStatus(RCPort.STATUS.INACTIVE);
153//
154// try {
155// rcPort.update();
156// break;
157// } catch (ObjectDoesntExistException | WrongVersionException e) {
158// // retry
159// }
160// }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800161 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800162
Jonathan Hart369875b2014-02-13 10:00:31 -0800163 public void addLink(LinkEvent linkEvent) {
164 log.debug("Adding link {}", linkEvent);
165
166 RCLink rcLink = new RCLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(),
167 linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
168
169 //RCPort rcSrcPort = new RCPort(link.getSrc().getDpid(), link.getSrc().getNumber());
170 //RCPort rcDstPort = new RCPort(link.getDst().getDpid(), link.getDst().getNumber());
171
172 for (int i = 0; i < NUM_RETRIES; i++) {
173 try {
174 //rcSrcPort.read();
175 //rcDstPort.read();
176 rcLink.create();
177 //} catch (ObjectDoesntExistException e) {
178 // port doesn't exist
179 //log.error("Add link failed {}", link, e);
180 //return;
181 } catch (ObjectExistsException e) {
182 log.debug("Link already exists {}", linkEvent);
183 return;
184 }
185
186 //rcSrcPort.addLinkId(rcLink.getId());
187 //rcDstPort.addLinkId(rcLink.getId());
188
189 rcLink.setStatus(RCLink.STATUS.ACTIVE);
190
191 try {
192 rcLink.update();
193 //rcSrcPort.update();
194 //rcDstPort.update();
195 break;
196 } catch (ObjectDoesntExistException | WrongVersionException e) {
197 log.debug(" ", e);
198 // retry
199 }
200 }
201
202 // Publish event to in-memory cache
203 graph.putLink(linkEvent);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800204 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800205
Jonathan Hart369875b2014-02-13 10:00:31 -0800206 public void removeLink(LinkEvent linkEvent) {
207 log.debug("Removing link {}", linkEvent);
208 RCLink rcLink = new RCLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(),
209 linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
210
211 //RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
212 //RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
213
214 for (int i = 0; i < NUM_RETRIES; i++) {
215 try {
216 //rcSrcPort.read();
217 //rcDstPort.read();
218 rcLink.read();
219 } catch (ObjectDoesntExistException e) {
220 log.error("Remove link failed {}", linkEvent, e);
221 return;
222 }
223
224 //rcSrcPort.removeLinkId(rcLink.getId());
225 //rcDstPort.removeLinkId(rcLink.getId());
226
227 try {
228 //rcSrcPort.update();
229 //rcDstPort.update();
230 rcLink.delete();
231 } catch (ObjectDoesntExistException e) {
232 log.error("Remove link failed {}", linkEvent, e);
233 return;
234 } catch (WrongVersionException e) {
235 // retry
236 }
237 }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800238 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800239
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800240 public void updateDevice(DeviceEvent device) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800241 // TODO implement
242 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800243
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800244 public void removeDevice(DeviceEvent device) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800245 // TODO implement
246 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800247
Jonathan Hart062a2e82014-02-03 09:41:57 -0800248 // TODO what happens if this fails? why could it fail?
249 private void writeObject(RCObject object) {
250 for (int i = 0; i < NUM_RETRIES; i++) {
251 try {
252 object.create();
253 } catch (ObjectExistsException e) {
254 try {
255 object.read();
256 } catch (ObjectDoesntExistException e1) {
257 // TODO Auto-generated catch block
258 log.error(" ", e);
259 return;
260 }
261 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800262
Jonathan Hart062a2e82014-02-03 09:41:57 -0800263 try {
264 // TODO check API for writing without caring what's there
265 object.update();
266 break;
267 } catch (ObjectDoesntExistException | WrongVersionException e) {
268 log.debug(" ", e);
269 // re-read and retry
270 }
271 }
272 }
273}