blob: 126d29988dad4cb7aaea935bf9805b775f2d7a94 [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);
Jonathan Hart4c263272014-02-13 17:41:05 -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.getDpid(), 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);
Jonathan Hart4c263272014-02-13 17:41:05 -0800143 RCPort rcPort = new RCPort(port.getDpid(), 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);
Yuta HIGUCHI0a4bd192014-02-17 13:52:34 -0800167
Jonathan Hart369875b2014-02-13 10:00:31 -0800168 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) {
Yuta HIGUCHI0a4bd192014-02-17 13:52:34 -0800222 // XXX Note: This error might be harmless, if triggered by out-dated remove Link event
Jonathan Hart369875b2014-02-13 10:00:31 -0800223 log.error("Remove link failed {}", linkEvent, e);
224 return;
225 }
226
227 //rcSrcPort.removeLinkId(rcLink.getId());
228 //rcDstPort.removeLinkId(rcLink.getId());
229
230 try {
231 //rcSrcPort.update();
232 //rcDstPort.update();
233 rcLink.delete();
Jonathan Hart480c5572014-02-14 18:28:16 -0800234 return;
Jonathan Hart369875b2014-02-13 10:00:31 -0800235 } catch (ObjectDoesntExistException e) {
236 log.error("Remove link failed {}", linkEvent, e);
237 return;
238 } catch (WrongVersionException e) {
239 // retry
240 }
241 }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800242 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800243
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800244 public void updateDevice(DeviceEvent device) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800245 // TODO implement
246 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800247
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800248 public void removeDevice(DeviceEvent device) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800249 // TODO implement
250 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800251
Jonathan Hart062a2e82014-02-03 09:41:57 -0800252 // TODO what happens if this fails? why could it fail?
253 private void writeObject(RCObject object) {
254 for (int i = 0; i < NUM_RETRIES; i++) {
255 try {
256 object.create();
257 } catch (ObjectExistsException e) {
258 try {
259 object.read();
260 } catch (ObjectDoesntExistException e1) {
261 // TODO Auto-generated catch block
262 log.error(" ", e);
263 return;
264 }
265 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800266
Jonathan Hart062a2e82014-02-03 09:41:57 -0800267 try {
268 // TODO check API for writing without caring what's there
269 object.update();
270 break;
271 } catch (ObjectDoesntExistException | WrongVersionException e) {
272 log.debug(" ", e);
273 // re-read and retry
274 }
275 }
276 }
277}