2 * Copyright (c) 2015, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
9 package org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.Sets;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance;
24 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundMapper;
25 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
26 import org.opendaylight.ovsdb.lib.message.TableUpdates;
27 import org.opendaylight.ovsdb.lib.notation.UUID;
28 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
29 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
30 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalSwitch;
31 import org.opendaylight.ovsdb.schema.hardwarevtep.Tunnel;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalRef;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalSwitchRef;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentationBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Switches;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.SwitchesBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.ManagementIps;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.ManagementIpsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.ManagementIpsKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.SwitchFaultStatus;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.SwitchFaultStatusBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.SwitchFaultStatusKey;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIps;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIpsBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIpsKey;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
57 import org.opendaylight.yangtools.yang.binding.DataObject;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
62 public class HwvtepPhysicalSwitchUpdateCommand extends AbstractTransactionCommand {
64 private static final Logger LOG = LoggerFactory.getLogger(HwvtepPhysicalSwitchUpdateCommand.class);
65 private final Map<UUID, PhysicalSwitch> updatedPSRows;
66 private Map<UUID, Tunnel> updatedTunnelRows;
67 private final Map<UUID, PhysicalSwitch> oldPSRows;
69 public HwvtepPhysicalSwitchUpdateCommand(HwvtepConnectionInstance key, TableUpdates updates,
70 DatabaseSchema dbSchema) {
71 super(key, updates, dbSchema);
72 updatedPSRows = TyperUtils.extractRowsUpdated(PhysicalSwitch.class, getUpdates(), getDbSchema());
73 oldPSRows = TyperUtils.extractRowsOld(PhysicalSwitch.class, getUpdates(), getDbSchema());
75 updatedTunnelRows = TyperUtils.extractRowsUpdated(Tunnel.class, getUpdates(), getDbSchema());
76 } catch (IllegalArgumentException e) {
77 LOG.debug("Tunnel Table not supported on this HWVTEP device", e);
82 public void execute(ReadWriteTransaction transaction) {
83 for (Map.Entry<UUID, PhysicalSwitch> entry : updatedPSRows.entrySet()) {
84 updatePhysicalSwitch(transaction, entry.getKey(), entry.getValue());
88 private void updatePhysicalSwitch(ReadWriteTransaction transaction, UUID uuid, PhysicalSwitch phySwitch) {
89 final InstanceIdentifier<Node> connectionIId = getOvsdbConnectionInstance().getInstanceIdentifier();
90 //TODO remove this read
91 Optional<Node> connection = HwvtepSouthboundUtil.readNode(transaction, connectionIId);
92 if (connection.isPresent()) {
93 LOG.debug("Connection {} is present", connection);
94 // Update the connection node to let it know it manages this
96 Node connectionNode = buildConnectionNode(phySwitch);
97 transaction.merge(LogicalDatastoreType.OPERATIONAL, connectionIId, connectionNode);
99 // Update the Physical Switch with whatever data we are getting
100 InstanceIdentifier<Node> psIid = getInstanceIdentifier(phySwitch);
101 Node psNode = buildPhysicalSwitchNode(connection.get(), phySwitch);
102 transaction.merge(LogicalDatastoreType.OPERATIONAL, psIid, psNode);
104 PhysicalSwitch oldPSwitch = oldPSRows.get(uuid);
105 updateTunnelIps(phySwitch, oldPSwitch, transaction);
107 getOvsdbConnectionInstance().getDeviceInfo().putPhysicalSwitch(phySwitch.getUuid(), phySwitch);
108 getDeviceInfo().updateDeviceOperData(Node.class, psIid, phySwitch.getUuid(), phySwitch);
109 // TODO: Delete entries that are no longer needed
110 // TODO: Deletion of tunnels
111 // TODO: Deletion of Tunnel BFD config and params
112 //Deleting old switch fault status entries
113 deleteEntries(transaction, getSwitchFaultStatusToRemove(psIid,phySwitch));
117 private InstanceIdentifier<TunnelIps> getTunnelIpIid(final String tunnelIp,
118 final InstanceIdentifier<Node> psIid) {
119 IpAddress ip = IpAddressBuilder.getDefaultInstance(tunnelIp);
120 TunnelIps tunnelIps = new TunnelIpsBuilder().withKey(new TunnelIpsKey(ip)).setTunnelIpsKey(ip).build();
121 return psIid.augmentation(PhysicalSwitchAugmentation.class).child(TunnelIps.class, tunnelIps.key());
124 private void updateTunnelIps(@NonNull final PhysicalSwitch newPSwitch, @Nullable final PhysicalSwitch oldPSwitch,
125 final ReadWriteTransaction transaction) {
126 Set<String> oldTunnelIps = oldPSwitch != null && oldPSwitch.getTunnelIpsColumn() != null ? oldPSwitch
127 .getTunnelIpsColumn().getData() : Collections.emptySet();
128 Set<String> newTunelIps = newPSwitch.getTunnelIpsColumn() != null ? newPSwitch
129 .getTunnelIpsColumn().getData() : Collections.emptySet();
131 Set<String> addedTunnelIps = Sets.difference(newTunelIps, oldTunnelIps);
132 Set<String> removedTunnelIps = Sets.difference(oldTunnelIps, newTunelIps);
134 InstanceIdentifier<Node> psIid = getInstanceIdentifier(newPSwitch);
135 for (String tunnelIp : removedTunnelIps) {
136 InstanceIdentifier<TunnelIps> tunnelIpsInstanceIdentifier = getTunnelIpIid(tunnelIp, psIid);
137 transaction.delete(LogicalDatastoreType.OPERATIONAL, tunnelIpsInstanceIdentifier);
139 for (String tunnelIp : addedTunnelIps) {
140 IpAddress ip = IpAddressBuilder.getDefaultInstance(tunnelIp);
141 InstanceIdentifier<TunnelIps> tunnelIpsInstanceIdentifier = getTunnelIpIid(tunnelIp, psIid);
142 TunnelIps tunnelIps = new TunnelIpsBuilder().withKey(new TunnelIpsKey(ip)).setTunnelIpsKey(ip).build();
143 transaction.put(LogicalDatastoreType.OPERATIONAL, tunnelIpsInstanceIdentifier, tunnelIps, true);
147 private Node buildPhysicalSwitchNode(Node node, PhysicalSwitch phySwitch) {
148 NodeBuilder psNodeBuilder = new NodeBuilder();
149 NodeId psNodeId = getNodeId(phySwitch);
150 psNodeBuilder.setNodeId(psNodeId);
151 PhysicalSwitchAugmentationBuilder psAugmentationBuilder = new PhysicalSwitchAugmentationBuilder();
152 psAugmentationBuilder.setPhysicalSwitchUuid(new Uuid(phySwitch.getUuid().toString()));
153 setManagedBy(psAugmentationBuilder);
154 setPhysicalSwitchId(psAugmentationBuilder, phySwitch);
155 setManagementIps(psAugmentationBuilder, phySwitch);
156 setTunnels(psAugmentationBuilder, phySwitch);
157 setSwitchFaultStatus(psAugmentationBuilder, phySwitch);
159 psNodeBuilder.addAugmentation(PhysicalSwitchAugmentation.class, psAugmentationBuilder.build());
161 LOG.trace("Built with the intent to store PhysicalSwitch data {}", psAugmentationBuilder.build());
162 return psNodeBuilder.build();
165 private void setTunnels(PhysicalSwitchAugmentationBuilder psAugmentationBuilder, PhysicalSwitch phySwitch) {
166 if (updatedTunnelRows != null && phySwitch.getTunnels() != null && phySwitch.getTunnels().getData() != null
167 && !phySwitch.getTunnels().getData().isEmpty()) {
168 // Nothing to do but update deviceInfo cache
169 for (UUID uuid: phySwitch.getTunnels().getData()) {
170 getOvsdbConnectionInstance().getDeviceInfo().putPhysicalSwitchForTunnel(uuid, phySwitch.getUuid());
175 private void setManagedBy(PhysicalSwitchAugmentationBuilder psAugmentationBuilder) {
176 InstanceIdentifier<Node> connectionNodePath = getOvsdbConnectionInstance().getInstanceIdentifier();
177 psAugmentationBuilder.setManagedBy(new HwvtepGlobalRef(connectionNodePath));
180 private void setPhysicalSwitchId(PhysicalSwitchAugmentationBuilder psAugmentationBuilder,
181 PhysicalSwitch phySwitch) {
182 if (phySwitch.getName() != null) {
183 psAugmentationBuilder.setHwvtepNodeName(new HwvtepNodeName(phySwitch.getName()));
185 if (phySwitch.getDescription() != null) {
186 psAugmentationBuilder.setHwvtepNodeDescription(phySwitch.getDescription());
190 private void setManagementIps(PhysicalSwitchAugmentationBuilder psAugmentationBuilder,
191 PhysicalSwitch phySwitch) {
192 if (phySwitch.getManagementIpsColumn() != null && phySwitch.getManagementIpsColumn().getData() != null
193 && !phySwitch.getManagementIpsColumn().getData().isEmpty()) {
194 List<ManagementIps> mgmtIps = new ArrayList<>();
195 for (String mgmtIp : phySwitch.getManagementIpsColumn().getData()) {
196 IpAddress ip = IpAddressBuilder.getDefaultInstance(mgmtIp);
198 new ManagementIpsBuilder().withKey(new ManagementIpsKey(ip)).setManagementIpsKey(ip).build());
200 psAugmentationBuilder.setManagementIps(mgmtIps);
204 private Node buildConnectionNode(PhysicalSwitch phySwitch) {
205 // Update node with PhysicalSwitch reference
206 NodeBuilder connectionNode = new NodeBuilder();
207 connectionNode.setNodeId(getOvsdbConnectionInstance().getNodeId());
209 HwvtepGlobalAugmentationBuilder hgAugmentationBuilder = new HwvtepGlobalAugmentationBuilder();
210 List<Switches> switches = new ArrayList<>();
211 InstanceIdentifier<Node> switchIid =
212 HwvtepSouthboundMapper.createInstanceIdentifier(getOvsdbConnectionInstance(), phySwitch);
213 hgAugmentationBuilder.setSwitches(switches);
214 Switches physicalSwitch = new SwitchesBuilder().setSwitchRef(new HwvtepPhysicalSwitchRef(switchIid)).build();
215 switches.add(physicalSwitch);
217 connectionNode.addAugmentation(HwvtepGlobalAugmentation.class, hgAugmentationBuilder.build());
219 LOG.debug("Update node with physicalswitch ref {}", hgAugmentationBuilder.getSwitches().iterator().next());
220 return connectionNode.build();
223 private InstanceIdentifier<Node> getInstanceIdentifier(PhysicalSwitch phySwitch) {
224 return HwvtepSouthboundMapper.createInstanceIdentifier(getOvsdbConnectionInstance(), phySwitch);
227 private NodeId getNodeId(PhysicalSwitch phySwitch) {
228 NodeKey nodeKey = getInstanceIdentifier(phySwitch).firstKeyOf(Node.class);
229 return nodeKey.getNodeId();
232 private <T extends DataObject> void deleteEntries(ReadWriteTransaction transaction,
233 List<InstanceIdentifier<T>> entryIids) {
234 for (InstanceIdentifier<T> entryIid : entryIids) {
235 transaction.delete(LogicalDatastoreType.OPERATIONAL, entryIid);
239 private List<InstanceIdentifier<SwitchFaultStatus>> getSwitchFaultStatusToRemove(InstanceIdentifier<Node> psIid,
240 PhysicalSwitch phySwitch) {
241 Preconditions.checkNotNull(psIid);
242 Preconditions.checkNotNull(phySwitch);
243 List<InstanceIdentifier<SwitchFaultStatus>> result = new ArrayList<>();
244 PhysicalSwitch oldSwitch = oldPSRows.get(phySwitch.getUuid());
245 if (oldSwitch != null && oldSwitch.getSwitchFaultStatusColumn() != null) {
246 for (String switchFltStat : oldSwitch.getSwitchFaultStatusColumn().getData()) {
247 if (phySwitch.getSwitchFaultStatusColumn() == null
248 || !phySwitch.getSwitchFaultStatusColumn().getData().contains(switchFltStat)) {
249 InstanceIdentifier<SwitchFaultStatus> iid = psIid.augmentation(PhysicalSwitchAugmentation.class)
250 .child(SwitchFaultStatus.class, new SwitchFaultStatusKey(switchFltStat));
258 private void setSwitchFaultStatus(PhysicalSwitchAugmentationBuilder psAugmentationBuilder,
259 PhysicalSwitch phySwitch) {
260 if (phySwitch.getSwitchFaultStatusColumn() != null && phySwitch.getSwitchFaultStatusColumn().getData() != null
261 && !phySwitch.getSwitchFaultStatusColumn().getData().isEmpty()) {
262 List<SwitchFaultStatus> switchFaultStatusLst = new ArrayList<>();
263 for (String switchFaultStatus : phySwitch.getSwitchFaultStatusColumn().getData()) {
265 .add(new SwitchFaultStatusBuilder().withKey(new SwitchFaultStatusKey(switchFaultStatus))
266 .setSwitchFaultStatusKey(switchFaultStatus).build());
268 psAugmentationBuilder.setSwitchFaultStatus(switchFaultStatusLst);