blob: 288b1f44649f45dca6bb6f3c45caf25201f34f80 [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.RCLink;
9import net.onrc.onos.datastore.topology.RCPort;
10import 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;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080039
40 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
Jonathan Hart062a2e82014-02-03 09:41:57 -080046 public void addSwitch(Switch 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 Hart062a2e82014-02-03 09:41:57 -080058 for (Port port : sw.getPorts()) {
59 RCPort rcPort = new RCPort(sw.getDpid(), (long)port.getNumber());
60 rcPort.setStatus(RCPort.STATUS.ACTIVE);
61 rcSwitch.addPortId(rcPort.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080062
63 groupOp.add(WriteOp.ForceCreate(rcPort));
Jonathan Hart062a2e82014-02-03 09:41:57 -080064 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080065
66 boolean failed = RCObject.multiWrite( groupOp );
67
68 if ( failed ) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080069 log.error("Adding Switch {} and its ports failed.", sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080070 for ( WriteOp op : groupOp ) {
71 log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus() );
72
73 // If we changed the operation from ForceCreate to
74 // Conditional operation (Create/Update) then we should retry here.
75 }
76 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080077 else {
78 // Publish event to the in-memory cache
79 graph.addSwitch(sw);
80 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080081
Jonathan Hart062a2e82014-02-03 09:41:57 -080082 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080083
Jonathan Hart062a2e82014-02-03 09:41:57 -080084 public void deactivateSwitch(Switch sw) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080085 log.debug("Deactivating switch {}", sw);
Jonathan Hart062a2e82014-02-03 09:41:57 -080086 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080087
Jonathan Hart062a2e82014-02-03 09:41:57 -080088 List<RCObject> objectsToDeactive = new ArrayList<RCObject>();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080089
Jonathan Hart062a2e82014-02-03 09:41:57 -080090 for (int i = 0; i < NUM_RETRIES; i++) {
91 try {
92 rcSwitch.read();
93 rcSwitch.setStatus(RCSwitch.STATUS.INACTIVE);
94 objectsToDeactive.add(rcSwitch);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080095
Jonathan Hart062a2e82014-02-03 09:41:57 -080096 for (Port p : sw.getPorts()) {
97 RCPort rcPort = new RCPort(sw.getDpid(), (long)p.getNumber());
98 rcPort.read();
99 rcPort.setStatus(RCPort.STATUS.INACTIVE);
100 objectsToDeactive.add(rcPort);
101 }
102 } catch (ObjectDoesntExistException e) {
103 log.warn("Trying to deactivate an object that doesn't exist", e);
104 // We don't care to much if the object wasn't there, it's
105 // being deactivated anyway
106 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800107
Jonathan Hart062a2e82014-02-03 09:41:57 -0800108 try {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800109 for (RCObject rcObject : objectsToDeactive) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800110 rcObject.update();
111 }
112 break;
113 } catch (ObjectDoesntExistException e) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800114 // Unlikely, and we don't care anyway.
Jonathan Hart062a2e82014-02-03 09:41:57 -0800115 // TODO But, this will cause everything else to fail
116 log.warn("Trying to deactivate object that doesn't exist", e);
117 } catch (WrongVersionException e) {
118 // Need to re-read and retry
119 }
120 }
121 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800122
Jonathan Hart062a2e82014-02-03 09:41:57 -0800123 public void addPort(Switch sw, Port port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800124 log.debug("Adding port {}", port);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800125 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800126
Jonathan Hart062a2e82014-02-03 09:41:57 -0800127 try {
128 rcSwitch.read();
129 } catch (ObjectDoesntExistException e) {
130 log.warn("Add port failed because switch {} doesn't exist", sw.getDpid(), e);
131 return;
132 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800133
Jonathan Hart062a2e82014-02-03 09:41:57 -0800134 RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
135 rcPort.setStatus(RCPort.STATUS.ACTIVE);
Jonathan Hart891d0502014-02-10 10:04:08 -0800136 // TODO add description into RCPort
137 //rcPort.setDescription(port.getDescription());
Jonathan Hart062a2e82014-02-03 09:41:57 -0800138 rcSwitch.addPortId(rcPort.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800139
Jonathan Hart062a2e82014-02-03 09:41:57 -0800140 writeObject(rcPort);
141 writeObject(rcSwitch);
142 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800143
Jonathan Hart062a2e82014-02-03 09:41:57 -0800144 public void deactivatePort(Port port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800145 log.debug("Deactivating port {}", port);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800146 RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800147
Jonathan Hart062a2e82014-02-03 09:41:57 -0800148 for (int i = 0; i < NUM_RETRIES; i++) {
149 try {
150 rcPort.read();
151 } catch (ObjectDoesntExistException e) {
152 // oh well, we were deactivating anyway
153 log.warn("Trying to deactivate a port that doesn't exist: {}", port);
154 return;
155 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800156
Jonathan Hart062a2e82014-02-03 09:41:57 -0800157 rcPort.setStatus(RCPort.STATUS.INACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800158
Jonathan Hart062a2e82014-02-03 09:41:57 -0800159 try {
160 rcPort.update();
161 break;
162 } catch (ObjectDoesntExistException | WrongVersionException e) {
163 // retry
164 }
165 }
166 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800167
Jonathan Hart062a2e82014-02-03 09:41:57 -0800168 public void addLink(Link link) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800169 log.debug("Adding link {}", link);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800170 RCLink rcLink = new RCLink(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber(),
171 link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800172
Jonathan Hart062a2e82014-02-03 09:41:57 -0800173 RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
174 RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800175
Jonathan Hart062a2e82014-02-03 09:41:57 -0800176 for (int i = 0; i < NUM_RETRIES; i++) {
177 try {
178 rcSrcPort.read();
179 rcDstPort.read();
180 rcLink.create();
181 } catch (ObjectDoesntExistException e) {
182 // port doesn't exist
183 log.error("Add link failed {}", link, e);
184 return;
185 } catch (ObjectExistsException e) {
186 log.debug("Link already exists {}", link);
187 return;
188 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800189
Jonathan Hart062a2e82014-02-03 09:41:57 -0800190 rcSrcPort.addLinkId(rcLink.getId());
191 rcDstPort.addLinkId(rcLink.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800192
Jonathan Hart062a2e82014-02-03 09:41:57 -0800193 rcLink.setStatus(RCLink.STATUS.ACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800194
Jonathan Hart062a2e82014-02-03 09:41:57 -0800195 try {
196 rcLink.update();
197 rcSrcPort.update();
198 rcDstPort.update();
199 break;
200 } catch (ObjectDoesntExistException | WrongVersionException e) {
201 log.debug(" ", e);
202 // retry
203 }
204 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800205
206 // Publish event to in-memory cache
207 graph.addLink(link);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800208 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800209
Jonathan Hart062a2e82014-02-03 09:41:57 -0800210 public void removeLink(Link link) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800211 log.debug("Removing link {}", link);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800212 RCLink rcLink = new RCLink(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber(),
213 link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800214
Jonathan Hart062a2e82014-02-03 09:41:57 -0800215 RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
216 RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800217
Jonathan Hart062a2e82014-02-03 09:41:57 -0800218 for (int i = 0; i < NUM_RETRIES; i++) {
219 try {
220 rcSrcPort.read();
221 rcDstPort.read();
222 rcLink.read();
223 } catch (ObjectDoesntExistException e) {
224 log.error("Remove link failed {}", link, e);
225 return;
226 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800227
Jonathan Hart062a2e82014-02-03 09:41:57 -0800228 rcSrcPort.removeLinkId(rcLink.getId());
229 rcDstPort.removeLinkId(rcLink.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800230
Jonathan Hart062a2e82014-02-03 09:41:57 -0800231 try {
232 rcSrcPort.update();
233 rcDstPort.update();
234 rcLink.delete();
235 } catch (ObjectDoesntExistException e) {
236 log.error("Remove link failed {}", link, e);
237 return;
238 } catch (WrongVersionException e) {
239 // retry
240 }
241 }
242 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800243
Jonathan Hart062a2e82014-02-03 09:41:57 -0800244 public void updateDevice(Device device) {
245 // TODO implement
246 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800247
Jonathan Hart062a2e82014-02-03 09:41:57 -0800248 public void removeDevice(Device device) {
249 // 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}