blob: 38f8ae1a1efaf22fbac416ab8b1c41cc22e7bb5f [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
Pavlin Radoslavovdb7dbb22014-02-18 14:45:10 -080040 private final TopologyManager graph;
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080041
Pavlin Radoslavovdb7dbb22014-02-18 14:45:10 -080042 public NetworkGraphDatastore(TopologyManager 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
Yuta HIGUCHIef479672014-02-19 09:14:39 -0800171 // XXX This method is called only by discovery,
172 // which means what we are trying to write currently is the truth
173 // so we can force write here
174 rcLink.setStatus(RCLink.STATUS.ACTIVE);
175 rcLink.forceCreate();
Jonathan Hart062a2e82014-02-03 09:41:57 -0800176 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800177
Jonathan Hart369875b2014-02-13 10:00:31 -0800178 public void removeLink(LinkEvent linkEvent) {
179 log.debug("Removing link {}", linkEvent);
180 RCLink rcLink = new RCLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(),
181 linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
182
183 //RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
184 //RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
185
186 for (int i = 0; i < NUM_RETRIES; i++) {
187 try {
188 //rcSrcPort.read();
189 //rcDstPort.read();
190 rcLink.read();
191 } catch (ObjectDoesntExistException e) {
Yuta HIGUCHI0a4bd192014-02-17 13:52:34 -0800192 // XXX Note: This error might be harmless, if triggered by out-dated remove Link event
Jonathan Hart369875b2014-02-13 10:00:31 -0800193 log.error("Remove link failed {}", linkEvent, e);
194 return;
195 }
196
197 //rcSrcPort.removeLinkId(rcLink.getId());
198 //rcDstPort.removeLinkId(rcLink.getId());
199
200 try {
201 //rcSrcPort.update();
202 //rcDstPort.update();
203 rcLink.delete();
Jonathan Hart480c5572014-02-14 18:28:16 -0800204 return;
Jonathan Hart369875b2014-02-13 10:00:31 -0800205 } catch (ObjectDoesntExistException e) {
206 log.error("Remove link failed {}", linkEvent, e);
207 return;
208 } catch (WrongVersionException e) {
209 // retry
210 }
211 }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800212 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800213
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800214 public void updateDevice(DeviceEvent device) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800215 // TODO implement
216 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800217
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800218 public void removeDevice(DeviceEvent device) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800219 // TODO implement
220 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800221
Jonathan Hart062a2e82014-02-03 09:41:57 -0800222 // TODO what happens if this fails? why could it fail?
223 private void writeObject(RCObject object) {
224 for (int i = 0; i < NUM_RETRIES; i++) {
225 try {
226 object.create();
227 } catch (ObjectExistsException e) {
228 try {
229 object.read();
230 } catch (ObjectDoesntExistException e1) {
231 // TODO Auto-generated catch block
232 log.error(" ", e);
233 return;
234 }
235 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800236
Jonathan Hart062a2e82014-02-03 09:41:57 -0800237 try {
238 // TODO check API for writing without caring what's there
239 object.update();
240 break;
241 } catch (ObjectDoesntExistException | WrongVersionException e) {
242 log.debug(" ", e);
243 // re-read and retry
244 }
245 }
246 }
247}