Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 1 | package net.onrc.onos.ofcontroller.networkgraph; |
| 2 | |
| 3 | import java.util.ArrayList; |
| 4 | import java.util.List; |
Pavlin Radoslavov | 018d533 | 2014-02-19 23:08:35 -0800 | [diff] [blame] | 5 | import java.util.Collection; |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 6 | |
| 7 | import net.onrc.onos.datastore.RCObject; |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 8 | import net.onrc.onos.datastore.RCObject.WriteOp; |
Jonathan Hart | 369875b | 2014-02-13 10:00:31 -0800 | [diff] [blame] | 9 | import net.onrc.onos.datastore.topology.RCLink; |
Jonathan Hart | 69864df | 2014-02-13 10:44:12 -0800 | [diff] [blame] | 10 | import net.onrc.onos.datastore.topology.RCPort; |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 11 | import net.onrc.onos.datastore.topology.RCPort.STATUS; |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 12 | import net.onrc.onos.datastore.topology.RCSwitch; |
| 13 | |
| 14 | import org.slf4j.Logger; |
| 15 | import org.slf4j.LoggerFactory; |
| 16 | |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 17 | /** |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 18 | * The southbound interface to the network graph which allows clients to |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 19 | * mutate the graph. This class will maintain the invariants of the network |
| 20 | * graph. The southbound discovery modules will use this interface to update |
| 21 | * the network graph as they learn about the state of the network. |
| 22 | * |
Yuta HIGUCHI | 181d34d | 2014-02-05 15:05:46 -0800 | [diff] [blame] | 23 | * Modification to the Network Map by this module will: |
| 24 | * 1. Writes to Cluster-wide DataStore. |
| 25 | * 2. Update ONOS instance In-memory Network Map. |
| 26 | * 3. Send-out Notification. (TBD) |
| 27 | * (XXX: To update other instances In-memory Network Map, |
| 28 | * notification should be triggered here. |
| 29 | * But if we want to aggregate notification to minimize notification, |
| 30 | * It might be better for the caller to trigger notification.) |
| 31 | * |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 32 | */ |
Jonathan Hart | fa01c24 | 2014-02-11 10:03:03 -0800 | [diff] [blame] | 33 | public class NetworkGraphDatastore { |
| 34 | private static final Logger log = LoggerFactory.getLogger(NetworkGraphDatastore.class); |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 35 | |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 36 | /** |
| 37 | * Add a switch to the database. |
| 38 | * |
| 39 | * @param sw the switch to add. |
Pavlin Radoslavov | 018d533 | 2014-02-19 23:08:35 -0800 | [diff] [blame] | 40 | * @param portEvents the corresponding switch ports to add. |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 41 | * @return true on success, otherwise false. |
| 42 | */ |
Pavlin Radoslavov | 018d533 | 2014-02-19 23:08:35 -0800 | [diff] [blame] | 43 | public boolean addSwitch(SwitchEvent sw, |
| 44 | Collection<PortEvent> portEvents) { |
Jonathan Hart | 4b5bbb5 | 2014-02-06 10:09:31 -0800 | [diff] [blame] | 45 | log.debug("Adding switch {}", sw); |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 46 | ArrayList<WriteOp> groupOp = new ArrayList<>(); |
| 47 | |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 48 | RCSwitch rcSwitch = new RCSwitch(sw.getDpid()); |
| 49 | rcSwitch.setStatus(RCSwitch.STATUS.ACTIVE); |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 50 | |
| 51 | // XXX Is ForceCreating Switch on DB OK here? |
| 52 | // If ForceCreating, who ever is calling this method needs |
| 53 | // to assure that DPID is unique cluster-wide, etc. |
| 54 | groupOp.add(WriteOp.ForceCreate(rcSwitch)); |
| 55 | |
Pavlin Radoslavov | 018d533 | 2014-02-19 23:08:35 -0800 | [diff] [blame] | 56 | for (PortEvent portEvent : portEvents) { |
Jonathan Hart | 69864df | 2014-02-13 10:44:12 -0800 | [diff] [blame] | 57 | RCPort rcPort = new RCPort(sw.getDpid(), portEvent.getNumber()); |
| 58 | rcPort.setStatus(RCPort.STATUS.ACTIVE); |
Jonathan Hart | 69864df | 2014-02-13 10:44:12 -0800 | [diff] [blame] | 59 | |
| 60 | groupOp.add(WriteOp.ForceCreate(rcPort)); |
| 61 | } |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 62 | |
Jonathan Hart | 369875b | 2014-02-13 10:00:31 -0800 | [diff] [blame] | 63 | boolean failed = RCObject.multiWrite(groupOp); |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 64 | |
Jonathan Hart | 369875b | 2014-02-13 10:00:31 -0800 | [diff] [blame] | 65 | if (failed) { |
Jonathan Hart | 4b5bbb5 | 2014-02-06 10:09:31 -0800 | [diff] [blame] | 66 | log.error("Adding Switch {} and its ports failed.", sw.getDpid()); |
Jonathan Hart | 369875b | 2014-02-13 10:00:31 -0800 | [diff] [blame] | 67 | for (WriteOp op : groupOp) { |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 68 | log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus() ); |
| 69 | |
| 70 | // If we changed the operation from ForceCreate to |
| 71 | // Conditional operation (Create/Update) then we should retry here. |
| 72 | } |
| 73 | } |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 74 | return !failed; |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 75 | } |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 76 | |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 77 | /** |
| 78 | * Update a switch as inactive in the database. |
| 79 | * |
| 80 | * @param sw the switch to update. |
Pavlin Radoslavov | 018d533 | 2014-02-19 23:08:35 -0800 | [diff] [blame] | 81 | * @param portEvents the corresponding switch ports to update. |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 82 | * @return true on success, otherwise false. |
| 83 | */ |
Pavlin Radoslavov | 018d533 | 2014-02-19 23:08:35 -0800 | [diff] [blame] | 84 | public boolean deactivateSwitch(SwitchEvent sw, |
| 85 | Collection<PortEvent> portEvents) { |
Jonathan Hart | 4b5bbb5 | 2014-02-06 10:09:31 -0800 | [diff] [blame] | 86 | log.debug("Deactivating switch {}", sw); |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 87 | RCSwitch rcSwitch = new RCSwitch(sw.getDpid()); |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 88 | |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 89 | List<WriteOp> groupOp = new ArrayList<>(); |
| 90 | rcSwitch.setStatus(RCSwitch.STATUS.INACTIVE); |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 91 | |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 92 | groupOp.add(WriteOp.ForceCreate(rcSwitch)); |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 93 | |
Pavlin Radoslavov | 018d533 | 2014-02-19 23:08:35 -0800 | [diff] [blame] | 94 | for (PortEvent portEvent : portEvents) { |
Yuta HIGUCHI | 5d2d8d4 | 2014-02-20 22:22:53 -0800 | [diff] [blame] | 95 | RCPort rcPort = new RCPort(sw.getDpid(), portEvent.getNumber()); |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 96 | rcPort.setStatus(RCPort.STATUS.INACTIVE); |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 97 | |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 98 | groupOp.add(WriteOp.ForceCreate(rcPort)); |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 99 | } |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 100 | |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 101 | boolean failed = RCObject.multiWrite(groupOp); |
Pavlin Radoslavov | 018d533 | 2014-02-19 23:08:35 -0800 | [diff] [blame] | 102 | |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 103 | return !failed; |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 104 | } |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 105 | |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 106 | /** |
| 107 | * Add a port to the database. |
| 108 | * |
| 109 | * @param port the port to add. |
| 110 | * @return true on success, otherwise false. |
| 111 | */ |
| 112 | public boolean addPort(PortEvent port) { |
Jonathan Hart | 4b5bbb5 | 2014-02-06 10:09:31 -0800 | [diff] [blame] | 113 | log.debug("Adding port {}", port); |
Jonathan Hart | 4c26327 | 2014-02-13 17:41:05 -0800 | [diff] [blame] | 114 | |
| 115 | RCPort rcPort = new RCPort(port.getDpid(), port.getNumber()); |
| 116 | rcPort.setStatus(RCPort.STATUS.ACTIVE); |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 117 | rcPort.forceCreate(); |
Jonathan Hart | 4c26327 | 2014-02-13 17:41:05 -0800 | [diff] [blame] | 118 | // TODO add description into RCPort |
| 119 | //rcPort.setDescription(port.getDescription()); |
Jonathan Hart | 4c26327 | 2014-02-13 17:41:05 -0800 | [diff] [blame] | 120 | |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 121 | return true; |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 122 | } |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 123 | |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 124 | /** |
| 125 | * Update a port as inactive in the database. |
| 126 | * |
| 127 | * @param port the port to update. |
| 128 | * @return true on success, otherwise false. |
| 129 | */ |
| 130 | public boolean deactivatePort(PortEvent port) { |
Jonathan Hart | 4b5bbb5 | 2014-02-06 10:09:31 -0800 | [diff] [blame] | 131 | log.debug("Deactivating port {}", port); |
Yuta HIGUCHI | 5d2d8d4 | 2014-02-20 22:22:53 -0800 | [diff] [blame] | 132 | |
Jonathan Hart | 4c26327 | 2014-02-13 17:41:05 -0800 | [diff] [blame] | 133 | RCPort rcPort = new RCPort(port.getDpid(), port.getNumber()); |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 134 | rcPort.setStatus(STATUS.INACTIVE); |
Yuta HIGUCHI | 5d2d8d4 | 2014-02-20 22:22:53 -0800 | [diff] [blame] | 135 | |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 136 | rcPort.forceCreate(); |
Jonathan Hart | 4c26327 | 2014-02-13 17:41:05 -0800 | [diff] [blame] | 137 | |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 138 | return true; |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 139 | } |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 140 | |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 141 | /** |
| 142 | * Add a link to the database. |
| 143 | * |
| 144 | * @param link the link to add. |
| 145 | * @return true on success, otherwise false. |
| 146 | */ |
| 147 | public boolean addLink(LinkEvent link) { |
| 148 | log.debug("Adding link {}", link); |
Yuta HIGUCHI | 0a4bd19 | 2014-02-17 13:52:34 -0800 | [diff] [blame] | 149 | |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 150 | RCLink rcLink = new RCLink(link.getSrc().getDpid(), |
| 151 | link.getSrc().getNumber(), |
| 152 | link.getDst().getDpid(), |
| 153 | link.getDst().getNumber()); |
Jonathan Hart | 369875b | 2014-02-13 10:00:31 -0800 | [diff] [blame] | 154 | |
Yuta HIGUCHI | ef47967 | 2014-02-19 09:14:39 -0800 | [diff] [blame] | 155 | // XXX This method is called only by discovery, |
| 156 | // which means what we are trying to write currently is the truth |
| 157 | // so we can force write here |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 158 | // |
| 159 | // TODO: We need to check for errors |
Yuta HIGUCHI | ef47967 | 2014-02-19 09:14:39 -0800 | [diff] [blame] | 160 | rcLink.setStatus(RCLink.STATUS.ACTIVE); |
| 161 | rcLink.forceCreate(); |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 162 | |
| 163 | return true; // Success |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 164 | } |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 165 | |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 166 | public boolean removeLink(LinkEvent linkEvent) { |
| 167 | log.debug("Removing link {}", linkEvent); |
Yuta HIGUCHI | 5d2d8d4 | 2014-02-20 22:22:53 -0800 | [diff] [blame] | 168 | |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 169 | RCLink rcLink = new RCLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(), |
| 170 | linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber()); |
| 171 | rcLink.forceDelete(); |
Jonathan Hart | 369875b | 2014-02-13 10:00:31 -0800 | [diff] [blame] | 172 | |
Jonathan Hart | daea86f | 2014-02-19 15:28:42 -0800 | [diff] [blame] | 173 | return true; |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 174 | } |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 175 | |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 176 | /** |
| 177 | * Add a device to the database. |
| 178 | * |
| 179 | * @param device the device to add. |
| 180 | * @return true on success, otherwise false. |
| 181 | */ |
Pavlin Radoslavov | 50cd148 | 2014-02-19 16:57:03 -0800 | [diff] [blame] | 182 | public boolean addDevice(DeviceEvent device) { |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 183 | // TODO implement |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 184 | return false; // Failure: not implemented yet |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 185 | } |
Yuta HIGUCHI | b4335ad | 2014-02-05 09:56:07 -0800 | [diff] [blame] | 186 | |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 187 | /** |
| 188 | * Remove a device from the database. |
| 189 | * |
| 190 | * @param device the device to remove. |
| 191 | * @return true on success, otherwise false. |
| 192 | */ |
| 193 | public boolean removeDevice(DeviceEvent device) { |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 194 | // TODO implement |
Pavlin Radoslavov | ca52907 | 2014-02-19 14:07:52 -0800 | [diff] [blame] | 195 | return false; // Failure: not implemented yet |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 196 | } |
Jonathan Hart | 062a2e8 | 2014-02-03 09:41:57 -0800 | [diff] [blame] | 197 | } |