blob: 26904d521ff8f2dfa526ddd6fefa3480b9f04652 [file] [log] [blame]
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.ovsdb.controller.driver;
17
andreaed976a42015-10-05 14:38:25 -070018import com.fasterxml.jackson.databind.JsonNode;
19import com.google.common.base.Function;
20import com.google.common.collect.Lists;
21import com.google.common.collect.Maps;
22import com.google.common.collect.Sets;
23import com.google.common.util.concurrent.Futures;
24import com.google.common.util.concurrent.ListenableFuture;
25import com.google.common.util.concurrent.SettableFuture;
lishuai6c56f5e2015-11-17 16:38:19 +080026
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070027import io.netty.channel.Channel;
lishuai6c56f5e2015-11-17 16:38:19 +080028
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070029import org.onlab.packet.IpAddress;
andreaed976a42015-10-05 14:38:25 -070030import org.onosproject.net.DeviceId;
Hyunsun Moon1251e192016-06-07 16:57:05 -070031import org.onosproject.net.behaviour.BridgeDescription;
andreaed976a42015-10-05 14:38:25 -070032import org.onosproject.net.behaviour.ControllerInfo;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070033import org.onosproject.ovsdb.controller.OvsdbBridge;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070034import org.onosproject.ovsdb.controller.OvsdbClientService;
Hyunsun Moondd14e8e2016-06-09 16:17:32 -070035import org.onosproject.ovsdb.controller.OvsdbInterface;
36import org.onosproject.ovsdb.controller.OvsdbInterface.Type;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070037import org.onosproject.ovsdb.controller.OvsdbNodeId;
38import org.onosproject.ovsdb.controller.OvsdbPort;
39import org.onosproject.ovsdb.controller.OvsdbPortName;
40import org.onosproject.ovsdb.controller.OvsdbPortNumber;
41import org.onosproject.ovsdb.controller.OvsdbRowStore;
42import org.onosproject.ovsdb.controller.OvsdbStore;
43import org.onosproject.ovsdb.controller.OvsdbTableStore;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070044import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
45import org.onosproject.ovsdb.rfc.message.OperationResult;
46import org.onosproject.ovsdb.rfc.message.TableUpdates;
47import org.onosproject.ovsdb.rfc.notation.Condition;
48import org.onosproject.ovsdb.rfc.notation.Mutation;
CNluciusa66c3972015-09-06 20:31:29 +080049import org.onosproject.ovsdb.rfc.notation.OvsdbMap;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070050import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
51import org.onosproject.ovsdb.rfc.notation.Row;
Jonathan Hart51539b82015-10-29 09:53:04 -070052import org.onosproject.ovsdb.rfc.notation.Uuid;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070053import org.onosproject.ovsdb.rfc.operations.Delete;
54import org.onosproject.ovsdb.rfc.operations.Insert;
55import org.onosproject.ovsdb.rfc.operations.Mutate;
56import org.onosproject.ovsdb.rfc.operations.Operation;
57import org.onosproject.ovsdb.rfc.operations.Update;
58import org.onosproject.ovsdb.rfc.schema.ColumnSchema;
59import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
60import org.onosproject.ovsdb.rfc.schema.TableSchema;
61import org.onosproject.ovsdb.rfc.table.Bridge;
62import org.onosproject.ovsdb.rfc.table.Controller;
63import org.onosproject.ovsdb.rfc.table.Interface;
64import org.onosproject.ovsdb.rfc.table.OvsdbTable;
65import org.onosproject.ovsdb.rfc.table.Port;
66import org.onosproject.ovsdb.rfc.table.TableGenerator;
67import org.onosproject.ovsdb.rfc.utils.ConditionUtil;
68import org.onosproject.ovsdb.rfc.utils.FromJsonUtil;
69import org.onosproject.ovsdb.rfc.utils.JsonRpcWriterUtil;
70import org.onosproject.ovsdb.rfc.utils.MutationUtil;
71import org.slf4j.Logger;
72import org.slf4j.LoggerFactory;
73
andreaed976a42015-10-05 14:38:25 -070074import java.net.InetSocketAddress;
75import java.util.ArrayList;
76import java.util.HashSet;
77import java.util.Iterator;
78import java.util.List;
79import java.util.Map;
Hyunsun Moondd14e8e2016-06-09 16:17:32 -070080import java.util.Optional;
andreaed976a42015-10-05 14:38:25 -070081import java.util.Set;
82import java.util.concurrent.ConcurrentMap;
83import java.util.concurrent.ExecutionException;
84import java.util.concurrent.atomic.AtomicReference;
85import java.util.stream.Collectors;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070086
Hyunsun Moon1251e192016-06-07 16:57:05 -070087import static org.onosproject.ovsdb.controller.OvsdbConstant.*;
88
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070089/**
90 * An representation of an ovsdb client.
91 */
Hyunsun Moon1251e192016-06-07 16:57:05 -070092public class DefaultOvsdbClient implements OvsdbProviderService, OvsdbClientService {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070093
Hyunsun Moon1251e192016-06-07 16:57:05 -070094 private final Logger log = LoggerFactory.getLogger(DefaultOvsdbClient.class);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070095
96 private Channel channel;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070097 private OvsdbAgent agent;
98 private boolean connected;
99 private OvsdbNodeId nodeId;
100 private Callback monitorCallBack;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700101 private OvsdbStore ovsdbStore = new OvsdbStore();
102
103 private final Map<String, String> requestMethod = Maps.newHashMap();
Hyunsun Moon1251e192016-06-07 16:57:05 -0700104 private final Map<String, SettableFuture<? extends Object>> requestResult = Maps.newHashMap();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700105 private final Map<String, DatabaseSchema> schema = Maps.newHashMap();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700106
107 /**
108 * Creates an OvsdbClient.
109 *
110 * @param nodeId ovsdb node id
111 */
112 public DefaultOvsdbClient(OvsdbNodeId nodeId) {
113 this.nodeId = nodeId;
114 }
115
116 @Override
117 public OvsdbNodeId nodeId() {
118 return nodeId;
119 }
120
121 @Override
122 public void setAgent(OvsdbAgent agent) {
123 if (this.agent == null) {
124 this.agent = agent;
125 }
126 }
127
128 @Override
129 public void setChannel(Channel channel) {
130 this.channel = channel;
131 }
132
133 @Override
134 public void setConnection(boolean connected) {
135 this.connected = connected;
136 }
137
138 @Override
139 public boolean isConnected() {
140 return this.connected;
141 }
142
143 @Override
144 public void nodeAdded() {
145 this.agent.addConnectedNode(nodeId, this);
146 }
147
148 @Override
149 public void nodeRemoved() {
150 this.agent.removeConnectedNode(nodeId);
151 channel.disconnect();
152 }
153
154 /**
155 * Gets the ovsdb table store.
156 *
157 * @param dbName the ovsdb database name
158 * @return ovsTableStore, empty if table store is find
159 */
160 private OvsdbTableStore getTableStore(String dbName) {
161 if (ovsdbStore == null) {
162 return null;
163 }
164 return ovsdbStore.getOvsdbTableStore(dbName);
165 }
166
167 /**
168 * Gets the ovsdb row store.
169 *
andreaed976a42015-10-05 14:38:25 -0700170 * @param dbName the ovsdb database name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700171 * @param tableName the ovsdb table name
Hyunsun Moon6125c612015-10-15 10:54:44 -0700172 * @return ovsRowStore, empty store if no rows exist in the table
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700173 */
174 private OvsdbRowStore getRowStore(String dbName, String tableName) {
175 OvsdbTableStore tableStore = getTableStore(dbName);
176 if (tableStore == null) {
177 return null;
178 }
Hyunsun Moon6125c612015-10-15 10:54:44 -0700179
180 OvsdbRowStore rowStore = tableStore.getRows(tableName);
181 if (rowStore == null) {
182 rowStore = new OvsdbRowStore();
183 }
184 return rowStore;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700185 }
186
187 /**
188 * Gets the ovsdb row.
189 *
andreaed976a42015-10-05 14:38:25 -0700190 * @param dbName the ovsdb database name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700191 * @param tableName the ovsdb table name
andreaed976a42015-10-05 14:38:25 -0700192 * @param uuid the key of the row
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700193 * @return row, empty if row is find
194 */
195 @Override
196 public Row getRow(String dbName, String tableName, String uuid) {
197 OvsdbTableStore tableStore = getTableStore(dbName);
198 if (tableStore == null) {
199 return null;
200 }
201 OvsdbRowStore rowStore = tableStore.getRows(tableName);
202 if (rowStore == null) {
203 return null;
204 }
205 return rowStore.getRow(uuid);
206 }
207
208 @Override
209 public void removeRow(String dbName, String tableName, String uuid) {
210 OvsdbTableStore tableStore = getTableStore(dbName);
211 if (tableStore == null) {
212 return;
213 }
214 OvsdbRowStore rowStore = tableStore.getRows(tableName);
215 if (rowStore == null) {
216 return;
217 }
218 rowStore.deleteRow(uuid);
219 }
220
221 @Override
222 public void updateOvsdbStore(String dbName, String tableName, String uuid,
223 Row row) {
224 OvsdbTableStore tableStore = ovsdbStore.getOvsdbTableStore(dbName);
225 if (tableStore == null) {
226 tableStore = new OvsdbTableStore();
227 }
228 OvsdbRowStore rowStore = tableStore.getRows(tableName);
229 if (rowStore == null) {
230 rowStore = new OvsdbRowStore();
231 }
232 rowStore.insertRow(uuid, row);
233 tableStore.createOrUpdateTable(tableName, rowStore);
234 ovsdbStore.createOrUpdateOvsdbStore(dbName, tableStore);
235 }
236
237 @Override
238 public String getPortUuid(String portName, String bridgeUuid) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700239 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700240
Hyunsun Moon1251e192016-06-07 16:57:05 -0700241 Row bridgeRow = getRow(DATABASENAME, BRIDGE, bridgeUuid);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700242 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow,
243 OvsdbTable.BRIDGE);
244 if (bridge != null) {
245 OvsdbSet setPorts = (OvsdbSet) bridge.getPortsColumn().data();
246 @SuppressWarnings("unchecked")
Jonathan Hart51539b82015-10-29 09:53:04 -0700247 Set<Uuid> ports = setPorts.set();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700248 if (ports == null || ports.size() == 0) {
249 log.warn("The port uuid is null");
250 return null;
251 }
252
Jonathan Hart51539b82015-10-29 09:53:04 -0700253 for (Uuid uuid : ports) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700254 Row portRow = getRow(DATABASENAME, PORT, uuid.value());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700255 Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
256 OvsdbTable.PORT);
257 if (port != null && portName.equalsIgnoreCase(port.getName())) {
258 return uuid.value();
259 }
260 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700261 }
262 return null;
263 }
264
265 @Override
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700266 public String getBridgeUuid(String bridgeName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700267 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700268 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700269 if (rowStore == null) {
270 log.debug("The bridge uuid is null");
271 return null;
272 }
273
274 ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
275 if (bridgeTableRows == null) {
276 log.debug("The bridge uuid is null");
277 return null;
278 }
279
280 for (String uuid : bridgeTableRows.keySet()) {
281 Bridge bridge = (Bridge) TableGenerator
Hyunsun Moon1251e192016-06-07 16:57:05 -0700282 .getTable(dbSchema, bridgeTableRows.get(uuid), OvsdbTable.BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700283 if (bridge.getName().equals(bridgeName)) {
284 return uuid;
285 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700286 }
287 return null;
288 }
289
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700290 private String getOvsUuid(String dbName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700291 OvsdbRowStore rowStore = getRowStore(DATABASENAME, DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700292 if (rowStore == null) {
293 log.debug("The bridge uuid is null");
294 return null;
295 }
296 ConcurrentMap<String, Row> ovsTableRows = rowStore.getRowStore();
297 if (ovsTableRows != null) {
298 for (String uuid : ovsTableRows.keySet()) {
299 Row row = ovsTableRows.get(uuid);
300 String tableName = row.tableName();
301 if (tableName.equals(dbName)) {
302 return uuid;
303 }
304 }
305 }
306 return null;
307 }
308
309 @Override
310 public void createPort(String bridgeName, String portName) {
311 String bridgeUuid = getBridgeUuid(bridgeName);
312 if (bridgeUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700313 log.error("Can't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700314 return;
315 }
316
Hyunsun Moon1251e192016-06-07 16:57:05 -0700317 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700318 String portUuid = getPortUuid(portName, bridgeUuid);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700319 Port port = (Port) TableGenerator.createTable(dbSchema, OvsdbTable.PORT);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700320 port.setName(portName);
321 if (portUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700322 insertConfig(PORT, UUID, BRIDGE, PORTS, bridgeUuid, port.getRow());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700323 } else {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700324 updateConfig(PORT, UUID, portUuid, port.getRow());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700325 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700326 }
327
328 @Override
329 public void dropPort(String bridgeName, String portName) {
330 String bridgeUuid = getBridgeUuid(bridgeName);
331 if (bridgeUuid == null) {
332 log.error("Could not find Bridge {} in {}", bridgeName, nodeId);
333 return;
334 }
335
336 String portUuid = getPortUuid(portName, bridgeUuid);
337 if (portUuid != null) {
338 log.info("Port {} delete", portName);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700339 deleteConfig(PORT, UUID, portUuid, BRIDGE, PORTS);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700340 }
341 }
342
Hyunsun Moon1251e192016-06-07 16:57:05 -0700343 @Deprecated
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700344 @Override
345 public void createBridge(String bridgeName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700346 OvsdbBridge ovsdbBridge = OvsdbBridge.builder()
347 .name(bridgeName)
348 .build();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700349
Hyunsun Moon1251e192016-06-07 16:57:05 -0700350 createBridge(ovsdbBridge);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700351 }
352
Hyunsun Moon1251e192016-06-07 16:57:05 -0700353 @Deprecated
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700354 @Override
lishuai6c56f5e2015-11-17 16:38:19 +0800355 public void createBridge(String bridgeName, String dpid, String exPortName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700356 OvsdbBridge ovsdbBridge = OvsdbBridge.builder()
357 .name(bridgeName)
358 .failMode(BridgeDescription.FailMode.SECURE)
359 .datapathId(dpid)
360 .disableInBand()
361 .controllers(Lists.newArrayList(localController()))
362 .build();
lishuai6c56f5e2015-11-17 16:38:19 +0800363
Hyunsun Moon1251e192016-06-07 16:57:05 -0700364 createBridge(ovsdbBridge);
lishuai6c56f5e2015-11-17 16:38:19 +0800365
lishuai6c56f5e2015-11-17 16:38:19 +0800366 if (exPortName != null) {
367 createPort(bridgeName, exPortName);
368 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700369 }
lishuai6c56f5e2015-11-17 16:38:19 +0800370
Hyunsun Moon1251e192016-06-07 16:57:05 -0700371 @Deprecated
372 @Override
373 public boolean createBridge(String bridgeName, String dpid, List<ControllerInfo> controllers) {
374 OvsdbBridge ovsdbBridge = OvsdbBridge.builder()
375 .name(bridgeName)
376 .failMode(BridgeDescription.FailMode.SECURE)
377 .datapathId(dpid)
378 .disableInBand()
379 .controllers(controllers)
380 .build();
381
382 return createBridge(ovsdbBridge);
lishuai6c56f5e2015-11-17 16:38:19 +0800383 }
384
385 @Override
Hyunsun Moon1251e192016-06-07 16:57:05 -0700386 public boolean createBridge(OvsdbBridge ovsdbBridge) {
387 DatabaseSchema dbSchema = schema.get(DATABASENAME);
388 String ovsUuid = getOvsUuid(DATABASENAME);
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700389
390 if (dbSchema == null || ovsUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700391 log.error("Can't find database Open_vSwitch");
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700392 return false;
393 }
394
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700395 Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema, OvsdbTable.BRIDGE);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700396 bridge.setOtherConfig(ovsdbBridge.otherConfigs());
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700397
Hyunsun Moon1251e192016-06-07 16:57:05 -0700398 if (ovsdbBridge.failMode().isPresent()) {
399 String failMode = ovsdbBridge.failMode().get().name().toLowerCase();
400 bridge.setFailMode(Sets.newHashSet(failMode));
Bob zhoue9795fd2016-05-12 20:18:45 +0800401 }
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700402
Hyunsun Moon1251e192016-06-07 16:57:05 -0700403 String bridgeUuid = getBridgeUuid(ovsdbBridge.name());
Hyunsun Moon98025542016-03-08 04:36:02 -0800404 if (bridgeUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700405 bridge.setName(ovsdbBridge.name());
406 bridgeUuid = insertConfig(
407 BRIDGE, UUID, DATABASENAME, BRIDGES,
408 ovsUuid, bridge.getRow());
Hyunsun Moon98025542016-03-08 04:36:02 -0800409 } else {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700410 // update the bridge if it's already existing
411 updateConfig(BRIDGE, UUID, bridgeUuid, bridge.getRow());
Hyunsun Moon98025542016-03-08 04:36:02 -0800412 }
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700413
Hyunsun Moon1251e192016-06-07 16:57:05 -0700414 if (bridgeUuid == null) {
415 log.warn("Failed to create bridge {} on {}", ovsdbBridge.name(), nodeId);
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700416 return false;
417 }
418
Hyunsun Moon1251e192016-06-07 16:57:05 -0700419 createPort(ovsdbBridge.name(), ovsdbBridge.name());
420 setControllersWithUuid(Uuid.uuid(bridgeUuid), ovsdbBridge.controllers());
421
422 log.info("Created bridge {}", ovsdbBridge.name());
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700423 return true;
424 }
425
Hyunsun Moon1251e192016-06-07 16:57:05 -0700426 @Override
427 public ControllerInfo localController() {
428 IpAddress ipAddress = IpAddress.valueOf(((InetSocketAddress)
429 channel.localAddress()).getAddress());
430 return new ControllerInfo(ipAddress, OFPORT, "tcp");
andreaed976a42015-10-05 14:38:25 -0700431 }
432
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700433 private void setControllersWithUuid(Uuid bridgeUuid, List<ControllerInfo> controllers) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700434 DatabaseSchema dbSchema = schema.get(DATABASENAME);
andreaed976a42015-10-05 14:38:25 -0700435 if (dbSchema == null) {
436 log.debug("There is no schema");
437 return;
438 }
439 List<Controller> oldControllers = getControllers(bridgeUuid);
440 if (oldControllers == null) {
441 log.warn("There are no controllers");
442 return;
443 }
444
Jonathan Hart51539b82015-10-29 09:53:04 -0700445 Set<Uuid> newControllerUuids = new HashSet<>();
andreaed976a42015-10-05 14:38:25 -0700446
447 Set<ControllerInfo> newControllers = new HashSet<>(controllers);
448 List<Controller> removeControllers = new ArrayList<>();
449 oldControllers.forEach(controller -> {
450 ControllerInfo controllerInfo = new ControllerInfo((String) controller.getTargetColumn().data());
451 if (newControllers.contains(controllerInfo)) {
452 newControllers.remove(controllerInfo);
453 newControllerUuids.add(controller.getRow().uuid());
454 } else {
455 removeControllers.add(controller);
456 }
457 });
Hyunsun Moon1251e192016-06-07 16:57:05 -0700458 OvsdbRowStore controllerRowStore = getRowStore(DATABASENAME, CONTROLLER);
andreaed976a42015-10-05 14:38:25 -0700459 if (controllerRowStore == null) {
460 log.debug("There is no controller table");
461 return;
462 }
463
Hyunsun Moon1251e192016-06-07 16:57:05 -0700464 removeControllers.forEach(c -> deleteConfig(CONTROLLER, UUID, c.getRow().uuid().value(),
465 BRIDGE, "controller"));
andreaed976a42015-10-05 14:38:25 -0700466 newControllers.stream().map(c -> {
467 Controller controller = (Controller) TableGenerator
468 .createTable(dbSchema, OvsdbTable.CONTROLLER);
469 controller.setTarget(c.target());
470 return controller;
471 }).forEach(c -> {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700472 String uuid = insertConfig(CONTROLLER, UUID, BRIDGE, "controller", bridgeUuid.value(),
andreaed976a42015-10-05 14:38:25 -0700473 c.getRow());
Jonathan Hart51539b82015-10-29 09:53:04 -0700474 newControllerUuids.add(Uuid.uuid(uuid));
andreaed976a42015-10-05 14:38:25 -0700475
476 });
477
Hyunsun Moon1251e192016-06-07 16:57:05 -0700478 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
andreaed976a42015-10-05 14:38:25 -0700479 if (rowStore == null) {
480 log.debug("There is no bridge table");
481 return;
482 }
483
484 Row bridgeRow = rowStore.getRow(bridgeUuid.value());
485 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
486 bridge.setController(OvsdbSet.ovsdbSet(newControllerUuids));
Hyunsun Moon1251e192016-06-07 16:57:05 -0700487 updateConfig(BRIDGE, UUID, bridgeUuid.value(), bridge.getRow());
andreaed976a42015-10-05 14:38:25 -0700488 }
489
andreaed976a42015-10-05 14:38:25 -0700490 @Override
491 public void setControllersWithDeviceId(DeviceId deviceId, List<ControllerInfo> controllers) {
Jonathan Hart51539b82015-10-29 09:53:04 -0700492 setControllersWithUuid(getBridgeUuid(deviceId), controllers);
andreaed976a42015-10-05 14:38:25 -0700493 }
494
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700495 @Override
496 public void dropBridge(String bridgeName) {
Jonathan Hart51539b82015-10-29 09:53:04 -0700497 String bridgeUuid = getBridgeUuid(bridgeName);
498 if (bridgeUuid == null) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700499 log.warn("Could not find bridge in node", nodeId.getIpAddress());
500 return;
501 }
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700502 deleteConfig(BRIDGE, UUID, bridgeUuid, DATABASENAME, BRIDGES);
503 }
504
505 @Deprecated
506 @Override
507 public boolean createTunnel(String bridgeName, String ifaceName, String tunnelType,
508 Map<String, String> options) {
509 OvsdbInterface ovsdbIface = OvsdbInterface.builder()
510 .name(ifaceName)
511 .type(Type.valueOf(tunnelType))
512 .options(options)
513 .build();
514
515 return createInterface(bridgeName, ovsdbIface);
516 }
517
518 @Deprecated
519 @Override
520 public void dropTunnel(IpAddress srcIp, IpAddress dstIp) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700521 }
522
523 @Override
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700524 public boolean createInterface(String bridgeName, OvsdbInterface ovsdbIface) {
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700525 String bridgeUuid = getBridgeUuid(bridgeName);
526 if (bridgeUuid == null) {
527 log.warn("Couldn't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
528 return false;
529 }
530
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700531 if (getPortUuid(ovsdbIface.name(), bridgeUuid) != null) {
532 log.warn("Interface {} already exists", ovsdbIface.name());
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700533 // remove existing one and re-create?
534 return false;
535 }
536
537 ArrayList<Operation> operations = Lists.newArrayList();
Hyunsun Moon1251e192016-06-07 16:57:05 -0700538 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700539
Hyunsun Moon89478662016-06-09 17:52:34 -0700540 // insert a new port with the interface name
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700541 Port port = (Port) TableGenerator.createTable(dbSchema, OvsdbTable.PORT);
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700542 port.setName(ovsdbIface.name());
543 Insert portInsert = new Insert(dbSchema.getTableSchema(PORT), PORT, port.getRow());
544 portInsert.getRow().put(INTERFACES, Uuid.uuid(INTERFACE));
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700545 operations.add(portInsert);
546
Hyunsun Moon89478662016-06-09 17:52:34 -0700547 // update the bridge table with the new port
Hyunsun Moon1251e192016-06-07 16:57:05 -0700548 Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(bridgeUuid));
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700549 Mutation mutation = MutationUtil.insert(PORTS, Uuid.uuid(PORT));
550 List<Condition> conditions = Lists.newArrayList(condition);
551 List<Mutation> mutations = Lists.newArrayList(mutation);
552 operations.add(new Mutate(dbSchema.getTableSchema(BRIDGE), conditions, mutations));
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700553
Hyunsun Moon89478662016-06-09 17:52:34 -0700554 // insert an interface
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700555 Interface intf = (Interface) TableGenerator.createTable(dbSchema, OvsdbTable.INTERFACE);
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700556 intf.setName(ovsdbIface.name());
557 intf.setType(ovsdbIface.typeToString());
558 intf.setOptions(ovsdbIface.options());
559 Insert intfInsert = new Insert(dbSchema.getTableSchema(INTERFACE), INTERFACE, intf.getRow());
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700560 operations.add(intfInsert);
561
Hyunsun Moon1251e192016-06-07 16:57:05 -0700562 transactConfig(DATABASENAME, operations);
Hyunsun Moon89478662016-06-09 17:52:34 -0700563 log.info("Created interface {}", ovsdbIface);
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700564 return true;
565 }
566
567 @Override
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700568 public boolean dropInterface(String ifaceName) {
569 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
570 if (rowStore == null) {
571 log.warn("Failed to get BRIDGE table");
572 return false;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700573 }
574
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700575 ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
576 if (bridgeTableRows == null) {
577 log.warn("Failed to get BRIDGE table rows");
578 return false;
579 }
580
581 // interface name is unique
582 Optional<String> bridgeId = bridgeTableRows.keySet().stream()
583 .filter(uuid -> getPortUuid(ifaceName, uuid) != null)
584 .findFirst();
585
586 if (bridgeId.isPresent()) {
587 String portId = getPortUuid(ifaceName, bridgeId.get());
588 deleteConfig(PORT, UUID, portId, BRIDGE, PORTS);
589 return true;
590 } else {
591 log.warn("Unable to find the interface with name {}", ifaceName);
592 return false;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700593 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700594 }
595
596 /**
597 * Delete transact config.
598 *
andreaed976a42015-10-05 14:38:25 -0700599 * @param childTableName child table name
600 * @param childColumnName child column name
601 * @param childUuid child row uuid
602 * @param parentTableName parent table name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700603 * @param parentColumnName parent column
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700604 */
605 private void deleteConfig(String childTableName, String childColumnName,
andreaed976a42015-10-05 14:38:25 -0700606 String childUuid, String parentTableName,
607 String parentColumnName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700608 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700609 TableSchema childTableSchema = dbSchema.getTableSchema(childTableName);
610
611 ArrayList<Operation> operations = Lists.newArrayList();
612 if (parentTableName != null && parentColumnName != null) {
613 TableSchema parentTableSchema = dbSchema
614 .getTableSchema(parentTableName);
615 ColumnSchema parentColumnSchema = parentTableSchema
616 .getColumnSchema(parentColumnName);
617 List<Mutation> mutations = Lists.newArrayList();
618 Mutation mutation = MutationUtil.delete(parentColumnSchema.name(),
Jonathan Hart51539b82015-10-29 09:53:04 -0700619 Uuid.uuid(childUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700620 mutations.add(mutation);
621 List<Condition> conditions = Lists.newArrayList();
622 Condition condition = ConditionUtil.includes(parentColumnName,
Jonathan Hart51539b82015-10-29 09:53:04 -0700623 Uuid.uuid(childUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700624 conditions.add(condition);
625 Mutate op = new Mutate(parentTableSchema, conditions, mutations);
626 operations.add(op);
627 }
628
629 List<Condition> conditions = Lists.newArrayList();
Jonathan Hart51539b82015-10-29 09:53:04 -0700630 Condition condition = ConditionUtil.isEqual(childColumnName, Uuid.uuid(childUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700631 conditions.add(condition);
632 Delete del = new Delete(childTableSchema, conditions);
633 operations.add(del);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700634 transactConfig(DATABASENAME, operations);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700635 }
636
637 /**
638 * Update transact config.
639 *
andreaed976a42015-10-05 14:38:25 -0700640 * @param tableName table name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700641 * @param columnName column name
andreaed976a42015-10-05 14:38:25 -0700642 * @param uuid uuid
643 * @param row the config data
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700644 */
645 private void updateConfig(String tableName, String columnName, String uuid,
andreaed976a42015-10-05 14:38:25 -0700646 Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700647 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700648 TableSchema tableSchema = dbSchema.getTableSchema(tableName);
649
650 List<Condition> conditions = Lists.newArrayList();
Jonathan Hart51539b82015-10-29 09:53:04 -0700651 Condition condition = ConditionUtil.isEqual(columnName, Uuid.uuid(uuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700652 conditions.add(condition);
653
654 Update update = new Update(tableSchema, row, conditions);
655
656 ArrayList<Operation> operations = Lists.newArrayList();
657 operations.add(update);
658
Hyunsun Moon1251e192016-06-07 16:57:05 -0700659 transactConfig(DATABASENAME, operations);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700660 }
661
662 /**
663 * Insert transact config.
664 *
andreaed976a42015-10-05 14:38:25 -0700665 * @param childTableName child table name
666 * @param childColumnName child column name
667 * @param parentTableName parent table name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700668 * @param parentColumnName parent column
andreaed976a42015-10-05 14:38:25 -0700669 * @param parentUuid parent uuid
670 * @param row the config data
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700671 * @return uuid, empty if no uuid is find
672 */
673 private String insertConfig(String childTableName, String childColumnName,
andreaed976a42015-10-05 14:38:25 -0700674 String parentTableName, String parentColumnName,
675 String parentUuid, Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700676 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700677 TableSchema tableSchema = dbSchema.getTableSchema(childTableName);
678
Sho SHIMIZUff18f8c2016-03-11 14:43:53 -0800679 Insert insert = new Insert(tableSchema, childTableName, row);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700680
681 ArrayList<Operation> operations = Lists.newArrayList();
682 operations.add(insert);
683
684 if (parentTableName != null && parentColumnName != null) {
685 TableSchema parentTableSchema = dbSchema
686 .getTableSchema(parentTableName);
687 ColumnSchema parentColumnSchema = parentTableSchema
688 .getColumnSchema(parentColumnName);
689
690 List<Mutation> mutations = Lists.newArrayList();
691 Mutation mutation = MutationUtil.insert(parentColumnSchema.name(),
Sho SHIMIZUff18f8c2016-03-11 14:43:53 -0800692 Uuid.uuid(childTableName));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700693 mutations.add(mutation);
694
695 List<Condition> conditions = Lists.newArrayList();
Hyunsun Moon1251e192016-06-07 16:57:05 -0700696 Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(parentUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700697 conditions.add(condition);
698
699 Mutate op = new Mutate(parentTableSchema, conditions, mutations);
700 operations.add(op);
701 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700702 if (childTableName.equalsIgnoreCase(PORT)) {
703 log.debug("Handle port insert");
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700704 Insert intfInsert = handlePortInsertTable(row);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700705
706 if (intfInsert != null) {
707 operations.add(intfInsert);
708 }
709
710 Insert ins = (Insert) operations.get(0);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700711 ins.getRow().put("interfaces", Uuid.uuid(INTERFACE));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700712 }
713
714 List<OperationResult> results;
715 try {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700716 results = transactConfig(DATABASENAME, operations).get();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700717 return results.get(0).getUuid().value();
718 } catch (InterruptedException e) {
719 log.warn("Interrupted while waiting to get result");
720 Thread.currentThread().interrupt();
721 } catch (ExecutionException e) {
722 log.error("Exception thrown while to get result");
723 }
724
725 return null;
726 }
727
728 /**
729 * Handles port insert.
730 *
andreaed976a42015-10-05 14:38:25 -0700731 * @param portRow row of port
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700732 * @return insert, empty if null
733 */
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700734 private Insert handlePortInsertTable(Row portRow) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700735 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700736
Hyunsun Moon1251e192016-06-07 16:57:05 -0700737 TableSchema portTableSchema = dbSchema.getTableSchema(PORT);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700738 ColumnSchema portColumnSchema = portTableSchema.getColumnSchema("name");
739
740 String portName = (String) portRow.getColumn(portColumnSchema.name()).data();
Hyunsun Moon1251e192016-06-07 16:57:05 -0700741 Interface inf = (Interface) TableGenerator.createTable(dbSchema, OvsdbTable.INTERFACE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700742 inf.setName(portName);
743
Hyunsun Moon1251e192016-06-07 16:57:05 -0700744 TableSchema intfTableSchema = dbSchema.getTableSchema(INTERFACE);
745 return new Insert(intfTableSchema, INTERFACE, inf.getRow());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700746 }
747
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700748 @Override
749 public ListenableFuture<DatabaseSchema> getOvsdbSchema(String dbName) {
750 if (dbName == null) {
751 return null;
752 }
753 DatabaseSchema databaseSchema = schema.get(dbName);
754 if (databaseSchema == null) {
755 List<String> dbNames = new ArrayList<String>();
756 dbNames.add(dbName);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700757 Function<JsonNode, DatabaseSchema> rowFunction = input -> {
758 log.debug("Get ovsdb database schema {}", dbName);
759 DatabaseSchema dbSchema = FromJsonUtil.jsonNodeToDbSchema(dbName, input);
760 if (dbSchema == null) {
761 log.debug("Get ovsdb database schema error");
762 return null;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700763 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700764 schema.put(dbName, dbSchema);
765 return dbSchema;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700766 };
767
768 ListenableFuture<JsonNode> input = getSchema(dbNames);
769 if (input != null) {
770 return Futures.transform(input, rowFunction);
771 }
772 return null;
773 } else {
774 return Futures.immediateFuture(databaseSchema);
775 }
776 }
777
778 @Override
779 public ListenableFuture<TableUpdates> monitorTables(String dbName, String id) {
780 if (dbName == null) {
781 return null;
782 }
783 DatabaseSchema dbSchema = schema.get(dbName);
784 if (dbSchema != null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700785 Function<JsonNode, TableUpdates> rowFunction = input -> {
786 log.debug("Get table updates");
787 TableUpdates updates = FromJsonUtil.jsonNodeToTableUpdates(input, dbSchema);
788 if (updates == null) {
789 log.debug("Get table updates error");
790 return null;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700791 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700792 return updates;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700793 };
794 return Futures.transform(monitor(dbSchema, id), rowFunction);
795 }
796 return null;
797 }
798
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700799 private ListenableFuture<List<OperationResult>> transactConfig(String dbName,
800 List<Operation> operations) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700801 if (dbName == null) {
802 return null;
803 }
804 DatabaseSchema dbSchema = schema.get(dbName);
805 if (dbSchema != null) {
andreaed976a42015-10-05 14:38:25 -0700806 Function<List<JsonNode>, List<OperationResult>> rowFunction = (input -> {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700807 log.debug("Get ovsdb operation result");
808 List<OperationResult> result = FromJsonUtil.jsonNodeToOperationResult(input, operations);
andreaed976a42015-10-05 14:38:25 -0700809 if (result == null) {
810 log.debug("The operation result is null");
811 return null;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700812 }
andreaed976a42015-10-05 14:38:25 -0700813 return result;
814 });
Hyunsun Moon1251e192016-06-07 16:57:05 -0700815 return Futures.transform(transact(dbSchema, operations), rowFunction);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700816 }
817 return null;
818 }
819
820 @Override
821 public ListenableFuture<JsonNode> getSchema(List<String> dbnames) {
822 String id = java.util.UUID.randomUUID().toString();
823 String getSchemaString = JsonRpcWriterUtil.getSchemaStr(id, dbnames);
824
825 SettableFuture<JsonNode> sf = SettableFuture.create();
826 requestResult.put(id, sf);
827 requestMethod.put(id, "getSchema");
828
829 channel.writeAndFlush(getSchemaString);
830 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700831 }
832
833 @Override
834 public ListenableFuture<List<String>> echo() {
835 String id = java.util.UUID.randomUUID().toString();
836 String echoString = JsonRpcWriterUtil.echoStr(id);
837
838 SettableFuture<List<String>> sf = SettableFuture.create();
839 requestResult.put(id, sf);
840 requestMethod.put(id, "echo");
841
842 channel.writeAndFlush(echoString);
843 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700844 }
845
846 @Override
847 public ListenableFuture<JsonNode> monitor(DatabaseSchema dbSchema,
848 String monitorId) {
849 String id = java.util.UUID.randomUUID().toString();
850 String monitorString = JsonRpcWriterUtil.monitorStr(id, monitorId,
851 dbSchema);
852
853 SettableFuture<JsonNode> sf = SettableFuture.create();
854 requestResult.put(id, sf);
855 requestMethod.put(id, "monitor");
856
857 channel.writeAndFlush(monitorString);
858 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700859 }
860
861 @Override
862 public ListenableFuture<List<String>> listDbs() {
863 String id = java.util.UUID.randomUUID().toString();
864 String listDbsString = JsonRpcWriterUtil.listDbsStr(id);
865
866 SettableFuture<List<String>> sf = SettableFuture.create();
867 requestResult.put(id, sf);
868 requestMethod.put(id, "listDbs");
869
870 channel.writeAndFlush(listDbsString);
871 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700872 }
873
874 @Override
875 public ListenableFuture<List<JsonNode>> transact(DatabaseSchema dbSchema,
876 List<Operation> operations) {
877 String id = java.util.UUID.randomUUID().toString();
878 String transactString = JsonRpcWriterUtil.transactStr(id, dbSchema,
879 operations);
880
881 SettableFuture<List<JsonNode>> sf = SettableFuture.create();
882 requestResult.put(id, sf);
883 requestMethod.put(id, "transact");
884
885 channel.writeAndFlush(transactString);
886 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700887 }
888
andreaed976a42015-10-05 14:38:25 -0700889 @SuppressWarnings({"rawtypes", "unchecked"})
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700890 @Override
891 public void processResult(JsonNode response) {
892 log.debug("Handle result");
893 String requestId = response.get("id").asText();
894 SettableFuture sf = requestResult.get(requestId);
895 if (sf == null) {
896 log.debug("No such future to process");
897 return;
898 }
899 String methodName = requestMethod.get(requestId);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700900 sf.set(FromJsonUtil.jsonResultParser(response, methodName));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700901 }
902
903 @Override
904 public void processRequest(JsonNode requestJson) {
905 log.debug("Handle request");
906 if (requestJson.get("method").asText().equalsIgnoreCase("echo")) {
907 log.debug("handle echo request");
908
909 String replyString = FromJsonUtil.getEchoRequestStr(requestJson);
910 channel.writeAndFlush(replyString);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700911 } else {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700912 FromJsonUtil.jsonCallbackRequestParser(requestJson, monitorCallBack);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700913 }
914 }
915
916 @Override
917 public void setCallback(Callback monitorCallback) {
918 this.monitorCallBack = monitorCallback;
919 }
920
921 @Override
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700922 public Set<OvsdbBridge> getBridges() {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700923 Set<OvsdbBridge> ovsdbBridges = new HashSet<>();
924 OvsdbTableStore tableStore = getTableStore(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700925 if (tableStore == null) {
MaoJianweidac220d2016-07-04 22:37:52 +0800926 return ovsdbBridges;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700927 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700928 OvsdbRowStore rowStore = tableStore.getRows(BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700929 if (rowStore == null) {
MaoJianweidac220d2016-07-04 22:37:52 +0800930 return ovsdbBridges;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700931 }
932 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
933 for (String uuid : rows.keySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700934 Row row = getRow(DATABASENAME, BRIDGE, uuid);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700935 OvsdbBridge ovsdbBridge = getOvsdbBridge(row);
936 if (ovsdbBridge != null) {
937 ovsdbBridges.add(ovsdbBridge);
938 }
939 }
940 return ovsdbBridges;
941 }
942
943 @Override
andreaed976a42015-10-05 14:38:25 -0700944 public Set<ControllerInfo> getControllers(DeviceId openflowDeviceId) {
Jonathan Hart51539b82015-10-29 09:53:04 -0700945 Uuid bridgeUuid = getBridgeUuid(openflowDeviceId);
andreaed976a42015-10-05 14:38:25 -0700946 if (bridgeUuid == null) {
947 log.warn("bad bridge Uuid");
948 return null;
949 }
950 List<Controller> controllers = getControllers(bridgeUuid);
951 if (controllers == null) {
952 log.warn("bad list of controllers");
953 return null;
954 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700955 return controllers.stream().map(controller -> new ControllerInfo(
956 (String) controller.getTargetColumn()
957 .data())).collect(Collectors.toSet());
andreaed976a42015-10-05 14:38:25 -0700958 }
959
Jonathan Hart51539b82015-10-29 09:53:04 -0700960 private List<Controller> getControllers(Uuid bridgeUuid) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700961 DatabaseSchema dbSchema = schema.get(DATABASENAME);
andreaed976a42015-10-05 14:38:25 -0700962 if (dbSchema == null) {
963 return null;
964 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700965 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
andreaed976a42015-10-05 14:38:25 -0700966 if (rowStore == null) {
967 log.debug("There is no bridge table");
968 return null;
969 }
970
971 Row bridgeRow = rowStore.getRow(bridgeUuid.value());
972 Bridge bridge = (Bridge) TableGenerator.
973 getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
974
975 //FIXME remove log
976 log.warn("type of controller column", bridge.getControllerColumn()
977 .data().getClass());
Jonathan Hart51539b82015-10-29 09:53:04 -0700978 Set<Uuid> controllerUuids = (Set<Uuid>) ((OvsdbSet) bridge
andreaed976a42015-10-05 14:38:25 -0700979 .getControllerColumn().data()).set();
andreaed976a42015-10-05 14:38:25 -0700980
Hyunsun Moon1251e192016-06-07 16:57:05 -0700981 OvsdbRowStore controllerRowStore = getRowStore(DATABASENAME, CONTROLLER);
andreaed976a42015-10-05 14:38:25 -0700982 if (controllerRowStore == null) {
983 log.debug("There is no controller table");
984 return null;
985 }
986
987 List<Controller> ovsdbControllers = new ArrayList<>();
988 ConcurrentMap<String, Row> controllerTableRows = controllerRowStore.getRowStore();
989 controllerTableRows.forEach((key, row) -> {
Jonathan Hart51539b82015-10-29 09:53:04 -0700990 if (!controllerUuids.contains(Uuid.uuid(key))) {
andreaed976a42015-10-05 14:38:25 -0700991 return;
992 }
993 Controller controller = (Controller) TableGenerator
994 .getTable(dbSchema, row, OvsdbTable.CONTROLLER);
995 ovsdbControllers.add(controller);
996 });
997 return ovsdbControllers;
998 }
999
1000
Jonathan Hart51539b82015-10-29 09:53:04 -07001001 private Uuid getBridgeUuid(DeviceId openflowDeviceId) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001002 DatabaseSchema dbSchema = schema.get(DATABASENAME);
andreaed976a42015-10-05 14:38:25 -07001003 if (dbSchema == null) {
1004 return null;
1005 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001006 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
andreaed976a42015-10-05 14:38:25 -07001007 if (rowStore == null) {
1008 log.debug("There is no bridge table");
1009 return null;
1010 }
1011
1012 ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
Jonathan Hart51539b82015-10-29 09:53:04 -07001013 final AtomicReference<Uuid> uuid = new AtomicReference<>();
andreaed976a42015-10-05 14:38:25 -07001014 for (Map.Entry<String, Row> entry : bridgeTableRows.entrySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001015 Bridge bridge = (Bridge) TableGenerator.getTable(
1016 dbSchema,
1017 entry.getValue(),
1018 OvsdbTable.BRIDGE);
1019
1020 if (matchesDpid(bridge, openflowDeviceId)) {
Jonathan Hart51539b82015-10-29 09:53:04 -07001021 uuid.set(Uuid.uuid(entry.getKey()));
andreaed976a42015-10-05 14:38:25 -07001022 break;
1023 }
1024 }
1025 if (uuid.get() == null) {
1026 log.debug("There is no bridge for {}", openflowDeviceId);
1027 }
1028 return uuid.get();
andreaed976a42015-10-05 14:38:25 -07001029 }
1030
1031 private static boolean matchesDpid(Bridge b, DeviceId deviceId) {
1032 String ofDpid = deviceId.toString().replace("of:", "");
1033 Set ofDeviceIds = ((OvsdbSet) b.getDatapathIdColumn().data()).set();
1034 //TODO Set<String>
1035 return ofDeviceIds.contains(ofDpid);
1036 }
1037
1038 @Override
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001039 public Set<OvsdbPort> getPorts() {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001040 Set<OvsdbPort> ovsdbPorts = new HashSet<>();
1041 OvsdbTableStore tableStore = getTableStore(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001042 if (tableStore == null) {
1043 return null;
1044 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001045 OvsdbRowStore rowStore = tableStore.getRows(INTERFACE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001046 if (rowStore == null) {
1047 return null;
1048 }
1049 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1050 for (String uuid : rows.keySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001051 Row row = getRow(DATABASENAME, INTERFACE, uuid);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001052 OvsdbPort ovsdbPort = getOvsdbPort(row);
1053 if (ovsdbPort != null) {
1054 ovsdbPorts.add(ovsdbPort);
1055 }
1056 }
1057 return ovsdbPorts;
1058 }
1059
1060 @Override
1061 public DatabaseSchema getDatabaseSchema(String dbName) {
1062 return schema.get(dbName);
1063 }
1064
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001065 private OvsdbPort getOvsdbPort(Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001066 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001067 Interface intf = (Interface) TableGenerator
1068 .getTable(dbSchema, row, OvsdbTable.INTERFACE);
1069 if (intf == null) {
1070 return null;
1071 }
1072 long ofPort = getOfPort(intf);
1073 String portName = intf.getName();
1074 if ((ofPort < 0) || (portName == null)) {
1075 return null;
1076 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001077 return new OvsdbPort(new OvsdbPortNumber(ofPort), new OvsdbPortName(portName));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001078 }
1079
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001080 private OvsdbBridge getOvsdbBridge(Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001081 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
1082 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, row, OvsdbTable.BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001083 if (bridge == null) {
1084 return null;
1085 }
1086
1087 OvsdbSet datapathIdSet = (OvsdbSet) bridge.getDatapathIdColumn().data();
1088 @SuppressWarnings("unchecked")
1089 Set<String> datapathIds = datapathIdSet.set();
1090 if (datapathIds == null || datapathIds.size() == 0) {
1091 return null;
1092 }
1093 String datapathId = (String) datapathIds.toArray()[0];
1094 String bridgeName = bridge.getName();
1095 if ((datapathId == null) || (bridgeName == null)) {
1096 return null;
1097 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001098 return OvsdbBridge.builder().name(bridgeName).datapathId(datapathId).build();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001099 }
1100
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001101 private long getOfPort(Interface intf) {
1102 OvsdbSet ofPortSet = (OvsdbSet) intf.getOpenFlowPortColumn().data();
1103 @SuppressWarnings("unchecked")
1104 Set<Integer> ofPorts = ofPortSet.set();
Hyunsun Moon1251e192016-06-07 16:57:05 -07001105 if (ofPorts == null || ofPorts.size() <= 0) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001106 log.debug("The ofport is null in {}", intf.getName());
1107 return -1;
1108 }
1109 // return (long) ofPorts.toArray()[0];
1110 Iterator<Integer> it = ofPorts.iterator();
1111 return Long.parseLong(it.next().toString());
1112 }
CNluciusa66c3972015-09-06 20:31:29 +08001113
1114 @Override
1115 public Set<OvsdbPort> getLocalPorts(Iterable<String> ifaceids) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001116 Set<OvsdbPort> ovsdbPorts = new HashSet<>();
1117 OvsdbTableStore tableStore = getTableStore(DATABASENAME);
CNluciusa66c3972015-09-06 20:31:29 +08001118 if (tableStore == null) {
1119 return null;
1120 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001121 OvsdbRowStore rowStore = tableStore.getRows(INTERFACE);
CNluciusa66c3972015-09-06 20:31:29 +08001122 if (rowStore == null) {
1123 return null;
1124 }
1125 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1126 for (String uuid : rows.keySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001127 Row row = getRow(DATABASENAME, INTERFACE, uuid);
1128 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
CNluciusa66c3972015-09-06 20:31:29 +08001129 Interface intf = (Interface) TableGenerator
1130 .getTable(dbSchema, row, OvsdbTable.INTERFACE);
1131 if (intf == null || getIfaceid(intf) == null) {
1132 continue;
1133 }
1134 String portName = intf.getName();
Hyunsun Moon1251e192016-06-07 16:57:05 -07001135 if (portName == null) {
1136 continue;
1137 }
CNluciusa66c3972015-09-06 20:31:29 +08001138 Set<String> ifaceidSet = Sets.newHashSet(ifaceids);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001139 if (portName.startsWith(TYPEVXLAN) || !ifaceidSet.contains(getIfaceid(intf))) {
CNluciusa66c3972015-09-06 20:31:29 +08001140 continue;
1141 }
1142 long ofPort = getOfPort(intf);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001143 if (ofPort < 0) {
CNluciusa66c3972015-09-06 20:31:29 +08001144 continue;
1145 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001146 ovsdbPorts.add(new OvsdbPort(new OvsdbPortNumber(ofPort),
1147 new OvsdbPortName(portName)));
CNluciusa66c3972015-09-06 20:31:29 +08001148 }
1149 return ovsdbPorts;
1150 }
1151
1152 private String getIfaceid(Interface intf) {
1153 OvsdbMap ovsdbMap = (OvsdbMap) intf.getExternalIdsColumn().data();
1154 @SuppressWarnings("unchecked")
1155 Map<String, String> externalIds = ovsdbMap.map();
1156 if (externalIds.isEmpty()) {
1157 log.warn("The external_ids is null");
1158 return null;
1159 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001160 String ifaceid = externalIds.get(EXTERNAL_ID_INTERFACE_ID);
CNluciusa66c3972015-09-06 20:31:29 +08001161 if (ifaceid == null) {
1162 log.warn("The ifaceid is null");
1163 return null;
1164 }
1165 return ifaceid;
1166 }
Hyunsun Moon5fb20a52015-09-25 17:02:33 -07001167
1168 @Override
1169 public void disconnect() {
1170 channel.disconnect();
1171 this.agent.removeConnectedNode(nodeId);
1172 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001173}