blob: f5aec14c9e434b09c1a09a74a1601f896ef29fa3 [file] [log] [blame]
Jonathan Hart472062d2014-04-03 10:56:48 -07001package net.onrc.onos.core.topology;
Jonathan Hart062a2e82014-02-03 09:41:57 -08002
3import java.util.ArrayList;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08004import java.util.Collection;
Jonathan Harta99ec672014-04-03 11:30:34 -07005import java.util.List;
Jonathan Hart062a2e82014-02-03 09:41:57 -08006
Jonathan Hart6df90172014-04-03 10:13:11 -07007import net.onrc.onos.core.datastore.DataStoreClient;
8import net.onrc.onos.core.datastore.IKVClient;
9import net.onrc.onos.core.datastore.topology.KVDevice;
10import net.onrc.onos.core.datastore.topology.KVLink;
11import net.onrc.onos.core.datastore.topology.KVPort;
Jonathan Hart6df90172014-04-03 10:13:11 -070012import net.onrc.onos.core.datastore.topology.KVPort.STATUS;
Jonathan Harta99ec672014-04-03 11:30:34 -070013import net.onrc.onos.core.datastore.topology.KVSwitch;
Jonathan Hart6df90172014-04-03 10:13:11 -070014import net.onrc.onos.core.datastore.utils.KVObject;
15import net.onrc.onos.core.datastore.utils.KVObject.WriteOp;
Jonathan Hart472062d2014-04-03 10:56:48 -070016import net.onrc.onos.core.topology.PortEvent.SwitchPort;
Jonathan Hart062a2e82014-02-03 09:41:57 -080017
18import org.slf4j.Logger;
19import org.slf4j.LoggerFactory;
20
Jonathan Hart062a2e82014-02-03 09:41:57 -080021/**
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080022 * The southbound interface to the network graph which allows clients to
Jonathan Hart062a2e82014-02-03 09:41:57 -080023 * mutate the graph. This class will maintain the invariants of the network
24 * graph. The southbound discovery modules will use this interface to update
25 * the network graph as they learn about the state of the network.
Ray Milkey269ffb92014-04-03 14:43:30 -070026 * <p/>
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080027 * Modification to the Network Map by this module will:
28 * 1. Writes to Cluster-wide DataStore.
29 * 2. Update ONOS instance In-memory Network Map.
30 * 3. Send-out Notification. (TBD)
Ray Milkey269ffb92014-04-03 14:43:30 -070031 * (XXX: To update other instances In-memory Network Map,
32 * notification should be triggered here.
33 * But if we want to aggregate notification to minimize notification,
34 * It might be better for the caller to trigger notification.)
Jonathan Hart062a2e82014-02-03 09:41:57 -080035 */
Jonathan Hartfa01c242014-02-11 10:03:03 -080036public class NetworkGraphDatastore {
Ray Milkey269ffb92014-04-03 14:43:30 -070037 private static final Logger log = LoggerFactory.getLogger(NetworkGraphDatastore.class);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080038
Ray Milkey269ffb92014-04-03 14:43:30 -070039 /**
40 * Add a switch to the database.
41 *
42 * @param sw the switch to add.
43 * @param portEvents the corresponding switch ports to add.
44 * @return true on success, otherwise false.
45 */
46 public boolean addSwitch(SwitchEvent sw,
47 Collection<PortEvent> portEvents) {
48 log.debug("Adding switch {}", sw);
49 ArrayList<WriteOp> groupOp = new ArrayList<>();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080050
Ray Milkey269ffb92014-04-03 14:43:30 -070051 KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
52 rcSwitch.setStatus(KVSwitch.STATUS.ACTIVE);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070053
Ray Milkey269ffb92014-04-03 14:43:30 -070054 IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080055
Ray Milkey269ffb92014-04-03 14:43:30 -070056 // XXX Is ForceCreating Switch on DB OK here?
57 // If ForceCreating, who ever is calling this method needs
58 // to assure that DPID is unique cluster-wide, etc.
59 groupOp.add(rcSwitch.forceCreateOp(client));
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080060
Ray Milkey269ffb92014-04-03 14:43:30 -070061 for (PortEvent portEvent : portEvents) {
62 KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getNumber());
63 rcPort.setStatus(KVPort.STATUS.ACTIVE);
Jonathan Hart69864df2014-02-13 10:44:12 -080064
Ray Milkey269ffb92014-04-03 14:43:30 -070065 groupOp.add(rcPort.forceCreateOp(client));
66 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080067
Ray Milkey269ffb92014-04-03 14:43:30 -070068 boolean failed = KVObject.multiWrite(groupOp);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080069
Ray Milkey269ffb92014-04-03 14:43:30 -070070 if (failed) {
71 log.error("Adding Switch {} and its ports failed.", sw.getDpid());
72 for (WriteOp op : groupOp) {
73 log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080074
Ray Milkey269ffb92014-04-03 14:43:30 -070075 // If we changed the operation from ForceCreate to
76 // Conditional operation (Create/Update) then we should retry here.
77 }
78 }
79 return !failed;
80 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080081
Ray Milkey269ffb92014-04-03 14:43:30 -070082 /**
83 * Update a switch as inactive in the database.
84 *
85 * @param sw the switch to update.
86 * @param portEvents the corresponding switch ports to update.
87 * @return true on success, otherwise false.
88 */
89 public boolean deactivateSwitch(SwitchEvent sw,
90 Collection<PortEvent> portEvents) {
91 log.debug("Deactivating switch {}", sw);
92 KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070093
Ray Milkey269ffb92014-04-03 14:43:30 -070094 IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080095
Ray Milkey269ffb92014-04-03 14:43:30 -070096 List<WriteOp> groupOp = new ArrayList<>();
97 rcSwitch.setStatus(KVSwitch.STATUS.INACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080098
Ray Milkey269ffb92014-04-03 14:43:30 -070099 groupOp.add(rcSwitch.forceCreateOp(client));
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800100
Ray Milkey269ffb92014-04-03 14:43:30 -0700101 for (PortEvent portEvent : portEvents) {
102 KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getNumber());
103 rcPort.setStatus(KVPort.STATUS.INACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800104
Ray Milkey269ffb92014-04-03 14:43:30 -0700105 groupOp.add(rcPort.forceCreateOp(client));
106 }
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800107
Ray Milkey269ffb92014-04-03 14:43:30 -0700108 boolean failed = KVObject.multiWrite(groupOp);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800109
Ray Milkey269ffb92014-04-03 14:43:30 -0700110 return !failed;
111 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800112
Ray Milkey269ffb92014-04-03 14:43:30 -0700113 /**
114 * Add a port to the database.
115 *
116 * @param port the port to add.
117 * @return true on success, otherwise false.
118 */
119 public boolean addPort(PortEvent port) {
120 log.debug("Adding port {}", port);
Jonathan Hart4c263272014-02-13 17:41:05 -0800121
Ray Milkey269ffb92014-04-03 14:43:30 -0700122 KVPort rcPort = new KVPort(port.getDpid(), port.getNumber());
123 rcPort.setStatus(KVPort.STATUS.ACTIVE);
124 rcPort.forceCreate();
125 // TODO add description into KVPort
126 //rcPort.setDescription(port.getDescription());
Jonathan Hart4c263272014-02-13 17:41:05 -0800127
Ray Milkey269ffb92014-04-03 14:43:30 -0700128 return true;
129 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800130
Ray Milkey269ffb92014-04-03 14:43:30 -0700131 /**
132 * Update a port as inactive in the database.
133 *
134 * @param port the port to update.
135 * @return true on success, otherwise false.
136 */
137 public boolean deactivatePort(PortEvent port) {
138 log.debug("Deactivating port {}", port);
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -0800139
Ray Milkey269ffb92014-04-03 14:43:30 -0700140 KVPort rcPort = new KVPort(port.getDpid(), port.getNumber());
141 rcPort.setStatus(STATUS.INACTIVE);
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -0800142
Ray Milkey269ffb92014-04-03 14:43:30 -0700143 rcPort.forceCreate();
Jonathan Hart4c263272014-02-13 17:41:05 -0800144
Ray Milkey269ffb92014-04-03 14:43:30 -0700145 return true;
146 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800147
Ray Milkey269ffb92014-04-03 14:43:30 -0700148 /**
149 * Add a link to the database.
150 *
151 * @param link the link to add.
152 * @return true on success, otherwise false.
153 */
154 public boolean addLink(LinkEvent link) {
155 log.debug("Adding link {}", link);
Yuta HIGUCHI0a4bd192014-02-17 13:52:34 -0800156
Ray Milkey269ffb92014-04-03 14:43:30 -0700157 KVLink rcLink = new KVLink(link.getSrc().getDpid(),
158 link.getSrc().getNumber(),
159 link.getDst().getDpid(),
160 link.getDst().getNumber());
Jonathan Hart369875b2014-02-13 10:00:31 -0800161
Ray Milkey269ffb92014-04-03 14:43:30 -0700162 // XXX This method is called only by discovery,
163 // which means what we are trying to write currently is the truth
164 // so we can force write here
165 //
166 // TODO: We need to check for errors
167 rcLink.setStatus(KVLink.STATUS.ACTIVE);
168 rcLink.forceCreate();
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800169
Ray Milkey269ffb92014-04-03 14:43:30 -0700170 return true; // Success
171 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800172
Ray Milkey269ffb92014-04-03 14:43:30 -0700173 public boolean removeLink(LinkEvent linkEvent) {
174 log.debug("Removing link {}", linkEvent);
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -0800175
Ray Milkey269ffb92014-04-03 14:43:30 -0700176 KVLink rcLink = new KVLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(),
177 linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
178 rcLink.forceDelete();
Jonathan Hart369875b2014-02-13 10:00:31 -0800179
Ray Milkey269ffb92014-04-03 14:43:30 -0700180 return true;
181 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800182
Ray Milkey269ffb92014-04-03 14:43:30 -0700183 /**
184 * Add a device to the database.
185 *
186 * @param device the device to add.
187 * @return true on success, otherwise false.
188 */
189 public boolean addDevice(DeviceEvent device) {
190 log.debug("Adding device into DB. mac {}", device.getMac());
TeruUd1c5b652014-03-24 13:58:46 -0700191
Ray Milkey269ffb92014-04-03 14:43:30 -0700192 KVDevice rcDevice = new KVDevice(device.getMac().toBytes());
TeruUd1c5b652014-03-24 13:58:46 -0700193
Ray Milkey269ffb92014-04-03 14:43:30 -0700194 for (SwitchPort sp : device.getAttachmentPoints()) {
195 byte[] portId = KVPort.getPortID(sp.getDpid(), sp.getNumber());
196 rcDevice.addPortId(portId);
197 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800198
Ray Milkey269ffb92014-04-03 14:43:30 -0700199 rcDevice.forceCreate();
200
201 return true;
202 }
203
204 /**
205 * Remove a device from the database.
206 *
207 * @param device the device to remove.
208 * @return true on success, otherwise false.
209 */
210 public boolean removeDevice(DeviceEvent device) {
211 log.debug("Removing device into DB. mac {}", device.getMac());
212
213 KVDevice rcDevice = new KVDevice(device.getMac().toBytes());
214 rcDevice.forceDelete();
215
216 return true;
217 }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800218}