Small fix to handle the fact that ovsdb sometimes returns ofport of -1
[ovsdb.git] / southbound / southbound-impl / src / main / java / org / opendaylight / ovsdb / southbound / transactions / md / OvsdbPortUpdateCommand.java
1 /*
2  * Copyright (c) 2014 Intel Corp. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.ovsdb.southbound.transactions.md;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17
18 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
21 import org.opendaylight.ovsdb.lib.message.TableUpdates;
22 import org.opendaylight.ovsdb.lib.notation.Column;
23 import org.opendaylight.ovsdb.lib.notation.UUID;
24 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
25 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
26 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
27 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
28 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
29 import org.opendaylight.ovsdb.schema.openvswitch.Port;
30 import org.opendaylight.ovsdb.southbound.OvsdbClientKey;
31 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.external.ids.attributes.ExternalIds;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.external.ids.attributes.ExternalIdsBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Trunks;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.TrunksBuilder;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
48 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 import com.google.common.base.Optional;
53
54 public class OvsdbPortUpdateCommand extends AbstractTransactionCommand {
55     private static final Logger LOG = LoggerFactory.getLogger(OvsdbPortUpdateCommand.class);
56
57     public OvsdbPortUpdateCommand(OvsdbClientKey key, TableUpdates updates,
58             DatabaseSchema dbSchema) {
59         super(key, updates, dbSchema);
60     }
61
62     @Override
63     public void execute(ReadWriteTransaction transaction) {
64         String bridgeName = null;
65         Collection<Port> portUpdatedRows = TyperUtils.extractRowsUpdated(
66                 Port.class, getUpdates(), getDbSchema()).values();
67         Collection<Bridge> bridgeUpdatedRows = TyperUtils.extractRowsUpdated(
68                 Bridge.class, getUpdates(), getDbSchema()).values();
69         for (Bridge bridge : bridgeUpdatedRows) {
70             Iterator<UUID> bridgePorts = bridge.getPortsColumn().getData()
71                     .iterator();
72             while (bridgePorts.hasNext()) {
73                 UUID portUUID = bridgePorts.next();
74                 for (Port port : portUpdatedRows) {
75                     if (portUUID.equals(port.getUuid())) {
76                         Collection<Long> vlanId = port.getTagColumn().getData();
77                         Set<Long> portTrunks = port.getTrunksColumn().getData();
78                         bridgeName = bridge.getName();
79                         NodeId bridgeId = SouthboundMapper.createManagedNodeId(
80                                 getKey(), new OvsdbBridgeName(bridgeName));
81                         final InstanceIdentifier<Node> nodePath = SouthboundMapper
82                                 .createInstanceIdentifier(bridgeId);
83                         Optional<Node> node = Optional.absent();
84                         try {
85                             node = transaction.read(
86                                     LogicalDatastoreType.OPERATIONAL, nodePath)
87                                     .checkedGet();
88                         } catch (final ReadFailedException e) {
89                             LOG.warn("Read Operational/DS for Node fail! {}",
90                                     nodePath, e);
91                         }
92                         if (node.isPresent()) {
93                             NodeBuilder nodeBuilder = new NodeBuilder();
94                             nodeBuilder.setNodeId(bridgeId);
95
96                             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder
97                                 = new OvsdbTerminationPointAugmentationBuilder();
98                             List<TerminationPoint> tpList = new ArrayList<TerminationPoint>();
99                             TerminationPointBuilder entry = new TerminationPointBuilder();
100                             TpId tpId = SouthboundMapper
101                                     .createTerminationPointId(getKey(),
102                                             new OvsdbBridgeName(bridgeName),
103                                             port.getName());
104                             entry.setTpId(tpId);
105                             ovsdbTerminationPointBuilder
106                                     .setName(port.getName());
107                             ovsdbTerminationPointBuilder.setPortUuid(new Uuid(
108                                     port.getUuid().toString()));
109                             if (vlanId.size() > 0) {
110                                 Iterator<Long> itr = vlanId.iterator();
111                                 // There are no loops here, just get the first element.
112                                 int id = itr.next().intValue();
113                                 ovsdbTerminationPointBuilder.setVlanTag(new VlanId(id));
114                             }
115                             List<Trunks> modelTrunks = new ArrayList<Trunks>();
116                             for (Long trunk: portTrunks) {
117                                 if (trunk != null) {
118                                     modelTrunks.add(new TrunksBuilder().setTrunk(new VlanId(trunk.intValue())).build());
119                                 }
120                             }
121                             ovsdbTerminationPointBuilder.setTrunks(modelTrunks);
122                             Column<GenericTableSchema, Set<UUID>> iface = port.getInterfacesColumn();
123                             Set<UUID> ifUuid = iface.getData();
124                             Collection<Interface> ifUpdateRows = TyperUtils.extractRowsUpdated(
125                                     Interface.class, getUpdates(),  getDbSchema()).values();
126                             for (UUID ifIter : ifUuid) {
127                                 for (Interface interfIter : ifUpdateRows) {
128                                     Column<GenericTableSchema, String> typeColumn = interfIter.getTypeColumn();
129                                     String type = typeColumn.getData();
130                                     if ((interfIter.getUuid()).equals(ifIter)) {
131                                         ovsdbTerminationPointBuilder.setInterfaceUuid(
132                                                 new Uuid(interfIter.getUuid().toString()));
133                                         ovsdbTerminationPointBuilder.setInterfaceType(
134                                                 SouthboundMapper.createInterfaceType(type));
135                                         Set<Long> ofPorts = interfIter.getOpenFlowPortColumn().getData();
136                                         if (ofPorts != null && !ofPorts.isEmpty()) {
137                                             Iterator<Long> ofPortsIter = ofPorts.iterator();
138                                             int ofPort = ofPortsIter.next().intValue();
139                                             if (ofPort >= 0) {
140                                                 ovsdbTerminationPointBuilder
141                                                     .setOfport(ofPort);
142                                             } else {
143                                                 LOG.debug("Received negative value for ofPort from ovsdb for {} {} {}",
144                                                         bridge.getName(), interfIter.getName(),ofPort);
145                                             }
146                                         }
147                                         Set<Long> ofPortRequests = interfIter
148                                                 .getOpenFlowPortRequestColumn().getData();
149                                         if (ofPortRequests != null && !ofPortRequests.isEmpty()) {
150                                             Iterator<Long> ofPortRequestsIter = ofPortRequests.iterator();
151                                             int ofPort = ofPortRequestsIter.next().intValue();
152                                             if (ofPort >= 0) {
153                                                 ovsdbTerminationPointBuilder
154                                                     .setOfportRequest(ofPort);
155                                             } else {
156                                                 LOG.debug("Received negative value for ofPort from ovsdb for {} {} {}",
157                                                         bridge.getName(), interfIter.getName(),ofPort);
158                                             }
159                                         }
160
161                                         Map<String, String> externalIds = interfIter.getExternalIdsColumn().getData();
162                                         if (externalIds != null && !externalIds.isEmpty()) {
163                                             Set<String> externalIdKeys = externalIds.keySet();
164                                             ArrayList<ExternalIds> externalIdsList = new ArrayList<ExternalIds>();
165                                             String externalIdValue;
166                                             for (String externalIdKey : externalIdKeys) {
167                                                 externalIdValue = externalIds.get(externalIdKey);
168                                                 if (externalIdKey != null && externalIdValue != null) {
169                                                     externalIdsList.add(new ExternalIdsBuilder()
170                                                             .setExternalIdKey(externalIdKey)
171                                                             .setExternalIdValue(externalIdValue).build());
172                                                 }
173                                             }
174                                             ovsdbTerminationPointBuilder.setExternalIds(externalIdsList);
175                                         }
176
177                                         break;
178                                     }
179                                 }
180                             }
181                             entry.addAugmentation(
182                                     OvsdbTerminationPointAugmentation.class,
183                                     ovsdbTerminationPointBuilder.build());
184
185                             tpList.add(entry.build());
186                             nodeBuilder.setTerminationPoint(tpList);
187                             nodeBuilder.addAugmentation(
188                                     OvsdbBridgeAugmentation.class,
189                                     node.get().getAugmentation(
190                                             OvsdbBridgeAugmentation.class));
191                             transaction.merge(LogicalDatastoreType.OPERATIONAL,
192                                     nodePath, nodeBuilder.build());
193                         }
194                     }
195                 }
196             }
197         }
198     }
199 }