blob: b9ed471fdcddf7bd08cb918fdd74aee8720b2d99 [file] [log] [blame]
Jonathan Hart062a2e82014-02-03 09:41:57 -08001package net.onrc.onos.ofcontroller.networkgraph;
2
TeruUd1c5b652014-03-24 13:58:46 -07003import java.net.Inet4Address;
4import java.net.InetAddress;
Jonathan Hart062a2e82014-02-03 09:41:57 -08005import java.util.ArrayList;
6import java.util.List;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08007import java.util.Collection;
Jonathan Hart062a2e82014-02-03 09:41:57 -08008
Jonathan Hart6df90172014-04-03 10:13:11 -07009import net.onrc.onos.core.datastore.DataStoreClient;
10import net.onrc.onos.core.datastore.IKVClient;
11import net.onrc.onos.core.datastore.topology.KVDevice;
12import net.onrc.onos.core.datastore.topology.KVLink;
13import net.onrc.onos.core.datastore.topology.KVPort;
14import net.onrc.onos.core.datastore.topology.KVSwitch;
15import net.onrc.onos.core.datastore.topology.KVPort.STATUS;
16import net.onrc.onos.core.datastore.utils.KVObject;
17import net.onrc.onos.core.datastore.utils.KVObject.WriteOp;
TeruUd1c5b652014-03-24 13:58:46 -070018import net.onrc.onos.ofcontroller.networkgraph.PortEvent.SwitchPort;
Jonathan Hart062a2e82014-02-03 09:41:57 -080019
20import org.slf4j.Logger;
21import org.slf4j.LoggerFactory;
22
TeruUd1c5b652014-03-24 13:58:46 -070023import com.google.common.net.InetAddresses;
24
Jonathan Hart062a2e82014-02-03 09:41:57 -080025/**
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080026 * The southbound interface to the network graph which allows clients to
Jonathan Hart062a2e82014-02-03 09:41:57 -080027 * mutate the graph. This class will maintain the invariants of the network
28 * graph. The southbound discovery modules will use this interface to update
29 * the network graph as they learn about the state of the network.
30 *
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080031 * Modification to the Network Map by this module will:
32 * 1. Writes to Cluster-wide DataStore.
33 * 2. Update ONOS instance In-memory Network Map.
34 * 3. Send-out Notification. (TBD)
35 * (XXX: To update other instances In-memory Network Map,
36 * notification should be triggered here.
37 * But if we want to aggregate notification to minimize notification,
38 * It might be better for the caller to trigger notification.)
39 *
Jonathan Hart062a2e82014-02-03 09:41:57 -080040 */
Jonathan Hartfa01c242014-02-11 10:03:03 -080041public class NetworkGraphDatastore {
42 private static final Logger log = LoggerFactory.getLogger(NetworkGraphDatastore.class);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080043
Pavlin Radoslavovca529072014-02-19 14:07:52 -080044 /**
45 * Add a switch to the database.
46 *
47 * @param sw the switch to add.
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080048 * @param portEvents the corresponding switch ports to add.
Pavlin Radoslavovca529072014-02-19 14:07:52 -080049 * @return true on success, otherwise false.
50 */
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080051 public boolean addSwitch(SwitchEvent sw,
52 Collection<PortEvent> portEvents) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080053 log.debug("Adding switch {}", sw);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080054 ArrayList<WriteOp> groupOp = new ArrayList<>();
55
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070056 KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
57 rcSwitch.setStatus(KVSwitch.STATUS.ACTIVE);
58
59 IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080060
61 // XXX Is ForceCreating Switch on DB OK here?
62 // If ForceCreating, who ever is calling this method needs
63 // to assure that DPID is unique cluster-wide, etc.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070064 groupOp.add(rcSwitch.forceCreateOp(client));
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080065
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080066 for (PortEvent portEvent : portEvents) {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070067 KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getNumber());
68 rcPort.setStatus(KVPort.STATUS.ACTIVE);
Jonathan Hart69864df2014-02-13 10:44:12 -080069
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070070 groupOp.add(rcPort.forceCreateOp(client));
Jonathan Hart69864df2014-02-13 10:44:12 -080071 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080072
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070073 boolean failed = KVObject.multiWrite(groupOp);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080074
Jonathan Hart369875b2014-02-13 10:00:31 -080075 if (failed) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080076 log.error("Adding Switch {} and its ports failed.", sw.getDpid());
Jonathan Hart369875b2014-02-13 10:00:31 -080077 for (WriteOp op : groupOp) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080078 log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus() );
79
80 // If we changed the operation from ForceCreate to
81 // Conditional operation (Create/Update) then we should retry here.
82 }
83 }
Jonathan Hartdaea86f2014-02-19 15:28:42 -080084 return !failed;
Jonathan Hart062a2e82014-02-03 09:41:57 -080085 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080086
Pavlin Radoslavovca529072014-02-19 14:07:52 -080087 /**
88 * Update a switch as inactive in the database.
89 *
90 * @param sw the switch to update.
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080091 * @param portEvents the corresponding switch ports to update.
Pavlin Radoslavovca529072014-02-19 14:07:52 -080092 * @return true on success, otherwise false.
93 */
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080094 public boolean deactivateSwitch(SwitchEvent sw,
95 Collection<PortEvent> portEvents) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080096 log.debug("Deactivating switch {}", sw);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070097 KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
98
99 IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800100
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800101 List<WriteOp> groupOp = new ArrayList<>();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700102 rcSwitch.setStatus(KVSwitch.STATUS.INACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800103
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700104 groupOp.add(rcSwitch.forceCreateOp(client));
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800105
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800106 for (PortEvent portEvent : portEvents) {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700107 KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getNumber());
108 rcPort.setStatus(KVPort.STATUS.INACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800109
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700110 groupOp.add(rcPort.forceCreateOp(client));
Jonathan Hart062a2e82014-02-03 09:41:57 -0800111 }
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800112
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700113 boolean failed = KVObject.multiWrite(groupOp);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800114
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800115 return !failed;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800116 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800117
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800118 /**
119 * Add a port to the database.
120 *
121 * @param port the port to add.
122 * @return true on success, otherwise false.
123 */
124 public boolean addPort(PortEvent port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800125 log.debug("Adding port {}", port);
Jonathan Hart4c263272014-02-13 17:41:05 -0800126
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700127 KVPort rcPort = new KVPort(port.getDpid(), port.getNumber());
128 rcPort.setStatus(KVPort.STATUS.ACTIVE);
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800129 rcPort.forceCreate();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700130 // TODO add description into KVPort
Jonathan Hart4c263272014-02-13 17:41:05 -0800131 //rcPort.setDescription(port.getDescription());
Jonathan Hart4c263272014-02-13 17:41:05 -0800132
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800133 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800134 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800135
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800136 /**
137 * Update a port as inactive in the database.
138 *
139 * @param port the port to update.
140 * @return true on success, otherwise false.
141 */
142 public boolean deactivatePort(PortEvent port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800143 log.debug("Deactivating port {}", port);
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -0800144
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700145 KVPort rcPort = new KVPort(port.getDpid(), port.getNumber());
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800146 rcPort.setStatus(STATUS.INACTIVE);
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -0800147
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800148 rcPort.forceCreate();
Jonathan Hart4c263272014-02-13 17:41:05 -0800149
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800150 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800151 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800152
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800153 /**
154 * Add a link to the database.
155 *
156 * @param link the link to add.
157 * @return true on success, otherwise false.
158 */
159 public boolean addLink(LinkEvent link) {
160 log.debug("Adding link {}", link);
Yuta HIGUCHI0a4bd192014-02-17 13:52:34 -0800161
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700162 KVLink rcLink = new KVLink(link.getSrc().getDpid(),
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800163 link.getSrc().getNumber(),
164 link.getDst().getDpid(),
165 link.getDst().getNumber());
Jonathan Hart369875b2014-02-13 10:00:31 -0800166
Yuta HIGUCHIef479672014-02-19 09:14:39 -0800167 // XXX This method is called only by discovery,
168 // which means what we are trying to write currently is the truth
169 // so we can force write here
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800170 //
171 // TODO: We need to check for errors
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700172 rcLink.setStatus(KVLink.STATUS.ACTIVE);
Yuta HIGUCHIef479672014-02-19 09:14:39 -0800173 rcLink.forceCreate();
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800174
175 return true; // Success
Jonathan Hart062a2e82014-02-03 09:41:57 -0800176 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800177
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800178 public boolean removeLink(LinkEvent linkEvent) {
179 log.debug("Removing link {}", linkEvent);
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -0800180
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700181 KVLink rcLink = new KVLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(),
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800182 linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
183 rcLink.forceDelete();
Jonathan Hart369875b2014-02-13 10:00:31 -0800184
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800185 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800186 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800187
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800188 /**
189 * Add a device to the database.
190 *
191 * @param device the device to add.
192 * @return true on success, otherwise false.
193 */
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800194 public boolean addDevice(DeviceEvent device) {
TeruUd1c5b652014-03-24 13:58:46 -0700195 log.debug("Adding device into DB. mac {}", device.getMac());
196
197 KVDevice rcDevice = new KVDevice(device.getMac().toBytes());
198 rcDevice.setLastSeenTime(device.getLastSeenTime());
199
200 for(SwitchPort sp : device.getAttachmentPoints()) {
201 byte[] portId = KVPort.getPortID(sp.getDpid(), sp.getNumber());
202 rcDevice.addPortId(portId);
203 }
204
205 for(InetAddress addr : device.getIpAddresses()) {
206 //It assume only one ip on a device now.
207 rcDevice.setIp(InetAddresses.coerceToInteger(addr));
208 }
209
210 rcDevice.forceCreate();
211
212 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800213 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800214
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800215 /**
216 * Remove a device from the database.
217 *
218 * @param device the device to remove.
219 * @return true on success, otherwise false.
220 */
221 public boolean removeDevice(DeviceEvent device) {
TeruUd1c5b652014-03-24 13:58:46 -0700222 log.debug("Removing device into DB. mac {}", device.getMac());
223
224 KVDevice rcDevice = new KVDevice(device.getMac().toBytes());
225 rcDevice.forceDelete();
226
227 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800228 }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800229}