7bfb9f0b178ebe53123331b4afd21a93bc725347
[ovsdb.git] / southbound / southbound-impl / src / main / java / org / opendaylight / ovsdb / southbound / transactions / md / OpenVSwitchUpdateCommand.java
1 /*
2  * Copyright (c) 2015 Inocybe inc. 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 package org.opendaylight.ovsdb.southbound.transactions.md;
9
10 import static org.opendaylight.ovsdb.southbound.SouthboundUtil.schemaMismatchLog;
11
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Map.Entry;
16 import java.util.NoSuchElementException;
17 import java.util.Set;
18
19 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.ovsdb.lib.error.SchemaVersionMismatchException;
22 import org.opendaylight.ovsdb.lib.message.TableUpdates;
23 import org.opendaylight.ovsdb.lib.notation.UUID;
24 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
25 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
26 import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
27 import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
28 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
29 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
30 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.DatapathTypeEntry;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.DatapathTypeEntryBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntry;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchExternalIds;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchExternalIdsBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchExternalIdsKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigsBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigsKey;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
51 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
52 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 public class OpenVSwitchUpdateCommand extends AbstractTransactionCommand {
57
58     private static final Logger LOG = LoggerFactory.getLogger(OpenVSwitchUpdateCommand.class);
59
60     public OpenVSwitchUpdateCommand(OvsdbConnectionInstance key, TableUpdates updates,
61             DatabaseSchema dbSchema) {
62         super(key, updates, dbSchema);
63     }
64
65     @Override
66     public void execute(ReadWriteTransaction transaction) {
67         Map<UUID, OpenVSwitch> updatedOpenVSwitchRows = TyperUtils
68                 .extractRowsUpdated(OpenVSwitch.class, getUpdates(),
69                         getDbSchema());
70         Map<UUID, OpenVSwitch> deletedOpenVSwitchRows = TyperUtils
71                 .extractRowsOld(OpenVSwitch.class, getUpdates(),
72                         getDbSchema());
73
74         for (Entry<UUID, OpenVSwitch> entry : updatedOpenVSwitchRows.entrySet()) {
75             OpenVSwitch openVSwitch = entry.getValue();
76             OpenVSwitch oldEntry = deletedOpenVSwitchRows.get(entry.getKey());
77             final InstanceIdentifier<Node> nodePath = getInstanceIdentifier(openVSwitch);
78
79             OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
80
81             setVersion(ovsdbNodeBuilder, openVSwitch);
82             setDataPathTypes(ovsdbNodeBuilder, openVSwitch);
83             setInterfaceTypes(ovsdbNodeBuilder, openVSwitch);
84             setExternalIds(transaction, ovsdbNodeBuilder, oldEntry, openVSwitch);
85             setOtherConfig(transaction, ovsdbNodeBuilder, oldEntry, openVSwitch);
86             ovsdbNodeBuilder.setConnectionInfo(getConnectionInfo());
87
88             NodeBuilder nodeBuilder = new NodeBuilder();
89             nodeBuilder.setNodeId(getNodeId(openVSwitch));
90             nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class,
91                     ovsdbNodeBuilder.build());
92             transaction.merge(LogicalDatastoreType.OPERATIONAL, nodePath,
93                     nodeBuilder.build());
94         }
95     }
96
97     private void setOtherConfig(ReadWriteTransaction transaction,
98             OvsdbNodeAugmentationBuilder ovsdbNodeBuilder, OpenVSwitch oldEntry, OpenVSwitch openVSwitch) {
99         Map<String, String> oldOtherConfigs = null;
100         Map<String, String> otherConfigs = null;
101
102         if (openVSwitch.getOtherConfigColumn() != null) {
103             otherConfigs = openVSwitch.getOtherConfigColumn().getData();
104         }
105         if (oldEntry != null && oldEntry.getOtherConfigColumn() != null) {
106             oldOtherConfigs = oldEntry.getOtherConfigColumn().getData();
107         }
108         if ((oldOtherConfigs == null) || oldOtherConfigs.isEmpty()) {
109             setNewOtherConfigs(ovsdbNodeBuilder, otherConfigs);
110         } else if (otherConfigs != null && !otherConfigs.isEmpty()) {
111             removeOldConfigs(transaction, oldOtherConfigs, openVSwitch);
112             setNewOtherConfigs(ovsdbNodeBuilder, otherConfigs);
113         }
114     }
115
116     private void removeOldConfigs(ReadWriteTransaction transaction, Map<String, String> oldOtherConfigs,
117             OpenVSwitch ovs) {
118         InstanceIdentifier<OvsdbNodeAugmentation> nodeAugmentataionIid = InstanceIdentifier
119                 .create(NetworkTopology.class)
120                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
121                 .child(Node.class, new NodeKey(getNodeId(ovs))).augmentation(OvsdbNodeAugmentation.class);
122         Set<String> otherConfigKeys = oldOtherConfigs.keySet();
123         for (String otherConfigKey : otherConfigKeys) {
124             KeyedInstanceIdentifier<OpenvswitchOtherConfigs, OpenvswitchOtherConfigsKey> externalIid =
125                     nodeAugmentataionIid
126                     .child(OpenvswitchOtherConfigs.class, new OpenvswitchOtherConfigsKey(otherConfigKey));
127             transaction.delete(LogicalDatastoreType.OPERATIONAL, externalIid);
128         }
129     }
130
131     private void setNewOtherConfigs(OvsdbNodeAugmentationBuilder ovsdbNodeBuilder,
132             Map<String, String> otherConfigs) {
133         Set<String> otherConfigKeys = otherConfigs.keySet();
134         List<OpenvswitchOtherConfigs> otherConfigsList = new ArrayList<>();
135         String otherConfigValue;
136         for (String otherConfigKey : otherConfigKeys) {
137             otherConfigValue = otherConfigs.get(otherConfigKey);
138             if (otherConfigKey != null && otherConfigValue != null) {
139                 otherConfigsList.add(new OpenvswitchOtherConfigsBuilder().setOtherConfigKey(otherConfigKey)
140                         .setOtherConfigValue(otherConfigValue).build());
141             }
142         }
143         ovsdbNodeBuilder.setOpenvswitchOtherConfigs(otherConfigsList);
144     }
145
146     private void setExternalIds(ReadWriteTransaction transaction,
147             OvsdbNodeAugmentationBuilder ovsdbNodeBuilder, OpenVSwitch oldEntry, OpenVSwitch openVSwitch) {
148         Map<String, String> oldExternalIds = null;
149         Map<String, String> externalIds = null;
150
151         if (openVSwitch.getExternalIdsColumn() != null) {
152             externalIds = openVSwitch.getExternalIdsColumn().getData();
153         }
154         if (oldEntry != null && oldEntry.getExternalIdsColumn() != null) {
155             oldExternalIds = oldEntry.getExternalIdsColumn().getData();
156         }
157         if ((oldExternalIds == null) || oldExternalIds.isEmpty()) {
158             setNewExternalIds(ovsdbNodeBuilder, externalIds);
159         } else if (externalIds != null && !externalIds.isEmpty()) {
160             removeExternalIds(transaction, oldExternalIds, openVSwitch);
161             setNewExternalIds(ovsdbNodeBuilder, externalIds);
162         }
163     }
164
165     private void removeExternalIds(ReadWriteTransaction transaction, Map<String, String> oldExternalIds,
166             OpenVSwitch ovs) {
167         InstanceIdentifier<OvsdbNodeAugmentation> nodeAugmentataionIid = InstanceIdentifier
168                 .create(NetworkTopology.class)
169                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
170                 .child(Node.class, new NodeKey(getNodeId(ovs))).augmentation(OvsdbNodeAugmentation.class);
171         Set<String> externalIdKeys = oldExternalIds.keySet();
172         for (String externalIdKey : externalIdKeys) {
173             KeyedInstanceIdentifier<OpenvswitchExternalIds, OpenvswitchExternalIdsKey> externalIid =
174                     nodeAugmentataionIid
175                     .child(OpenvswitchExternalIds.class, new OpenvswitchExternalIdsKey(externalIdKey));
176             transaction.delete(LogicalDatastoreType.OPERATIONAL, externalIid);
177         }
178     }
179
180     private void setNewExternalIds(OvsdbNodeAugmentationBuilder ovsdbNodeBuilder,
181             Map<String, String> externalIds) {
182         Set<String> externalIdKeys = externalIds.keySet();
183         List<OpenvswitchExternalIds> externalIdsList = new ArrayList<>();
184         String externalIdValue;
185         for (String externalIdKey : externalIdKeys) {
186             externalIdValue = externalIds.get(externalIdKey);
187             if (externalIdKey != null && externalIdValue != null) {
188                 externalIdsList.add(new OpenvswitchExternalIdsBuilder().setExternalIdKey(externalIdKey)
189                         .setExternalIdValue(externalIdValue).build());
190             }
191         }
192         ovsdbNodeBuilder.setOpenvswitchExternalIds(externalIdsList);
193     }
194
195     private void setInterfaceTypes(
196             OvsdbNodeAugmentationBuilder ovsdbNodeBuilder,
197             OpenVSwitch openVSwitch) {
198         try {
199             Set<String> iftypes = openVSwitch.getIfaceTypesColumn().getData();
200             List<InterfaceTypeEntry> ifEntryList = new ArrayList<>();
201             for (String ifType : iftypes) {
202                 if (SouthboundMapper.createInterfaceType(ifType) != null) {
203                     InterfaceTypeEntry ifEntry = new InterfaceTypeEntryBuilder()
204                             .setInterfaceType(
205                                     SouthboundMapper.createInterfaceType(ifType))
206                             .build();
207                     ifEntryList.add(ifEntry);
208                 } else {
209                     LOG.warn("Interface type {} not present in model", ifType);
210                 }
211             }
212             ovsdbNodeBuilder.setInterfaceTypeEntry(ifEntryList);
213         } catch (SchemaVersionMismatchException e) {
214             schemaMismatchLog("iface_types", SouthboundConstants.OPEN_V_SWITCH, e);
215         }
216     }
217
218     private void setDataPathTypes(
219             OvsdbNodeAugmentationBuilder ovsdbNodeBuilder,
220             OpenVSwitch openVSwitch) {
221         try {
222             Set<String> dptypes = openVSwitch.getDatapathTypesColumn()
223                     .getData();
224             List<DatapathTypeEntry> dpEntryList = new ArrayList<>();
225             for (String dpType : dptypes) {
226                 if (SouthboundMapper.createDatapathType(dpType) != null) {
227                     DatapathTypeEntry dpEntry = new DatapathTypeEntryBuilder()
228                             .setDatapathType(
229                                     SouthboundMapper.createDatapathType(dpType))
230                             .build();
231                     dpEntryList.add(dpEntry);
232                 } else {
233                     LOG.warn("Datapath type {} not present in model", dpType);
234                 }
235             }
236             ovsdbNodeBuilder.setDatapathTypeEntry(dpEntryList);
237         } catch (SchemaVersionMismatchException e) {
238             schemaMismatchLog("datapath_types", SouthboundConstants.OPEN_V_SWITCH, e);
239         }
240     }
241
242     private void setVersion(OvsdbNodeAugmentationBuilder ovsdbNodeBuilder,
243             OpenVSwitch openVSwitch) {
244         try {
245             ovsdbNodeBuilder.setOvsVersion(openVSwitch.getOvsVersionColumn().getData().iterator().next());
246         } catch (NoSuchElementException e) {
247             LOG.debug("ovs_version is not set for this switch",e);
248         }
249     }
250
251     private InstanceIdentifier<Node> getInstanceIdentifier(OpenVSwitch ovs) {
252         if (ovs.getExternalIdsColumn() != null
253                 && ovs.getExternalIdsColumn().getData() != null
254                 && ovs.getExternalIdsColumn().getData().containsKey(SouthboundConstants.IID_EXTERNAL_ID_KEY)) {
255             String iidString = ovs.getExternalIdsColumn().getData().get(SouthboundConstants.IID_EXTERNAL_ID_KEY);
256             InstanceIdentifier<Node> iid =
257                    (InstanceIdentifier<Node>) SouthboundUtil.deserializeInstanceIdentifier(iidString);
258             getOvsdbConnectionInstance().setInstanceIdentifier(iid);
259         } else {
260             String nodeString = SouthboundConstants.OVSDB_URI_PREFIX + "://" + SouthboundConstants.UUID + "/"
261                     + ovs.getUuid().toString();
262             NodeId nodeId = new NodeId(new Uri(nodeString));
263             NodeKey nodeKey = new NodeKey(nodeId);
264             InstanceIdentifier<Node> iid = InstanceIdentifier.builder(NetworkTopology.class)
265                     .child(Topology.class,new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
266                     .child(Node.class,nodeKey)
267                     .build();
268             getOvsdbConnectionInstance().setInstanceIdentifier(iid);
269         }
270         return getOvsdbConnectionInstance().getInstanceIdentifier();
271     }
272
273     private NodeId getNodeId(OpenVSwitch ovs) {
274         NodeKey nodeKey = getInstanceIdentifier(ovs).firstKeyOf(Node.class, NodeKey.class);
275         return nodeKey.getNodeId();
276     }
277 }