blob: 5523b814b9a74611f98f51c9a3ad5b271062d497 [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
18import io.netty.channel.Channel;
lishuai6c56f5e2015-11-17 16:38:19 +080019
Ray Milkeyb1250322017-06-05 17:18:17 -070020import java.net.InetSocketAddress;
21import java.util.ArrayList;
22import java.util.HashMap;
23import java.util.HashSet;
24import java.util.Iterator;
25import java.util.List;
26import java.util.Map;
27import java.util.Objects;
28import java.util.Optional;
29import java.util.Set;
30import java.util.concurrent.ConcurrentMap;
31import java.util.concurrent.ExecutionException;
32import java.util.concurrent.TimeUnit;
33import java.util.concurrent.TimeoutException;
34import java.util.concurrent.atomic.AtomicReference;
35import java.util.stream.Collectors;
36
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070037import org.onlab.packet.IpAddress;
andreaed976a42015-10-05 14:38:25 -070038import org.onosproject.net.DeviceId;
Frank Wange11a98d2016-10-26 17:04:03 +080039import org.onosproject.net.PortNumber;
andreaed976a42015-10-05 14:38:25 -070040import org.onosproject.net.behaviour.ControllerInfo;
Pier Ventref5d72362016-07-17 12:02:14 +020041import org.onosproject.net.behaviour.MirroringName;
Ray Milkeyb1250322017-06-05 17:18:17 -070042import org.onosproject.net.behaviour.MirroringStatistics;
Frank Wange11a98d2016-10-26 17:04:03 +080043import org.onosproject.net.behaviour.QosId;
44import org.onosproject.net.behaviour.QueueId;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070045import org.onosproject.ovsdb.controller.OvsdbBridge;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070046import org.onosproject.ovsdb.controller.OvsdbClientService;
Hyunsun Moondd14e8e2016-06-09 16:17:32 -070047import org.onosproject.ovsdb.controller.OvsdbInterface;
Pier Ventref5d72362016-07-17 12:02:14 +020048import org.onosproject.ovsdb.controller.OvsdbMirror;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070049import org.onosproject.ovsdb.controller.OvsdbNodeId;
50import org.onosproject.ovsdb.controller.OvsdbPort;
51import org.onosproject.ovsdb.controller.OvsdbPortName;
52import org.onosproject.ovsdb.controller.OvsdbPortNumber;
Frank Wange11a98d2016-10-26 17:04:03 +080053import org.onosproject.ovsdb.controller.OvsdbQos;
54import org.onosproject.ovsdb.controller.OvsdbQueue;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070055import org.onosproject.ovsdb.controller.OvsdbRowStore;
56import org.onosproject.ovsdb.controller.OvsdbStore;
57import org.onosproject.ovsdb.controller.OvsdbTableStore;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070058import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
59import org.onosproject.ovsdb.rfc.message.OperationResult;
60import org.onosproject.ovsdb.rfc.message.TableUpdates;
Frank Wange11a98d2016-10-26 17:04:03 +080061import org.onosproject.ovsdb.rfc.notation.Column;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070062import org.onosproject.ovsdb.rfc.notation.Condition;
63import org.onosproject.ovsdb.rfc.notation.Mutation;
CNluciusa66c3972015-09-06 20:31:29 +080064import org.onosproject.ovsdb.rfc.notation.OvsdbMap;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070065import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
66import org.onosproject.ovsdb.rfc.notation.Row;
Jonathan Hart51539b82015-10-29 09:53:04 -070067import org.onosproject.ovsdb.rfc.notation.Uuid;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070068import org.onosproject.ovsdb.rfc.operations.Delete;
69import org.onosproject.ovsdb.rfc.operations.Insert;
70import org.onosproject.ovsdb.rfc.operations.Mutate;
71import org.onosproject.ovsdb.rfc.operations.Operation;
72import org.onosproject.ovsdb.rfc.operations.Update;
73import org.onosproject.ovsdb.rfc.schema.ColumnSchema;
74import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
75import org.onosproject.ovsdb.rfc.schema.TableSchema;
76import org.onosproject.ovsdb.rfc.table.Bridge;
77import org.onosproject.ovsdb.rfc.table.Controller;
78import org.onosproject.ovsdb.rfc.table.Interface;
Pier Ventref5d72362016-07-17 12:02:14 +020079import org.onosproject.ovsdb.rfc.table.Mirror;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070080import org.onosproject.ovsdb.rfc.table.OvsdbTable;
81import org.onosproject.ovsdb.rfc.table.Port;
Frank Wange11a98d2016-10-26 17:04:03 +080082import org.onosproject.ovsdb.rfc.table.Qos;
83import org.onosproject.ovsdb.rfc.table.Queue;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070084import org.onosproject.ovsdb.rfc.table.TableGenerator;
85import org.onosproject.ovsdb.rfc.utils.ConditionUtil;
86import org.onosproject.ovsdb.rfc.utils.FromJsonUtil;
87import org.onosproject.ovsdb.rfc.utils.JsonRpcWriterUtil;
88import org.onosproject.ovsdb.rfc.utils.MutationUtil;
89import org.slf4j.Logger;
90import org.slf4j.LoggerFactory;
91
Ray Milkeyb1250322017-06-05 17:18:17 -070092import com.fasterxml.jackson.databind.JsonNode;
93import com.google.common.base.Function;
94import com.google.common.collect.ImmutableList;
95import com.google.common.collect.ImmutableSet;
96import com.google.common.collect.Lists;
97import com.google.common.collect.Maps;
98import com.google.common.collect.Sets;
99import com.google.common.util.concurrent.Futures;
100import com.google.common.util.concurrent.ListenableFuture;
101import com.google.common.util.concurrent.SettableFuture;
Pier Ventref5d72362016-07-17 12:02:14 +0200102
Ray Milkeyb1250322017-06-05 17:18:17 -0700103import static org.onosproject.ovsdb.controller.OvsdbConstant.BRIDGE;
104import static org.onosproject.ovsdb.controller.OvsdbConstant.BRIDGES;
105import static org.onosproject.ovsdb.controller.OvsdbConstant.CONTROLLER;
106import static org.onosproject.ovsdb.controller.OvsdbConstant.DATABASENAME;
107import static org.onosproject.ovsdb.controller.OvsdbConstant.EXTERNAL_ID;
108import static org.onosproject.ovsdb.controller.OvsdbConstant.EXTERNAL_ID_INTERFACE_ID;
109import static org.onosproject.ovsdb.controller.OvsdbConstant.INTERFACE;
110import static org.onosproject.ovsdb.controller.OvsdbConstant.INTERFACES;
111import static org.onosproject.ovsdb.controller.OvsdbConstant.MIRROR;
112import static org.onosproject.ovsdb.controller.OvsdbConstant.MIRRORS;
113import static org.onosproject.ovsdb.controller.OvsdbConstant.OFPORT;
114import static org.onosproject.ovsdb.controller.OvsdbConstant.PORT;
115import static org.onosproject.ovsdb.controller.OvsdbConstant.PORTS;
116import static org.onosproject.ovsdb.controller.OvsdbConstant.PORT_QOS;
117import static org.onosproject.ovsdb.controller.OvsdbConstant.QOS;
118import static org.onosproject.ovsdb.controller.OvsdbConstant.QOS_EXTERNAL_ID_KEY;
119import static org.onosproject.ovsdb.controller.OvsdbConstant.QUEUE;
120import static org.onosproject.ovsdb.controller.OvsdbConstant.QUEUES;
121import static org.onosproject.ovsdb.controller.OvsdbConstant.QUEUE_EXTERNAL_ID_KEY;
122import static org.onosproject.ovsdb.controller.OvsdbConstant.TYPEVXLAN;
123import static org.onosproject.ovsdb.controller.OvsdbConstant.UUID;
Saritha8a0c36a2017-07-04 15:01:35 +0530124import static org.onosproject.ovsdb.controller.OvsdbConstant.BRIDGE_CONTROLLER;
Hyunsun Moon1251e192016-06-07 16:57:05 -0700125
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700126/**
127 * An representation of an ovsdb client.
128 */
Hyunsun Moon1251e192016-06-07 16:57:05 -0700129public class DefaultOvsdbClient implements OvsdbProviderService, OvsdbClientService {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700130
jaegonkim01d7c912017-01-22 22:03:38 +0900131 private static final int TRANSACTCONFIG_TIMEOUT = 3; //sec
132
Hyunsun Moon1251e192016-06-07 16:57:05 -0700133 private final Logger log = LoggerFactory.getLogger(DefaultOvsdbClient.class);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700134
135 private Channel channel;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700136 private OvsdbAgent agent;
137 private boolean connected;
138 private OvsdbNodeId nodeId;
139 private Callback monitorCallBack;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700140 private OvsdbStore ovsdbStore = new OvsdbStore();
141
142 private final Map<String, String> requestMethod = Maps.newHashMap();
Hyunsun Moon1251e192016-06-07 16:57:05 -0700143 private final Map<String, SettableFuture<? extends Object>> requestResult = Maps.newHashMap();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700144 private final Map<String, DatabaseSchema> schema = Maps.newHashMap();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700145
Pier Ventref5d72362016-07-17 12:02:14 +0200146
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700147 /**
148 * Creates an OvsdbClient.
149 *
150 * @param nodeId ovsdb node id
151 */
152 public DefaultOvsdbClient(OvsdbNodeId nodeId) {
153 this.nodeId = nodeId;
154 }
155
156 @Override
157 public OvsdbNodeId nodeId() {
158 return nodeId;
159 }
160
161 @Override
162 public void setAgent(OvsdbAgent agent) {
163 if (this.agent == null) {
164 this.agent = agent;
165 }
166 }
167
168 @Override
169 public void setChannel(Channel channel) {
170 this.channel = channel;
171 }
172
173 @Override
174 public void setConnection(boolean connected) {
175 this.connected = connected;
176 }
177
178 @Override
179 public boolean isConnected() {
180 return this.connected;
181 }
182
183 @Override
184 public void nodeAdded() {
185 this.agent.addConnectedNode(nodeId, this);
186 }
187
188 @Override
189 public void nodeRemoved() {
190 this.agent.removeConnectedNode(nodeId);
191 channel.disconnect();
192 }
193
194 /**
195 * Gets the ovsdb table store.
196 *
197 * @param dbName the ovsdb database name
198 * @return ovsTableStore, empty if table store is find
199 */
200 private OvsdbTableStore getTableStore(String dbName) {
201 if (ovsdbStore == null) {
202 return null;
203 }
204 return ovsdbStore.getOvsdbTableStore(dbName);
205 }
206
207 /**
208 * Gets the ovsdb row store.
209 *
andreaed976a42015-10-05 14:38:25 -0700210 * @param dbName the ovsdb database name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700211 * @param tableName the ovsdb table name
Hyunsun Moon6125c612015-10-15 10:54:44 -0700212 * @return ovsRowStore, empty store if no rows exist in the table
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700213 */
214 private OvsdbRowStore getRowStore(String dbName, String tableName) {
215 OvsdbTableStore tableStore = getTableStore(dbName);
216 if (tableStore == null) {
217 return null;
218 }
Hyunsun Moon6125c612015-10-15 10:54:44 -0700219
220 OvsdbRowStore rowStore = tableStore.getRows(tableName);
221 if (rowStore == null) {
222 rowStore = new OvsdbRowStore();
223 }
224 return rowStore;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700225 }
226
227 /**
228 * Gets the ovsdb row.
229 *
andreaed976a42015-10-05 14:38:25 -0700230 * @param dbName the ovsdb database name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700231 * @param tableName the ovsdb table name
andreaed976a42015-10-05 14:38:25 -0700232 * @param uuid the key of the row
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700233 * @return row, empty if row is find
234 */
235 @Override
236 public Row getRow(String dbName, String tableName, String uuid) {
237 OvsdbTableStore tableStore = getTableStore(dbName);
238 if (tableStore == null) {
239 return null;
240 }
241 OvsdbRowStore rowStore = tableStore.getRows(tableName);
242 if (rowStore == null) {
243 return null;
244 }
245 return rowStore.getRow(uuid);
246 }
247
248 @Override
249 public void removeRow(String dbName, String tableName, String uuid) {
250 OvsdbTableStore tableStore = getTableStore(dbName);
251 if (tableStore == null) {
252 return;
253 }
254 OvsdbRowStore rowStore = tableStore.getRows(tableName);
255 if (rowStore == null) {
256 return;
257 }
258 rowStore.deleteRow(uuid);
259 }
260
261 @Override
262 public void updateOvsdbStore(String dbName, String tableName, String uuid,
263 Row row) {
264 OvsdbTableStore tableStore = ovsdbStore.getOvsdbTableStore(dbName);
265 if (tableStore == null) {
266 tableStore = new OvsdbTableStore();
267 }
268 OvsdbRowStore rowStore = tableStore.getRows(tableName);
269 if (rowStore == null) {
270 rowStore = new OvsdbRowStore();
271 }
272 rowStore.insertRow(uuid, row);
273 tableStore.createOrUpdateTable(tableName, rowStore);
274 ovsdbStore.createOrUpdateOvsdbStore(dbName, tableStore);
275 }
276
Pier Ventref5d72362016-07-17 12:02:14 +0200277 /**
278 * Gets the Mirror uuid.
279 *
280 * @param mirrorName mirror name
281 * @return mirror uuid, empty if no uuid is found
282 */
283 @Override
284 public String getMirrorUuid(String mirrorName) {
285 DatabaseSchema dbSchema = schema.get(DATABASENAME);
286 OvsdbRowStore rowStore = getRowStore(DATABASENAME, MIRROR);
287 if (rowStore == null) {
288 log.warn("The mirror uuid is null");
289 return null;
290 }
291
292 ConcurrentMap<String, Row> mirrorTableRows = rowStore.getRowStore();
293 if (mirrorTableRows == null) {
294 log.warn("The mirror uuid is null");
295 return null;
296 }
297
298 for (String uuid : mirrorTableRows.keySet()) {
299 Mirror mirror = (Mirror) TableGenerator
300 .getTable(dbSchema, mirrorTableRows.get(uuid), OvsdbTable.MIRROR);
301 String name = mirror.getName();
302 if (name.contains(mirrorName)) {
303 return uuid;
304 }
305 }
306 log.warn("Mirroring not found");
307 return null;
308 }
309
310 /**
311 * Gets mirrors of the device.
312 *
313 * @param deviceId target device id
314 * @return set of mirroring; empty if no mirror is found
315 */
316 @Override
317 public Set<MirroringStatistics> getMirroringStatistics(DeviceId deviceId) {
318 Uuid bridgeUuid = getBridgeUuid(deviceId);
319 if (bridgeUuid == null) {
320 log.warn("Couldn't find bridge {} in {}", deviceId, nodeId.getIpAddress());
321 return null;
322 }
323
324 List<MirroringStatistics> mirrorings = getMirrorings(bridgeUuid);
325 if (mirrorings == null) {
326 log.warn("Couldn't find mirrors in {}", nodeId.getIpAddress());
327 return null;
328 }
329 return ImmutableSet.copyOf(mirrorings);
330 }
331
332 /**
333 * Helper method which retrieves mirrorings statistics using bridge uuid.
334 *
335 * @param bridgeUuid the uuid of the bridge
336 * @return the list of the mirrorings statistics.
337 */
338 private List<MirroringStatistics> getMirrorings(Uuid bridgeUuid) {
339 DatabaseSchema dbSchema = schema.get(DATABASENAME);
340 if (dbSchema == null) {
341 log.warn("Unable to retrieve dbSchema {}", DATABASENAME);
342 return null;
343 }
344 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
345 if (rowStore == null) {
346 log.warn("Unable to retrieve rowStore {} of {}", BRIDGE, DATABASENAME);
347 return null;
348 }
349
350 Row bridgeRow = rowStore.getRow(bridgeUuid.value());
351 Bridge bridge = (Bridge) TableGenerator.
352 getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
353
354 Set<Uuid> mirroringsUuids = (Set<Uuid>) ((OvsdbSet) bridge
355 .getMirrorsColumn().data()).set();
356
357 OvsdbRowStore mirrorRowStore = getRowStore(DATABASENAME, MIRROR);
358 if (mirrorRowStore == null) {
359 log.warn("Unable to retrieve rowStore {} of {}", MIRROR, DATABASENAME);
360 return null;
361 }
362
363 List<MirroringStatistics> mirroringStatistics = new ArrayList<>();
364 ConcurrentMap<String, Row> mirrorTableRows = mirrorRowStore.getRowStore();
365 mirrorTableRows.forEach((key, row) -> {
366 if (!mirroringsUuids.contains(Uuid.uuid(key))) {
367 return;
368 }
369 Mirror mirror = (Mirror) TableGenerator
370 .getTable(dbSchema, row, OvsdbTable.MIRROR);
371 mirroringStatistics.add(MirroringStatistics.mirroringStatistics(mirror.getName(),
372 (Map<String, Integer>) ((OvsdbMap) mirror
373 .getStatisticsColumn().data()).map()));
374 });
375 return ImmutableList.copyOf(mirroringStatistics);
376 }
377
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700378 @Override
379 public String getPortUuid(String portName, String bridgeUuid) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700380 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700381
Hyunsun Moon1251e192016-06-07 16:57:05 -0700382 Row bridgeRow = getRow(DATABASENAME, BRIDGE, bridgeUuid);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700383 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow,
384 OvsdbTable.BRIDGE);
385 if (bridge != null) {
386 OvsdbSet setPorts = (OvsdbSet) bridge.getPortsColumn().data();
387 @SuppressWarnings("unchecked")
Jonathan Hart51539b82015-10-29 09:53:04 -0700388 Set<Uuid> ports = setPorts.set();
Jon Hallcbd1b392017-01-18 20:15:44 -0800389 if (ports == null || ports.isEmpty()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700390 log.warn("The port uuid is null");
391 return null;
392 }
393
Jonathan Hart51539b82015-10-29 09:53:04 -0700394 for (Uuid uuid : ports) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700395 Row portRow = getRow(DATABASENAME, PORT, uuid.value());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700396 Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
397 OvsdbTable.PORT);
398 if (port != null && portName.equalsIgnoreCase(port.getName())) {
399 return uuid.value();
400 }
401 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700402 }
403 return null;
404 }
405
406 @Override
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700407 public String getBridgeUuid(String bridgeName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700408 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700409 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700410 if (rowStore == null) {
411 log.debug("The bridge uuid is null");
412 return null;
413 }
414
415 ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
416 if (bridgeTableRows == null) {
417 log.debug("The bridge uuid is null");
418 return null;
419 }
420
421 for (String uuid : bridgeTableRows.keySet()) {
422 Bridge bridge = (Bridge) TableGenerator
Hyunsun Moon1251e192016-06-07 16:57:05 -0700423 .getTable(dbSchema, bridgeTableRows.get(uuid), OvsdbTable.BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700424 if (bridge.getName().equals(bridgeName)) {
425 return uuid;
426 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700427 }
428 return null;
429 }
430
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700431 private String getOvsUuid(String dbName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700432 OvsdbRowStore rowStore = getRowStore(DATABASENAME, DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700433 if (rowStore == null) {
434 log.debug("The bridge uuid is null");
435 return null;
436 }
437 ConcurrentMap<String, Row> ovsTableRows = rowStore.getRowStore();
438 if (ovsTableRows != null) {
439 for (String uuid : ovsTableRows.keySet()) {
440 Row row = ovsTableRows.get(uuid);
441 String tableName = row.tableName();
442 if (tableName.equals(dbName)) {
443 return uuid;
444 }
445 }
446 }
447 return null;
448 }
449
450 @Override
451 public void createPort(String bridgeName, String portName) {
452 String bridgeUuid = getBridgeUuid(bridgeName);
453 if (bridgeUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700454 log.error("Can't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700455 return;
456 }
457
Hyunsun Moon1251e192016-06-07 16:57:05 -0700458 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700459 String portUuid = getPortUuid(portName, bridgeUuid);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700460 Port port = (Port) TableGenerator.createTable(dbSchema, OvsdbTable.PORT);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700461 port.setName(portName);
462 if (portUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700463 insertConfig(PORT, UUID, BRIDGE, PORTS, bridgeUuid, port.getRow());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700464 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700465 }
466
467 @Override
468 public void dropPort(String bridgeName, String portName) {
469 String bridgeUuid = getBridgeUuid(bridgeName);
470 if (bridgeUuid == null) {
471 log.error("Could not find Bridge {} in {}", bridgeName, nodeId);
472 return;
473 }
474
475 String portUuid = getPortUuid(portName, bridgeUuid);
476 if (portUuid != null) {
477 log.info("Port {} delete", portName);
Frank Wange11a98d2016-10-26 17:04:03 +0800478 deleteConfig(PORT, UUID, portUuid, BRIDGE, PORTS, Uuid.uuid(portUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700479 }
480 }
481
lishuai6c56f5e2015-11-17 16:38:19 +0800482 @Override
Hyunsun Moon1251e192016-06-07 16:57:05 -0700483 public boolean createBridge(OvsdbBridge ovsdbBridge) {
484 DatabaseSchema dbSchema = schema.get(DATABASENAME);
485 String ovsUuid = getOvsUuid(DATABASENAME);
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700486
487 if (dbSchema == null || ovsUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700488 log.error("Can't find database Open_vSwitch");
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700489 return false;
490 }
491
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700492 Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema, OvsdbTable.BRIDGE);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700493 bridge.setOtherConfig(ovsdbBridge.otherConfigs());
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700494
Hyunsun Moon1251e192016-06-07 16:57:05 -0700495 if (ovsdbBridge.failMode().isPresent()) {
496 String failMode = ovsdbBridge.failMode().get().name().toLowerCase();
497 bridge.setFailMode(Sets.newHashSet(failMode));
Bob zhoue9795fd2016-05-12 20:18:45 +0800498 }
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700499
jaegonkim80bee532017-05-15 15:16:38 +0900500 if (ovsdbBridge.datapathType().isPresent()) {
501 String datapathType = ovsdbBridge.datapathType().get();
502 bridge.setDatapathType(datapathType);
503 }
504
Hyunsun Moon1251e192016-06-07 16:57:05 -0700505 String bridgeUuid = getBridgeUuid(ovsdbBridge.name());
Hyunsun Moon98025542016-03-08 04:36:02 -0800506 if (bridgeUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700507 bridge.setName(ovsdbBridge.name());
508 bridgeUuid = insertConfig(
509 BRIDGE, UUID, DATABASENAME, BRIDGES,
510 ovsUuid, bridge.getRow());
Hyunsun Moon98025542016-03-08 04:36:02 -0800511 } else {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700512 // update the bridge if it's already existing
513 updateConfig(BRIDGE, UUID, bridgeUuid, bridge.getRow());
Hyunsun Moon98025542016-03-08 04:36:02 -0800514 }
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700515
Hyunsun Moon1251e192016-06-07 16:57:05 -0700516 if (bridgeUuid == null) {
517 log.warn("Failed to create bridge {} on {}", ovsdbBridge.name(), nodeId);
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700518 return false;
519 }
520
Hyunsun Moon1251e192016-06-07 16:57:05 -0700521 createPort(ovsdbBridge.name(), ovsdbBridge.name());
522 setControllersWithUuid(Uuid.uuid(bridgeUuid), ovsdbBridge.controllers());
523
524 log.info("Created bridge {}", ovsdbBridge.name());
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700525 return true;
526 }
527
Hyunsun Moon1251e192016-06-07 16:57:05 -0700528 @Override
529 public ControllerInfo localController() {
530 IpAddress ipAddress = IpAddress.valueOf(((InetSocketAddress)
531 channel.localAddress()).getAddress());
532 return new ControllerInfo(ipAddress, OFPORT, "tcp");
andreaed976a42015-10-05 14:38:25 -0700533 }
534
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700535 private void setControllersWithUuid(Uuid bridgeUuid, List<ControllerInfo> controllers) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700536 DatabaseSchema dbSchema = schema.get(DATABASENAME);
andreaed976a42015-10-05 14:38:25 -0700537 if (dbSchema == null) {
538 log.debug("There is no schema");
539 return;
540 }
541 List<Controller> oldControllers = getControllers(bridgeUuid);
542 if (oldControllers == null) {
543 log.warn("There are no controllers");
544 return;
545 }
546
Jonathan Hart51539b82015-10-29 09:53:04 -0700547 Set<Uuid> newControllerUuids = new HashSet<>();
andreaed976a42015-10-05 14:38:25 -0700548
549 Set<ControllerInfo> newControllers = new HashSet<>(controllers);
550 List<Controller> removeControllers = new ArrayList<>();
551 oldControllers.forEach(controller -> {
552 ControllerInfo controllerInfo = new ControllerInfo((String) controller.getTargetColumn().data());
553 if (newControllers.contains(controllerInfo)) {
554 newControllers.remove(controllerInfo);
555 newControllerUuids.add(controller.getRow().uuid());
556 } else {
557 removeControllers.add(controller);
558 }
559 });
Hyunsun Moon1251e192016-06-07 16:57:05 -0700560 OvsdbRowStore controllerRowStore = getRowStore(DATABASENAME, CONTROLLER);
andreaed976a42015-10-05 14:38:25 -0700561 if (controllerRowStore == null) {
562 log.debug("There is no controller table");
563 return;
564 }
565
Hyunsun Moon1251e192016-06-07 16:57:05 -0700566 removeControllers.forEach(c -> deleteConfig(CONTROLLER, UUID, c.getRow().uuid().value(),
Saritha8a0c36a2017-07-04 15:01:35 +0530567 BRIDGE, BRIDGE_CONTROLLER, c.getRow().uuid()));
andreaed976a42015-10-05 14:38:25 -0700568 newControllers.stream().map(c -> {
569 Controller controller = (Controller) TableGenerator
570 .createTable(dbSchema, OvsdbTable.CONTROLLER);
571 controller.setTarget(c.target());
572 return controller;
573 }).forEach(c -> {
Saritha8a0c36a2017-07-04 15:01:35 +0530574 String uuid = insertConfig(CONTROLLER, UUID, BRIDGE, BRIDGE_CONTROLLER, bridgeUuid.value(),
andreaed976a42015-10-05 14:38:25 -0700575 c.getRow());
Jonathan Hart51539b82015-10-29 09:53:04 -0700576 newControllerUuids.add(Uuid.uuid(uuid));
andreaed976a42015-10-05 14:38:25 -0700577
578 });
579
Hyunsun Moon1251e192016-06-07 16:57:05 -0700580 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
andreaed976a42015-10-05 14:38:25 -0700581 if (rowStore == null) {
582 log.debug("There is no bridge table");
583 return;
584 }
585
586 Row bridgeRow = rowStore.getRow(bridgeUuid.value());
587 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
588 bridge.setController(OvsdbSet.ovsdbSet(newControllerUuids));
Hyunsun Moon1251e192016-06-07 16:57:05 -0700589 updateConfig(BRIDGE, UUID, bridgeUuid.value(), bridge.getRow());
andreaed976a42015-10-05 14:38:25 -0700590 }
591
andreaed976a42015-10-05 14:38:25 -0700592 @Override
593 public void setControllersWithDeviceId(DeviceId deviceId, List<ControllerInfo> controllers) {
Jonathan Hart51539b82015-10-29 09:53:04 -0700594 setControllersWithUuid(getBridgeUuid(deviceId), controllers);
andreaed976a42015-10-05 14:38:25 -0700595 }
596
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700597 @Override
598 public void dropBridge(String bridgeName) {
Jonathan Hart51539b82015-10-29 09:53:04 -0700599 String bridgeUuid = getBridgeUuid(bridgeName);
600 if (bridgeUuid == null) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700601 log.warn("Could not find bridge in node", nodeId.getIpAddress());
602 return;
603 }
Frank Wange11a98d2016-10-26 17:04:03 +0800604 deleteConfig(BRIDGE, UUID, bridgeUuid, DATABASENAME, BRIDGES, Uuid.uuid(bridgeUuid));
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700605 }
606
Frank Wange11a98d2016-10-26 17:04:03 +0800607 @Override
608 public void applyQos(PortNumber portNumber, String qosName) {
609 DatabaseSchema dbSchema = schema.get(DATABASENAME);
610 OvsdbRowStore portRowStore = getRowStore(DATABASENAME, PORT);
611 if (portRowStore == null) {
612 log.debug("The port uuid is null");
613 return;
614 }
615 OvsdbRowStore qosRowStore = getRowStore(DATABASENAME, QOS);
616 if (qosRowStore == null) {
617 log.debug("The qos uuid is null");
618 return;
619 }
620
621 // Due to Qos Table doesn't have a unique identifier except uuid, unlike
622 // Bridge or Port Table has a name column,in order to make the api more
623 // general, put qos name in external_ids column of Qos Table if this qos
624 // created by onos.
625 ConcurrentMap<String, Row> qosTableRows = qosRowStore.getRowStore();
626 ConcurrentMap<String, Row> portTableRows = portRowStore.getRowStore();
627 Row qosRow = qosTableRows.values().stream().filter(r -> {
628 OvsdbMap ovsdbMap = (OvsdbMap) (r.getColumn(EXTERNAL_ID).data());
629 return qosName.equals(ovsdbMap.map().get(QOS_EXTERNAL_ID_KEY));
630 }).findFirst().orElse(null);
631
632 Row portRow = portTableRows.values().stream()
633 .filter(r -> r.getColumn("name").data().equals(portNumber.name()))
634 .findFirst().orElse(null);
635 if (portRow != null && qosRow != null) {
636 String qosId = qosRow.uuid().value();
637 Uuid portUuid = portRow.uuid();
638 Map<String, Column> columns = new HashMap<>();
639 Row newPortRow = new Row(PORT, portUuid, columns);
640 Port newport = new Port(dbSchema, newPortRow);
641 columns.put(Port.PortColumn.QOS.columnName(), newport.getQosColumn());
642 newport.setQos(Uuid.uuid(qosId));
643 updateConfig(PORT, UUID, portUuid.value(), newport.getRow());
644 }
645 }
646
647 @Override
648 public void removeQos(PortNumber portNumber) {
649 DatabaseSchema dbSchema = schema.get(DATABASENAME);
650 OvsdbRowStore rowStore = getRowStore(DATABASENAME, PORT);
651 if (rowStore == null) {
652 log.debug("The qos uuid is null");
653 return;
654 }
655
656 ConcurrentMap<String, Row> ovsTableRows = rowStore.getRowStore();
657 Row portRow = ovsTableRows.values().stream()
658 .filter(r -> r.getColumn("name").data().equals(portNumber.name()))
659 .findFirst().orElse(null);
660 if (portRow == null) {
661 log.warn("Couldn't find port {} in ovsdb port table.", portNumber.name());
662 return;
663 }
664
665 OvsdbSet ovsdbSet = ((OvsdbSet) portRow.getColumn(PORT_QOS).data());
666 @SuppressWarnings("unchecked")
667 Set<Uuid> qosIdSet = ovsdbSet.set();
668 if (qosIdSet == null || qosIdSet.isEmpty()) {
669 return;
670 }
671 Uuid qosUuid = (Uuid) qosIdSet.toArray()[0];
672 Condition condition = ConditionUtil.isEqual(UUID, portRow.uuid());
673 List<Condition> conditions = Lists.newArrayList(condition);
674 Mutation mutation = MutationUtil.delete(PORT_QOS, qosUuid);
675 List<Mutation> mutations = Lists.newArrayList(mutation);
676
677 ArrayList<Operation> operations = Lists.newArrayList();
678 Mutate mutate = new Mutate(dbSchema.getTableSchema(PORT), conditions, mutations);
679 operations.add(mutate);
680 transactConfig(DATABASENAME, operations);
681 }
682
683 @Override
684 public boolean createQos(OvsdbQos ovsdbQos) {
685 DatabaseSchema dbSchema = schema.get(DATABASENAME);
686 Qos qos = (Qos) TableGenerator.createTable(dbSchema, OvsdbTable.QOS);
687 OvsdbRowStore rowStore = getRowStore(DATABASENAME, QOS);
688 if (rowStore == null) {
689 log.debug("The qos uuid is null");
690 return false;
691 }
692
693 ArrayList<Operation> operations = Lists.newArrayList();
694 Set<String> types = Sets.newHashSet();
695 Map<Long, Uuid> queues = Maps.newHashMap();
696
697 types.add(ovsdbQos.qosType());
698 qos.setOtherConfig(ovsdbQos.otherConfigs());
699 qos.setExternalIds(ovsdbQos.externalIds());
700 qos.setType(types);
701 if (ovsdbQos.qosQueues().isPresent()) {
702 for (Map.Entry<Long, String> entry : ovsdbQos.qosQueues().get().entrySet()) {
703 OvsdbRowStore queueRowStore = getRowStore(DATABASENAME, QUEUE);
704 if (queueRowStore != null) {
705 ConcurrentMap<String, Row> queueTableRows = queueRowStore.getRowStore();
706 Row queueRow = queueTableRows.values().stream().filter(r -> {
707 OvsdbMap ovsdbMap = (OvsdbMap) (r.getColumn(EXTERNAL_ID).data());
708 return entry.getValue().equals(ovsdbMap.map().get(QUEUE_EXTERNAL_ID_KEY));
709 }).findFirst().orElse(null);
710 if (queueRow != null) {
711 queues.put(entry.getKey(), queueRow.uuid());
712 }
713 }
714 }
715 qos.setQueues(queues);
716 }
717
718 Insert qosInsert = new Insert(dbSchema.getTableSchema(QOS), QOS, qos.getRow());
719 operations.add(qosInsert);
720 try {
721 transactConfig(DATABASENAME, operations).get();
722 } catch (InterruptedException | ExecutionException e) {
723 return false;
724 }
725 return true;
726 }
727
728 @Override
729 public void dropQos(QosId qosId) {
730 OvsdbRowStore rowStore = getRowStore(DATABASENAME, QOS);
731 if (rowStore != null) {
732 ConcurrentMap<String, Row> qosTableRows = rowStore.getRowStore();
733 Row qosRow = qosTableRows.values().stream().filter(r -> {
734 OvsdbMap ovsdbMap = (OvsdbMap) (r.getColumn(EXTERNAL_ID).data());
735 return qosId.name().equals(ovsdbMap.map().get(QOS_EXTERNAL_ID_KEY));
736 }).findFirst().orElse(null);
737 if (qosRow != null) {
738 deleteConfig(QOS, UUID, qosRow.uuid().value(), PORT, PORT_QOS, qosRow.uuid());
739 }
740 }
741 }
742 @Override
743 public OvsdbQos getQos(QosId qosId) {
744 Set<OvsdbQos> ovsdbQoses = getQoses();
745 return ovsdbQoses.stream().filter(r ->
746 qosId.name().equals(r.externalIds().get(QOS_EXTERNAL_ID_KEY))).
747 findFirst().orElse(null);
748 }
749
750 @Override
751 public Set<OvsdbQos> getQoses() {
752 Set<OvsdbQos> ovsdbQoses = new HashSet<>();
753 OvsdbRowStore rowStore = getRowStore(DATABASENAME, QOS);
754 if (rowStore == null) {
755 log.debug("The qos uuid is null");
756 return ovsdbQoses;
757 }
758 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
759 for (String uuid : rows.keySet()) {
760 Row row = getRow(DATABASENAME, QOS, uuid);
761 OvsdbQos ovsdbQos = getOvsdbQos(row);
762 if (ovsdbQos != null) {
763 ovsdbQoses.add(ovsdbQos);
764 }
765 }
766 return ovsdbQoses;
767 }
768
769 @Override
770 public boolean createQueue(OvsdbQueue ovsdbQueue) {
771 DatabaseSchema dbSchema = schema.get(DATABASENAME);
772 Queue queue = (Queue) TableGenerator.createTable(dbSchema, OvsdbTable.QUEUE);
773 ArrayList<Operation> operations = Lists.newArrayList();
774 OvsdbRowStore rowStore = getRowStore(DATABASENAME, QUEUE);
775 if (rowStore == null) {
776 log.debug("The queue uuid is null");
777 return false;
778 }
779
780 if (ovsdbQueue.dscp().isPresent()) {
781 queue.setDscp(ImmutableSet.of(ovsdbQueue.dscp().get()));
782 }
783 queue.setOtherConfig(ovsdbQueue.otherConfigs());
784 queue.setExternalIds(ovsdbQueue.externalIds());
785 Insert queueInsert = new Insert(dbSchema.getTableSchema(QUEUE), QUEUE, queue.getRow());
786 operations.add(queueInsert);
787
788 try {
789 transactConfig(DATABASENAME, operations).get();
790 } catch (InterruptedException | ExecutionException e) {
791 log.error("createQueue transactConfig get exception !");
792 }
793 return true;
794 }
795
796 @Override
797 public void dropQueue(QueueId queueId) {
798 OvsdbRowStore queueRowStore = getRowStore(DATABASENAME, QUEUE);
799 if (queueRowStore == null) {
800 return;
801 }
802
803 ConcurrentMap<String, Row> queueTableRows = queueRowStore.getRowStore();
804 Row queueRow = queueTableRows.values().stream().filter(r -> {
805 OvsdbMap ovsdbMap = (OvsdbMap) (r.getColumn(EXTERNAL_ID).data());
806 return queueId.name().equals(ovsdbMap.map().get(QUEUE_EXTERNAL_ID_KEY));
807 }).findFirst().orElse(null);
808 if (queueRow == null) {
809 return;
810 }
811
812 String queueUuid = queueRow.uuid().value();
813 OvsdbRowStore qosRowStore = getRowStore(DATABASENAME, QOS);
814 if (qosRowStore != null) {
815 Map<Long, Uuid> queueMap = new HashMap<>();
816 ConcurrentMap<String, Row> qosTableRows = qosRowStore.getRowStore();
817 qosTableRows.values().stream().filter(r -> {
818 Map<Integer, Uuid> ovsdbMap = ((OvsdbMap) r.getColumn(QUEUES).data()).map();
819 Set<Integer> keySet = ovsdbMap.keySet();
820 for (Integer keyId : keySet) {
821 if (ovsdbMap.get(keyId).equals(Uuid.uuid(queueUuid))) {
822 queueMap.put(keyId.longValue(), Uuid.uuid(queueUuid));
823 return true;
824 }
825 }
826 return false;
827 }).findFirst().orElse(null);
828 deleteConfig(QUEUE, UUID, queueUuid, QOS, QUEUES, OvsdbMap.ovsdbMap(queueMap));
829 } else {
830 deleteConfig(QUEUE, UUID, queueUuid, null, null, null);
831 }
832 }
833 @Override
834 public OvsdbQueue getQueue(QueueId queueId) {
835 Set<OvsdbQueue> ovsdbQueues = getQueues();
836 return ovsdbQueues.stream().filter(r ->
837 queueId.name().equals(r.externalIds().get(QUEUE_EXTERNAL_ID_KEY))).
838 findFirst().orElse(null);
839 }
840
841 @Override
842 public Set<OvsdbQueue> getQueues() {
843 Set<OvsdbQueue> ovsdbqueues = new HashSet<>();
844 OvsdbRowStore rowStore = getRowStore(DATABASENAME, QUEUE);
845 if (rowStore == null) {
846 log.debug("The queue uuid is null");
847 return ovsdbqueues;
848 }
849 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
850 for (String uuid : rows.keySet()) {
851 Row row = getRow(DATABASENAME, QUEUE, uuid);
852 OvsdbQueue ovsdbQueue = getOvsdbQueue(row);
853 if (ovsdbQueue != null) {
854 ovsdbqueues.add(ovsdbQueue);
855 }
856 }
857 return ovsdbqueues;
858 }
Pier Ventref5d72362016-07-17 12:02:14 +0200859 /**
860 * Creates a mirror port. Mirrors the traffic
861 * that goes to selectDstPort or comes from
862 * selectSrcPort or packets containing selectVlan
863 * to mirrorPort or to all ports that trunk mirrorVlan.
864 *
865 * @param mirror the OVSDB mirror description
866 * @return true if mirror creation is successful, false otherwise
867 */
868 @Override
869 public boolean createMirror(String bridgeName, OvsdbMirror mirror) {
870
871 /**
872 * Retrieves bridge's uuid. It is necessary to update
873 * Bridge table.
874 */
875 String bridgeUuid = getBridgeUuid(bridgeName);
876 if (bridgeUuid == null) {
877 log.warn("Couldn't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
878 return false;
879 }
880
881 OvsdbMirror.Builder mirrorBuilder = OvsdbMirror.builder();
882
883 mirrorBuilder.mirroringName(mirror.mirroringName());
884 mirrorBuilder.selectAll(mirror.selectAll());
885
886 /**
887 * Retrieves the uuid of the monitored dst ports.
888 */
889 mirrorBuilder.monitorDstPorts(mirror.monitorDstPorts().parallelStream()
890 .map(dstPort -> {
891 String dstPortUuid = getPortUuid(dstPort.value(), bridgeUuid);
892 if (dstPortUuid != null) {
893 return Uuid.uuid(dstPortUuid);
894 }
895 log.warn("Couldn't find port {} in {}",
896 dstPort.value(), nodeId.getIpAddress());
897 return null;
898 })
899 .filter(Objects::nonNull)
900 .collect(Collectors.toSet())
901 );
902
903 /**
904 * Retrieves the uuid of the monitored src ports.
905 */
906 mirrorBuilder.monitorSrcPorts(mirror.monitorSrcPorts().parallelStream()
907 .map(srcPort -> {
908 String srcPortUuid = getPortUuid(srcPort.value(), bridgeUuid);
909 if (srcPortUuid != null) {
910 return Uuid.uuid(srcPortUuid);
911 }
912 log.warn("Couldn't find port {} in {}",
913 srcPort.value(), nodeId.getIpAddress());
914 return null;
915 }).filter(Objects::nonNull)
916 .collect(Collectors.toSet())
917 );
918
919 mirrorBuilder.monitorVlans(mirror.monitorVlans());
920 mirrorBuilder.mirrorPort(mirror.mirrorPort());
921 mirrorBuilder.mirrorVlan(mirror.mirrorVlan());
922 mirrorBuilder.externalIds(mirror.externalIds());
923 mirror = mirrorBuilder.build();
924
Jon Hallcbd1b392017-01-18 20:15:44 -0800925 if (mirror.monitorDstPorts().isEmpty() &&
926 mirror.monitorSrcPorts().isEmpty() &&
927 mirror.monitorVlans().isEmpty()) {
Pier Ventref5d72362016-07-17 12:02:14 +0200928 log.warn("Invalid monitoring data");
929 return false;
930 }
931
932 DatabaseSchema dbSchema = schema.get(DATABASENAME);
933
934 Mirror mirrorEntry = (Mirror) TableGenerator.createTable(dbSchema, OvsdbTable.MIRROR);
935 mirrorEntry.setName(mirror.mirroringName());
936 mirrorEntry.setSelectDstPort(mirror.monitorDstPorts());
937 mirrorEntry.setSelectSrcPort(mirror.monitorSrcPorts());
938 mirrorEntry.setSelectVlan(mirror.monitorVlans());
939 mirrorEntry.setExternalIds(mirror.externalIds());
940
941 /**
942 * If mirror port, retrieves the uuid of the mirror port.
943 */
944 if (mirror.mirrorPort() != null) {
945
946 String outputPortUuid = getPortUuid(mirror.mirrorPort().value(), bridgeUuid);
947 if (outputPortUuid == null) {
948 log.warn("Couldn't find port {} in {}", mirror.mirrorPort().value(), nodeId.getIpAddress());
949 return false;
950 }
951
952 mirrorEntry.setOutputPort(Uuid.uuid(outputPortUuid));
953
954 } else if (mirror.mirrorVlan() != null) {
955
956 mirrorEntry.setOutputVlan(mirror.mirrorVlan());
957
958 } else {
959 log.warn("Invalid mirror, no mirror port and no mirror vlan");
960 return false;
961 }
962
963 ArrayList<Operation> operations = Lists.newArrayList();
964 Insert mirrorInsert = new Insert(dbSchema.getTableSchema("Mirror"), "Mirror", mirrorEntry.getRow());
965 operations.add(mirrorInsert);
966
967 // update the bridge table
968 Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(bridgeUuid));
969 Mutation mutation = MutationUtil.insert(MIRRORS, Uuid.uuid("Mirror"));
970 List<Condition> conditions = Lists.newArrayList(condition);
971 List<Mutation> mutations = Lists.newArrayList(mutation);
972 operations.add(new Mutate(dbSchema.getTableSchema("Bridge"), conditions, mutations));
973
974 transactConfig(DATABASENAME, operations);
975 log.info("Created mirror {}", mirror.mirroringName());
976 return true;
977 }
978
979 /**
980 * Drops the configuration for mirror.
981 *
Ray Milkeyef794342016-11-09 16:20:29 -0800982 * @param mirroringName name of mirror to drop
Pier Ventref5d72362016-07-17 12:02:14 +0200983 */
984 @Override
985 public void dropMirror(MirroringName mirroringName) {
986 String mirrorUuid = getMirrorUuid(mirroringName.name());
987 if (mirrorUuid != null) {
988 log.info("Deleted mirror {}", mirroringName.name());
Frank Wange11a98d2016-10-26 17:04:03 +0800989 deleteConfig(MIRROR, UUID, mirrorUuid, BRIDGE, MIRRORS, Uuid.uuid(mirrorUuid));
Pier Ventref5d72362016-07-17 12:02:14 +0200990 }
991 log.warn("Unable to delete {}", mirroringName.name());
992 return;
993 }
994
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700995 @Override
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700996 public boolean createInterface(String bridgeName, OvsdbInterface ovsdbIface) {
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700997 String bridgeUuid = getBridgeUuid(bridgeName);
998 if (bridgeUuid == null) {
999 log.warn("Couldn't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
1000 return false;
1001 }
1002
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001003 if (getPortUuid(ovsdbIface.name(), bridgeUuid) != null) {
1004 log.warn("Interface {} already exists", ovsdbIface.name());
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001005 // remove existing one and re-create?
1006 return false;
1007 }
1008
1009 ArrayList<Operation> operations = Lists.newArrayList();
Hyunsun Moon1251e192016-06-07 16:57:05 -07001010 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001011
Hyunsun Moon89478662016-06-09 17:52:34 -07001012 // insert a new port with the interface name
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001013 Port port = (Port) TableGenerator.createTable(dbSchema, OvsdbTable.PORT);
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001014 port.setName(ovsdbIface.name());
1015 Insert portInsert = new Insert(dbSchema.getTableSchema(PORT), PORT, port.getRow());
1016 portInsert.getRow().put(INTERFACES, Uuid.uuid(INTERFACE));
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001017 operations.add(portInsert);
1018
Hyunsun Moon89478662016-06-09 17:52:34 -07001019 // update the bridge table with the new port
Hyunsun Moon1251e192016-06-07 16:57:05 -07001020 Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(bridgeUuid));
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001021 Mutation mutation = MutationUtil.insert(PORTS, Uuid.uuid(PORT));
1022 List<Condition> conditions = Lists.newArrayList(condition);
1023 List<Mutation> mutations = Lists.newArrayList(mutation);
1024 operations.add(new Mutate(dbSchema.getTableSchema(BRIDGE), conditions, mutations));
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001025
Hyunsun Moon89478662016-06-09 17:52:34 -07001026 // insert an interface
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001027 Interface intf = (Interface) TableGenerator.createTable(dbSchema, OvsdbTable.INTERFACE);
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001028 intf.setName(ovsdbIface.name());
jaegonkim256f2c12017-05-26 00:03:42 +09001029
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001030 intf.setType(ovsdbIface.typeToString());
jaegonkim256f2c12017-05-26 00:03:42 +09001031
1032 if (ovsdbIface.mtu().isPresent()) {
1033 Set<Long> mtuSet = Sets.newConcurrentHashSet();
1034 mtuSet.add(ovsdbIface.mtu().get());
1035 intf.setMtu(mtuSet);
1036 intf.setMtuRequest(mtuSet);
1037 }
1038
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001039 intf.setOptions(ovsdbIface.options());
1040 Insert intfInsert = new Insert(dbSchema.getTableSchema(INTERFACE), INTERFACE, intf.getRow());
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001041 operations.add(intfInsert);
1042
Hyunsun Moon1251e192016-06-07 16:57:05 -07001043 transactConfig(DATABASENAME, operations);
Hyunsun Moon89478662016-06-09 17:52:34 -07001044 log.info("Created interface {}", ovsdbIface);
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001045 return true;
1046 }
1047
1048 @Override
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001049 public boolean dropInterface(String ifaceName) {
1050 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
1051 if (rowStore == null) {
1052 log.warn("Failed to get BRIDGE table");
1053 return false;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001054 }
1055
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001056 ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
1057 if (bridgeTableRows == null) {
1058 log.warn("Failed to get BRIDGE table rows");
1059 return false;
1060 }
1061
1062 // interface name is unique
1063 Optional<String> bridgeId = bridgeTableRows.keySet().stream()
1064 .filter(uuid -> getPortUuid(ifaceName, uuid) != null)
1065 .findFirst();
1066
1067 if (bridgeId.isPresent()) {
1068 String portId = getPortUuid(ifaceName, bridgeId.get());
Frank Wange11a98d2016-10-26 17:04:03 +08001069 deleteConfig(PORT, UUID, portId, BRIDGE, PORTS, Uuid.uuid(portId));
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001070 return true;
1071 } else {
1072 log.warn("Unable to find the interface with name {}", ifaceName);
1073 return false;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001074 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001075 }
1076
1077 /**
1078 * Delete transact config.
1079 *
andreaed976a42015-10-05 14:38:25 -07001080 * @param childTableName child table name
1081 * @param childColumnName child column name
1082 * @param childUuid child row uuid
1083 * @param parentTableName parent table name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001084 * @param parentColumnName parent column
Frank Wange11a98d2016-10-26 17:04:03 +08001085 * @param referencedValue referenced value
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001086 */
1087 private void deleteConfig(String childTableName, String childColumnName,
andreaed976a42015-10-05 14:38:25 -07001088 String childUuid, String parentTableName,
Frank Wange11a98d2016-10-26 17:04:03 +08001089 String parentColumnName, Object referencedValue) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001090 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001091 TableSchema childTableSchema = dbSchema.getTableSchema(childTableName);
1092
1093 ArrayList<Operation> operations = Lists.newArrayList();
Frank Wange11a98d2016-10-26 17:04:03 +08001094 if (parentTableName != null && parentColumnName != null && referencedValue != null) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001095 TableSchema parentTableSchema = dbSchema
1096 .getTableSchema(parentTableName);
1097 ColumnSchema parentColumnSchema = parentTableSchema
1098 .getColumnSchema(parentColumnName);
1099 List<Mutation> mutations = Lists.newArrayList();
Frank Wange11a98d2016-10-26 17:04:03 +08001100 Mutation mutation = MutationUtil.delete(parentColumnSchema.name(), referencedValue);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001101 mutations.add(mutation);
1102 List<Condition> conditions = Lists.newArrayList();
Frank Wange11a98d2016-10-26 17:04:03 +08001103 Condition condition = ConditionUtil.includes(parentColumnName, referencedValue);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001104 conditions.add(condition);
1105 Mutate op = new Mutate(parentTableSchema, conditions, mutations);
1106 operations.add(op);
1107 }
1108
1109 List<Condition> conditions = Lists.newArrayList();
Jonathan Hart51539b82015-10-29 09:53:04 -07001110 Condition condition = ConditionUtil.isEqual(childColumnName, Uuid.uuid(childUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001111 conditions.add(condition);
1112 Delete del = new Delete(childTableSchema, conditions);
1113 operations.add(del);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001114 transactConfig(DATABASENAME, operations);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001115 }
1116
1117 /**
1118 * Update transact config.
1119 *
andreaed976a42015-10-05 14:38:25 -07001120 * @param tableName table name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001121 * @param columnName column name
andreaed976a42015-10-05 14:38:25 -07001122 * @param uuid uuid
1123 * @param row the config data
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001124 */
1125 private void updateConfig(String tableName, String columnName, String uuid,
andreaed976a42015-10-05 14:38:25 -07001126 Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001127 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001128 TableSchema tableSchema = dbSchema.getTableSchema(tableName);
1129
1130 List<Condition> conditions = Lists.newArrayList();
Jonathan Hart51539b82015-10-29 09:53:04 -07001131 Condition condition = ConditionUtil.isEqual(columnName, Uuid.uuid(uuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001132 conditions.add(condition);
1133
1134 Update update = new Update(tableSchema, row, conditions);
1135
1136 ArrayList<Operation> operations = Lists.newArrayList();
1137 operations.add(update);
1138
Hyunsun Moon1251e192016-06-07 16:57:05 -07001139 transactConfig(DATABASENAME, operations);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001140 }
1141
1142 /**
1143 * Insert transact config.
1144 *
andreaed976a42015-10-05 14:38:25 -07001145 * @param childTableName child table name
1146 * @param childColumnName child column name
1147 * @param parentTableName parent table name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001148 * @param parentColumnName parent column
andreaed976a42015-10-05 14:38:25 -07001149 * @param parentUuid parent uuid
1150 * @param row the config data
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001151 * @return uuid, empty if no uuid is find
1152 */
1153 private String insertConfig(String childTableName, String childColumnName,
andreaed976a42015-10-05 14:38:25 -07001154 String parentTableName, String parentColumnName,
1155 String parentUuid, Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001156 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001157 TableSchema tableSchema = dbSchema.getTableSchema(childTableName);
1158
Sho SHIMIZUff18f8c2016-03-11 14:43:53 -08001159 Insert insert = new Insert(tableSchema, childTableName, row);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001160
1161 ArrayList<Operation> operations = Lists.newArrayList();
1162 operations.add(insert);
1163
1164 if (parentTableName != null && parentColumnName != null) {
1165 TableSchema parentTableSchema = dbSchema
1166 .getTableSchema(parentTableName);
1167 ColumnSchema parentColumnSchema = parentTableSchema
1168 .getColumnSchema(parentColumnName);
1169
1170 List<Mutation> mutations = Lists.newArrayList();
1171 Mutation mutation = MutationUtil.insert(parentColumnSchema.name(),
Sho SHIMIZUff18f8c2016-03-11 14:43:53 -08001172 Uuid.uuid(childTableName));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001173 mutations.add(mutation);
1174
1175 List<Condition> conditions = Lists.newArrayList();
Hyunsun Moon1251e192016-06-07 16:57:05 -07001176 Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(parentUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001177 conditions.add(condition);
1178
1179 Mutate op = new Mutate(parentTableSchema, conditions, mutations);
1180 operations.add(op);
1181 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001182 if (childTableName.equalsIgnoreCase(PORT)) {
1183 log.debug("Handle port insert");
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001184 Insert intfInsert = handlePortInsertTable(row);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001185
1186 if (intfInsert != null) {
1187 operations.add(intfInsert);
1188 }
1189
1190 Insert ins = (Insert) operations.get(0);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001191 ins.getRow().put("interfaces", Uuid.uuid(INTERFACE));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001192 }
1193
1194 List<OperationResult> results;
1195 try {
jaegonkim01d7c912017-01-22 22:03:38 +09001196 results = transactConfig(DATABASENAME, operations)
1197 .get(TRANSACTCONFIG_TIMEOUT, TimeUnit.SECONDS);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001198 return results.get(0).getUuid().value();
jaegonkim01d7c912017-01-22 22:03:38 +09001199 } catch (TimeoutException e) {
1200 log.warn("TimeoutException thrown while to get result");
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001201 } catch (InterruptedException e) {
1202 log.warn("Interrupted while waiting to get result");
1203 Thread.currentThread().interrupt();
1204 } catch (ExecutionException e) {
1205 log.error("Exception thrown while to get result");
1206 }
1207
1208 return null;
1209 }
1210
jaegonkim01d7c912017-01-22 22:03:38 +09001211
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001212 /**
1213 * Handles port insert.
1214 *
andreaed976a42015-10-05 14:38:25 -07001215 * @param portRow row of port
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001216 * @return insert, empty if null
1217 */
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001218 private Insert handlePortInsertTable(Row portRow) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001219 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001220
Hyunsun Moon1251e192016-06-07 16:57:05 -07001221 TableSchema portTableSchema = dbSchema.getTableSchema(PORT);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001222 ColumnSchema portColumnSchema = portTableSchema.getColumnSchema("name");
1223
1224 String portName = (String) portRow.getColumn(portColumnSchema.name()).data();
Hyunsun Moon1251e192016-06-07 16:57:05 -07001225 Interface inf = (Interface) TableGenerator.createTable(dbSchema, OvsdbTable.INTERFACE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001226 inf.setName(portName);
1227
Hyunsun Moon1251e192016-06-07 16:57:05 -07001228 TableSchema intfTableSchema = dbSchema.getTableSchema(INTERFACE);
1229 return new Insert(intfTableSchema, INTERFACE, inf.getRow());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001230 }
1231
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001232 @Override
1233 public ListenableFuture<DatabaseSchema> getOvsdbSchema(String dbName) {
1234 if (dbName == null) {
1235 return null;
1236 }
1237 DatabaseSchema databaseSchema = schema.get(dbName);
1238 if (databaseSchema == null) {
1239 List<String> dbNames = new ArrayList<String>();
1240 dbNames.add(dbName);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001241 Function<JsonNode, DatabaseSchema> rowFunction = input -> {
1242 log.debug("Get ovsdb database schema {}", dbName);
1243 DatabaseSchema dbSchema = FromJsonUtil.jsonNodeToDbSchema(dbName, input);
1244 if (dbSchema == null) {
1245 log.debug("Get ovsdb database schema error");
1246 return null;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001247 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001248 schema.put(dbName, dbSchema);
1249 return dbSchema;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001250 };
1251
1252 ListenableFuture<JsonNode> input = getSchema(dbNames);
1253 if (input != null) {
1254 return Futures.transform(input, rowFunction);
1255 }
1256 return null;
1257 } else {
1258 return Futures.immediateFuture(databaseSchema);
1259 }
1260 }
1261
1262 @Override
1263 public ListenableFuture<TableUpdates> monitorTables(String dbName, String id) {
1264 if (dbName == null) {
1265 return null;
1266 }
1267 DatabaseSchema dbSchema = schema.get(dbName);
1268 if (dbSchema != null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001269 Function<JsonNode, TableUpdates> rowFunction = input -> {
1270 log.debug("Get table updates");
1271 TableUpdates updates = FromJsonUtil.jsonNodeToTableUpdates(input, dbSchema);
1272 if (updates == null) {
1273 log.debug("Get table updates error");
1274 return null;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001275 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001276 return updates;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001277 };
1278 return Futures.transform(monitor(dbSchema, id), rowFunction);
1279 }
1280 return null;
1281 }
1282
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001283 private ListenableFuture<List<OperationResult>> transactConfig(String dbName,
1284 List<Operation> operations) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001285 if (dbName == null) {
1286 return null;
1287 }
1288 DatabaseSchema dbSchema = schema.get(dbName);
1289 if (dbSchema != null) {
andreaed976a42015-10-05 14:38:25 -07001290 Function<List<JsonNode>, List<OperationResult>> rowFunction = (input -> {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001291 log.debug("Get ovsdb operation result");
1292 List<OperationResult> result = FromJsonUtil.jsonNodeToOperationResult(input, operations);
andreaed976a42015-10-05 14:38:25 -07001293 if (result == null) {
1294 log.debug("The operation result is null");
1295 return null;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001296 }
andreaed976a42015-10-05 14:38:25 -07001297 return result;
1298 });
Hyunsun Moon1251e192016-06-07 16:57:05 -07001299 return Futures.transform(transact(dbSchema, operations), rowFunction);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001300 }
1301 return null;
1302 }
1303
1304 @Override
1305 public ListenableFuture<JsonNode> getSchema(List<String> dbnames) {
1306 String id = java.util.UUID.randomUUID().toString();
1307 String getSchemaString = JsonRpcWriterUtil.getSchemaStr(id, dbnames);
1308
1309 SettableFuture<JsonNode> sf = SettableFuture.create();
1310 requestResult.put(id, sf);
1311 requestMethod.put(id, "getSchema");
1312
1313 channel.writeAndFlush(getSchemaString);
1314 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001315 }
1316
1317 @Override
1318 public ListenableFuture<List<String>> echo() {
1319 String id = java.util.UUID.randomUUID().toString();
1320 String echoString = JsonRpcWriterUtil.echoStr(id);
1321
1322 SettableFuture<List<String>> sf = SettableFuture.create();
1323 requestResult.put(id, sf);
1324 requestMethod.put(id, "echo");
1325
1326 channel.writeAndFlush(echoString);
1327 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001328 }
1329
1330 @Override
1331 public ListenableFuture<JsonNode> monitor(DatabaseSchema dbSchema,
1332 String monitorId) {
1333 String id = java.util.UUID.randomUUID().toString();
1334 String monitorString = JsonRpcWriterUtil.monitorStr(id, monitorId,
1335 dbSchema);
1336
1337 SettableFuture<JsonNode> sf = SettableFuture.create();
1338 requestResult.put(id, sf);
1339 requestMethod.put(id, "monitor");
1340
1341 channel.writeAndFlush(monitorString);
1342 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001343 }
1344
1345 @Override
1346 public ListenableFuture<List<String>> listDbs() {
1347 String id = java.util.UUID.randomUUID().toString();
1348 String listDbsString = JsonRpcWriterUtil.listDbsStr(id);
1349
1350 SettableFuture<List<String>> sf = SettableFuture.create();
1351 requestResult.put(id, sf);
1352 requestMethod.put(id, "listDbs");
1353
1354 channel.writeAndFlush(listDbsString);
1355 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001356 }
1357
1358 @Override
1359 public ListenableFuture<List<JsonNode>> transact(DatabaseSchema dbSchema,
1360 List<Operation> operations) {
1361 String id = java.util.UUID.randomUUID().toString();
1362 String transactString = JsonRpcWriterUtil.transactStr(id, dbSchema,
1363 operations);
1364
1365 SettableFuture<List<JsonNode>> sf = SettableFuture.create();
1366 requestResult.put(id, sf);
1367 requestMethod.put(id, "transact");
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001368 channel.writeAndFlush(transactString);
1369 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001370 }
1371
andreaed976a42015-10-05 14:38:25 -07001372 @SuppressWarnings({"rawtypes", "unchecked"})
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001373 @Override
1374 public void processResult(JsonNode response) {
1375 log.debug("Handle result");
1376 String requestId = response.get("id").asText();
1377 SettableFuture sf = requestResult.get(requestId);
1378 if (sf == null) {
1379 log.debug("No such future to process");
1380 return;
1381 }
1382 String methodName = requestMethod.get(requestId);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001383 sf.set(FromJsonUtil.jsonResultParser(response, methodName));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001384 }
1385
1386 @Override
1387 public void processRequest(JsonNode requestJson) {
1388 log.debug("Handle request");
1389 if (requestJson.get("method").asText().equalsIgnoreCase("echo")) {
1390 log.debug("handle echo request");
1391
1392 String replyString = FromJsonUtil.getEchoRequestStr(requestJson);
1393 channel.writeAndFlush(replyString);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001394 } else {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001395 FromJsonUtil.jsonCallbackRequestParser(requestJson, monitorCallBack);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001396 }
1397 }
1398
1399 @Override
1400 public void setCallback(Callback monitorCallback) {
1401 this.monitorCallBack = monitorCallback;
1402 }
1403
1404 @Override
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001405 public Set<OvsdbBridge> getBridges() {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001406 Set<OvsdbBridge> ovsdbBridges = new HashSet<>();
1407 OvsdbTableStore tableStore = getTableStore(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001408 if (tableStore == null) {
MaoJianweidac220d2016-07-04 22:37:52 +08001409 return ovsdbBridges;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001410 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001411 OvsdbRowStore rowStore = tableStore.getRows(BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001412 if (rowStore == null) {
MaoJianweidac220d2016-07-04 22:37:52 +08001413 return ovsdbBridges;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001414 }
1415 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1416 for (String uuid : rows.keySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001417 Row row = getRow(DATABASENAME, BRIDGE, uuid);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001418 OvsdbBridge ovsdbBridge = getOvsdbBridge(row);
1419 if (ovsdbBridge != null) {
1420 ovsdbBridges.add(ovsdbBridge);
1421 }
1422 }
1423 return ovsdbBridges;
1424 }
1425
1426 @Override
andreaed976a42015-10-05 14:38:25 -07001427 public Set<ControllerInfo> getControllers(DeviceId openflowDeviceId) {
Jonathan Hart51539b82015-10-29 09:53:04 -07001428 Uuid bridgeUuid = getBridgeUuid(openflowDeviceId);
andreaed976a42015-10-05 14:38:25 -07001429 if (bridgeUuid == null) {
1430 log.warn("bad bridge Uuid");
1431 return null;
1432 }
1433 List<Controller> controllers = getControllers(bridgeUuid);
1434 if (controllers == null) {
1435 log.warn("bad list of controllers");
1436 return null;
1437 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001438 return controllers.stream().map(controller -> new ControllerInfo(
1439 (String) controller.getTargetColumn()
1440 .data())).collect(Collectors.toSet());
andreaed976a42015-10-05 14:38:25 -07001441 }
1442
Jonathan Hart51539b82015-10-29 09:53:04 -07001443 private List<Controller> getControllers(Uuid bridgeUuid) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001444 DatabaseSchema dbSchema = schema.get(DATABASENAME);
andreaed976a42015-10-05 14:38:25 -07001445 if (dbSchema == null) {
1446 return null;
1447 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001448 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
andreaed976a42015-10-05 14:38:25 -07001449 if (rowStore == null) {
1450 log.debug("There is no bridge table");
1451 return null;
1452 }
1453
1454 Row bridgeRow = rowStore.getRow(bridgeUuid.value());
1455 Bridge bridge = (Bridge) TableGenerator.
1456 getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
1457
1458 //FIXME remove log
1459 log.warn("type of controller column", bridge.getControllerColumn()
1460 .data().getClass());
Jonathan Hart51539b82015-10-29 09:53:04 -07001461 Set<Uuid> controllerUuids = (Set<Uuid>) ((OvsdbSet) bridge
andreaed976a42015-10-05 14:38:25 -07001462 .getControllerColumn().data()).set();
andreaed976a42015-10-05 14:38:25 -07001463
Hyunsun Moon1251e192016-06-07 16:57:05 -07001464 OvsdbRowStore controllerRowStore = getRowStore(DATABASENAME, CONTROLLER);
andreaed976a42015-10-05 14:38:25 -07001465 if (controllerRowStore == null) {
1466 log.debug("There is no controller table");
1467 return null;
1468 }
1469
1470 List<Controller> ovsdbControllers = new ArrayList<>();
1471 ConcurrentMap<String, Row> controllerTableRows = controllerRowStore.getRowStore();
1472 controllerTableRows.forEach((key, row) -> {
Jonathan Hart51539b82015-10-29 09:53:04 -07001473 if (!controllerUuids.contains(Uuid.uuid(key))) {
andreaed976a42015-10-05 14:38:25 -07001474 return;
1475 }
1476 Controller controller = (Controller) TableGenerator
1477 .getTable(dbSchema, row, OvsdbTable.CONTROLLER);
1478 ovsdbControllers.add(controller);
1479 });
1480 return ovsdbControllers;
1481 }
1482
1483
Jonathan Hart51539b82015-10-29 09:53:04 -07001484 private Uuid getBridgeUuid(DeviceId openflowDeviceId) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001485 DatabaseSchema dbSchema = schema.get(DATABASENAME);
andreaed976a42015-10-05 14:38:25 -07001486 if (dbSchema == null) {
1487 return null;
1488 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001489 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
andreaed976a42015-10-05 14:38:25 -07001490 if (rowStore == null) {
1491 log.debug("There is no bridge table");
1492 return null;
1493 }
1494
1495 ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
Jonathan Hart51539b82015-10-29 09:53:04 -07001496 final AtomicReference<Uuid> uuid = new AtomicReference<>();
andreaed976a42015-10-05 14:38:25 -07001497 for (Map.Entry<String, Row> entry : bridgeTableRows.entrySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001498 Bridge bridge = (Bridge) TableGenerator.getTable(
1499 dbSchema,
1500 entry.getValue(),
1501 OvsdbTable.BRIDGE);
1502
1503 if (matchesDpid(bridge, openflowDeviceId)) {
Jonathan Hart51539b82015-10-29 09:53:04 -07001504 uuid.set(Uuid.uuid(entry.getKey()));
andreaed976a42015-10-05 14:38:25 -07001505 break;
1506 }
1507 }
1508 if (uuid.get() == null) {
1509 log.debug("There is no bridge for {}", openflowDeviceId);
1510 }
1511 return uuid.get();
andreaed976a42015-10-05 14:38:25 -07001512 }
1513
1514 private static boolean matchesDpid(Bridge b, DeviceId deviceId) {
1515 String ofDpid = deviceId.toString().replace("of:", "");
1516 Set ofDeviceIds = ((OvsdbSet) b.getDatapathIdColumn().data()).set();
1517 //TODO Set<String>
1518 return ofDeviceIds.contains(ofDpid);
1519 }
1520
1521 @Override
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001522 public Set<OvsdbPort> getPorts() {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001523 Set<OvsdbPort> ovsdbPorts = new HashSet<>();
1524 OvsdbTableStore tableStore = getTableStore(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001525 if (tableStore == null) {
1526 return null;
1527 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001528 OvsdbRowStore rowStore = tableStore.getRows(INTERFACE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001529 if (rowStore == null) {
1530 return null;
1531 }
1532 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1533 for (String uuid : rows.keySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001534 Row row = getRow(DATABASENAME, INTERFACE, uuid);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001535 OvsdbPort ovsdbPort = getOvsdbPort(row);
1536 if (ovsdbPort != null) {
1537 ovsdbPorts.add(ovsdbPort);
1538 }
1539 }
1540 return ovsdbPorts;
1541 }
1542
1543 @Override
1544 public DatabaseSchema getDatabaseSchema(String dbName) {
1545 return schema.get(dbName);
1546 }
1547
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001548 private OvsdbPort getOvsdbPort(Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001549 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001550 Interface intf = (Interface) TableGenerator
1551 .getTable(dbSchema, row, OvsdbTable.INTERFACE);
1552 if (intf == null) {
1553 return null;
1554 }
1555 long ofPort = getOfPort(intf);
1556 String portName = intf.getName();
1557 if ((ofPort < 0) || (portName == null)) {
1558 return null;
1559 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001560 return new OvsdbPort(new OvsdbPortNumber(ofPort), new OvsdbPortName(portName));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001561 }
1562
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001563 private OvsdbBridge getOvsdbBridge(Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001564 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
1565 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, row, OvsdbTable.BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001566 if (bridge == null) {
1567 return null;
1568 }
1569
1570 OvsdbSet datapathIdSet = (OvsdbSet) bridge.getDatapathIdColumn().data();
1571 @SuppressWarnings("unchecked")
1572 Set<String> datapathIds = datapathIdSet.set();
Jon Hallcbd1b392017-01-18 20:15:44 -08001573 if (datapathIds == null || datapathIds.isEmpty()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001574 return null;
1575 }
1576 String datapathId = (String) datapathIds.toArray()[0];
1577 String bridgeName = bridge.getName();
1578 if ((datapathId == null) || (bridgeName == null)) {
1579 return null;
1580 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001581 return OvsdbBridge.builder().name(bridgeName).datapathId(datapathId).build();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001582 }
1583
Frank Wange11a98d2016-10-26 17:04:03 +08001584 private OvsdbQos getOvsdbQos(Row row) {
1585 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
1586 Qos qos = (Qos) TableGenerator.getTable(dbSchema, row, OvsdbTable.QOS);
1587 if (qos == null) {
1588 return null;
1589 }
1590
1591 String type = (String) qos.getTypeColumn().data();
1592 Map<String, String> otherConfigs;
1593 Map<String, String> externalIds;
1594 Map<Long, String> queues;
1595
1596 otherConfigs = ((OvsdbMap) qos.getOtherConfigColumn().data()).map();
1597 externalIds = ((OvsdbMap) qos.getExternalIdsColumn().data()).map();
1598 queues = ((OvsdbMap) qos.getQueuesColumn().data()).map();
1599 return OvsdbQos.builder().qosType(type).
1600 queues(queues).otherConfigs(otherConfigs).
1601 externalIds(externalIds).build();
1602 }
1603
1604 private OvsdbQueue getOvsdbQueue(Row row) {
1605 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
1606 Queue queue = (Queue) TableGenerator.getTable(dbSchema, row, OvsdbTable.QUEUE);
1607 if (queue == null) {
1608 return null;
1609 }
1610
1611 OvsdbSet dscpOvsdbSet = ((OvsdbSet) queue.getDscpColumn().data());
1612 @SuppressWarnings("unchecked")
1613 Set<String> dscpSet = dscpOvsdbSet.set();
1614 Long dscp = null;
1615 if (dscpSet != null && !dscpSet.isEmpty()) {
1616 dscp = Long.valueOf((String) dscpSet.toArray()[0]);
1617 }
1618
1619 Map<String, String> otherConfigs;
1620 Map<String, String> externalIds;
1621
1622 otherConfigs = ((OvsdbMap) queue.getOtherConfigColumn().data()).map();
1623 externalIds = ((OvsdbMap) queue.getExternalIdsColumn().data()).map();
1624 return OvsdbQueue.builder().dscp(dscp).
1625 otherConfigs(otherConfigs).externalIds(externalIds).build();
1626 }
1627
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001628 private long getOfPort(Interface intf) {
1629 OvsdbSet ofPortSet = (OvsdbSet) intf.getOpenFlowPortColumn().data();
1630 @SuppressWarnings("unchecked")
1631 Set<Integer> ofPorts = ofPortSet.set();
Jon Hallcbd1b392017-01-18 20:15:44 -08001632 if (ofPorts == null || ofPorts.isEmpty()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001633 log.debug("The ofport is null in {}", intf.getName());
1634 return -1;
1635 }
1636 // return (long) ofPorts.toArray()[0];
1637 Iterator<Integer> it = ofPorts.iterator();
1638 return Long.parseLong(it.next().toString());
1639 }
CNluciusa66c3972015-09-06 20:31:29 +08001640
1641 @Override
1642 public Set<OvsdbPort> getLocalPorts(Iterable<String> ifaceids) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001643 Set<OvsdbPort> ovsdbPorts = new HashSet<>();
1644 OvsdbTableStore tableStore = getTableStore(DATABASENAME);
CNluciusa66c3972015-09-06 20:31:29 +08001645 if (tableStore == null) {
1646 return null;
1647 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001648 OvsdbRowStore rowStore = tableStore.getRows(INTERFACE);
CNluciusa66c3972015-09-06 20:31:29 +08001649 if (rowStore == null) {
1650 return null;
1651 }
1652 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1653 for (String uuid : rows.keySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001654 Row row = getRow(DATABASENAME, INTERFACE, uuid);
1655 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
CNluciusa66c3972015-09-06 20:31:29 +08001656 Interface intf = (Interface) TableGenerator
1657 .getTable(dbSchema, row, OvsdbTable.INTERFACE);
1658 if (intf == null || getIfaceid(intf) == null) {
1659 continue;
1660 }
1661 String portName = intf.getName();
Hyunsun Moon1251e192016-06-07 16:57:05 -07001662 if (portName == null) {
1663 continue;
1664 }
CNluciusa66c3972015-09-06 20:31:29 +08001665 Set<String> ifaceidSet = Sets.newHashSet(ifaceids);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001666 if (portName.startsWith(TYPEVXLAN) || !ifaceidSet.contains(getIfaceid(intf))) {
CNluciusa66c3972015-09-06 20:31:29 +08001667 continue;
1668 }
1669 long ofPort = getOfPort(intf);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001670 if (ofPort < 0) {
CNluciusa66c3972015-09-06 20:31:29 +08001671 continue;
1672 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001673 ovsdbPorts.add(new OvsdbPort(new OvsdbPortNumber(ofPort),
1674 new OvsdbPortName(portName)));
CNluciusa66c3972015-09-06 20:31:29 +08001675 }
1676 return ovsdbPorts;
1677 }
1678
1679 private String getIfaceid(Interface intf) {
1680 OvsdbMap ovsdbMap = (OvsdbMap) intf.getExternalIdsColumn().data();
1681 @SuppressWarnings("unchecked")
1682 Map<String, String> externalIds = ovsdbMap.map();
1683 if (externalIds.isEmpty()) {
1684 log.warn("The external_ids is null");
1685 return null;
1686 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001687 String ifaceid = externalIds.get(EXTERNAL_ID_INTERFACE_ID);
CNluciusa66c3972015-09-06 20:31:29 +08001688 if (ifaceid == null) {
1689 log.warn("The ifaceid is null");
1690 return null;
1691 }
1692 return ifaceid;
1693 }
Hyunsun Moon5fb20a52015-09-25 17:02:33 -07001694
1695 @Override
1696 public void disconnect() {
1697 channel.disconnect();
1698 this.agent.removeConnectedNode(nodeId);
1699 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001700}