blob: 84882974b47cd7bdc86a1e39b6eb73a99f79465d [file] [log] [blame]
Jonathan Hart472062d2014-04-03 10:56:48 -07001package net.onrc.onos.core.topology;
Jonathan Hart062a2e82014-02-03 09:41:57 -08002
TeruUd1c5b652014-03-24 13:58:46 -07003import java.net.InetAddress;
Jonathan Hart062a2e82014-02-03 09:41:57 -08004import java.util.ArrayList;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08005import java.util.Collection;
Jonathan Harta99ec672014-04-03 11:30:34 -07006import java.util.List;
Jonathan Hart062a2e82014-02-03 09:41:57 -08007
Jonathan Hart6df90172014-04-03 10:13:11 -07008import net.onrc.onos.core.datastore.DataStoreClient;
9import net.onrc.onos.core.datastore.IKVClient;
10import net.onrc.onos.core.datastore.topology.KVDevice;
11import net.onrc.onos.core.datastore.topology.KVLink;
12import net.onrc.onos.core.datastore.topology.KVPort;
Jonathan Hart6df90172014-04-03 10:13:11 -070013import net.onrc.onos.core.datastore.topology.KVPort.STATUS;
Jonathan Harta99ec672014-04-03 11:30:34 -070014import net.onrc.onos.core.datastore.topology.KVSwitch;
Jonathan Hart6df90172014-04-03 10:13:11 -070015import net.onrc.onos.core.datastore.utils.KVObject;
16import net.onrc.onos.core.datastore.utils.KVObject.WriteOp;
Jonathan Hart472062d2014-04-03 10:56:48 -070017import net.onrc.onos.core.topology.PortEvent.SwitchPort;
Jonathan Hart062a2e82014-02-03 09:41:57 -080018
19import org.slf4j.Logger;
20import org.slf4j.LoggerFactory;
21
TeruUd1c5b652014-03-24 13:58:46 -070022import com.google.common.net.InetAddresses;
23
Jonathan Hart062a2e82014-02-03 09:41:57 -080024/**
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080025 * The southbound interface to the network graph which allows clients to
Jonathan Hart062a2e82014-02-03 09:41:57 -080026 * mutate the graph. This class will maintain the invariants of the network
27 * graph. The southbound discovery modules will use this interface to update
28 * the network graph as they learn about the state of the network.
29 *
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080030 * Modification to the Network Map by this module will:
31 * 1. Writes to Cluster-wide DataStore.
32 * 2. Update ONOS instance In-memory Network Map.
33 * 3. Send-out Notification. (TBD)
34 * (XXX: To update other instances In-memory Network Map,
35 * notification should be triggered here.
36 * But if we want to aggregate notification to minimize notification,
37 * It might be better for the caller to trigger notification.)
38 *
Jonathan Hart062a2e82014-02-03 09:41:57 -080039 */
Jonathan Hartfa01c242014-02-11 10:03:03 -080040public class NetworkGraphDatastore {
41 private static final Logger log = LoggerFactory.getLogger(NetworkGraphDatastore.class);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080042
Pavlin Radoslavovca529072014-02-19 14:07:52 -080043 /**
44 * Add a switch to the database.
45 *
46 * @param sw the switch to add.
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080047 * @param portEvents the corresponding switch ports to add.
Pavlin Radoslavovca529072014-02-19 14:07:52 -080048 * @return true on success, otherwise false.
49 */
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080050 public boolean addSwitch(SwitchEvent sw,
51 Collection<PortEvent> portEvents) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080052 log.debug("Adding switch {}", sw);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080053 ArrayList<WriteOp> groupOp = new ArrayList<>();
54
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070055 KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
56 rcSwitch.setStatus(KVSwitch.STATUS.ACTIVE);
57
58 IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080059
60 // XXX Is ForceCreating Switch on DB OK here?
61 // If ForceCreating, who ever is calling this method needs
62 // to assure that DPID is unique cluster-wide, etc.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070063 groupOp.add(rcSwitch.forceCreateOp(client));
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080064
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080065 for (PortEvent portEvent : portEvents) {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070066 KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getNumber());
67 rcPort.setStatus(KVPort.STATUS.ACTIVE);
Jonathan Hart69864df2014-02-13 10:44:12 -080068
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070069 groupOp.add(rcPort.forceCreateOp(client));
Jonathan Hart69864df2014-02-13 10:44:12 -080070 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080071
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070072 boolean failed = KVObject.multiWrite(groupOp);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080073
Jonathan Hart369875b2014-02-13 10:00:31 -080074 if (failed) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080075 log.error("Adding Switch {} and its ports failed.", sw.getDpid());
Jonathan Hart369875b2014-02-13 10:00:31 -080076 for (WriteOp op : groupOp) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080077 log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus() );
78
79 // If we changed the operation from ForceCreate to
80 // Conditional operation (Create/Update) then we should retry here.
81 }
82 }
Jonathan Hartdaea86f2014-02-19 15:28:42 -080083 return !failed;
Jonathan Hart062a2e82014-02-03 09:41:57 -080084 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080085
Pavlin Radoslavovca529072014-02-19 14:07:52 -080086 /**
87 * Update a switch as inactive in the database.
88 *
89 * @param sw the switch to update.
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080090 * @param portEvents the corresponding switch ports to update.
Pavlin Radoslavovca529072014-02-19 14:07:52 -080091 * @return true on success, otherwise false.
92 */
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080093 public boolean deactivateSwitch(SwitchEvent sw,
94 Collection<PortEvent> portEvents) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080095 log.debug("Deactivating switch {}", sw);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070096 KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
97
98 IKVClient client = DataStoreClient.getClient();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080099
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800100 List<WriteOp> groupOp = new ArrayList<>();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700101 rcSwitch.setStatus(KVSwitch.STATUS.INACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800102
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700103 groupOp.add(rcSwitch.forceCreateOp(client));
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800104
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800105 for (PortEvent portEvent : portEvents) {
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700106 KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getNumber());
107 rcPort.setStatus(KVPort.STATUS.INACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800108
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700109 groupOp.add(rcPort.forceCreateOp(client));
Jonathan Hart062a2e82014-02-03 09:41:57 -0800110 }
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800111
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700112 boolean failed = KVObject.multiWrite(groupOp);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800113
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800114 return !failed;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800115 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800116
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800117 /**
118 * Add a port to the database.
119 *
120 * @param port the port to add.
121 * @return true on success, otherwise false.
122 */
123 public boolean addPort(PortEvent port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800124 log.debug("Adding port {}", port);
Jonathan Hart4c263272014-02-13 17:41:05 -0800125
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700126 KVPort rcPort = new KVPort(port.getDpid(), port.getNumber());
127 rcPort.setStatus(KVPort.STATUS.ACTIVE);
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800128 rcPort.forceCreate();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700129 // TODO add description into KVPort
Jonathan Hart4c263272014-02-13 17:41:05 -0800130 //rcPort.setDescription(port.getDescription());
Jonathan Hart4c263272014-02-13 17:41:05 -0800131
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800132 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800133 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800134
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800135 /**
136 * Update a port as inactive in the database.
137 *
138 * @param port the port to update.
139 * @return true on success, otherwise false.
140 */
141 public boolean deactivatePort(PortEvent port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800142 log.debug("Deactivating port {}", port);
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -0800143
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700144 KVPort rcPort = new KVPort(port.getDpid(), port.getNumber());
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800145 rcPort.setStatus(STATUS.INACTIVE);
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -0800146
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800147 rcPort.forceCreate();
Jonathan Hart4c263272014-02-13 17:41:05 -0800148
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800149 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800150 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800151
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800152 /**
153 * Add a link to the database.
154 *
155 * @param link the link to add.
156 * @return true on success, otherwise false.
157 */
158 public boolean addLink(LinkEvent link) {
159 log.debug("Adding link {}", link);
Yuta HIGUCHI0a4bd192014-02-17 13:52:34 -0800160
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700161 KVLink rcLink = new KVLink(link.getSrc().getDpid(),
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800162 link.getSrc().getNumber(),
163 link.getDst().getDpid(),
164 link.getDst().getNumber());
Jonathan Hart369875b2014-02-13 10:00:31 -0800165
Yuta HIGUCHIef479672014-02-19 09:14:39 -0800166 // XXX This method is called only by discovery,
167 // which means what we are trying to write currently is the truth
168 // so we can force write here
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800169 //
170 // TODO: We need to check for errors
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700171 rcLink.setStatus(KVLink.STATUS.ACTIVE);
Yuta HIGUCHIef479672014-02-19 09:14:39 -0800172 rcLink.forceCreate();
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800173
174 return true; // Success
Jonathan Hart062a2e82014-02-03 09:41:57 -0800175 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800176
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800177 public boolean removeLink(LinkEvent linkEvent) {
178 log.debug("Removing link {}", linkEvent);
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -0800179
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700180 KVLink rcLink = new KVLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(),
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800181 linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
182 rcLink.forceDelete();
Jonathan Hart369875b2014-02-13 10:00:31 -0800183
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800184 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800185 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800186
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800187 /**
188 * Add a device to the database.
189 *
190 * @param device the device to add.
191 * @return true on success, otherwise false.
192 */
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800193 public boolean addDevice(DeviceEvent device) {
TeruUd1c5b652014-03-24 13:58:46 -0700194 log.debug("Adding device into DB. mac {}", device.getMac());
195
196 KVDevice rcDevice = new KVDevice(device.getMac().toBytes());
197 rcDevice.setLastSeenTime(device.getLastSeenTime());
198
199 for(SwitchPort sp : device.getAttachmentPoints()) {
200 byte[] portId = KVPort.getPortID(sp.getDpid(), sp.getNumber());
201 rcDevice.addPortId(portId);
202 }
203
204 for(InetAddress addr : device.getIpAddresses()) {
205 //It assume only one ip on a device now.
206 rcDevice.setIp(InetAddresses.coerceToInteger(addr));
207 }
208
209 rcDevice.forceCreate();
210
211 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800212 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800213
Pavlin Radoslavovca529072014-02-19 14:07:52 -0800214 /**
215 * Remove a device from the database.
216 *
217 * @param device the device to remove.
218 * @return true on success, otherwise false.
219 */
220 public boolean removeDevice(DeviceEvent device) {
TeruUd1c5b652014-03-24 13:58:46 -0700221 log.debug("Removing device into DB. mac {}", device.getMac());
222
223 KVDevice rcDevice = new KVDevice(device.getMac().toBytes());
224 rcDevice.forceDelete();
225
226 return true;
Jonathan Hart062a2e82014-02-03 09:41:57 -0800227 }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800228}