added support for switch/port fault status for hwvtep schema changes.
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / transactions / md / HwvtepPhysicalSwitchUpdateCommand.java
1 /*
2  * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.hwvtepsouthbound.transactions.md;
10
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.Map;
14
15 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance;
18 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundMapper;
19 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
20 import org.opendaylight.ovsdb.lib.message.TableUpdates;
21 import org.opendaylight.ovsdb.lib.notation.UUID;
22 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
23 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
24 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalSwitch;
25 import org.opendaylight.ovsdb.schema.hardwarevtep.Tunnel;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalRef;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalSwitchRef;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentationBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Switches;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.SwitchesBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.ManagementIps;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.ManagementIpsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.ManagementIpsKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.SwitchFaultStatus;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.SwitchFaultStatusBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.SwitchFaultStatusKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIps;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIpsBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIpsKey;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
50 import org.opendaylight.yangtools.yang.binding.DataObject;
51 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55 import com.google.common.base.Optional;
56 import com.google.common.base.Preconditions;
57
58 public class HwvtepPhysicalSwitchUpdateCommand extends AbstractTransactionCommand {
59
60     private static final Logger LOG = LoggerFactory.getLogger(HwvtepPhysicalSwitchUpdateCommand.class);
61     private Map<UUID, PhysicalSwitch> updatedPSRows;
62     private Map<UUID, Tunnel> updatedTunnelRows;
63     private Map<UUID, PhysicalSwitch> oldPSRows;
64
65     public HwvtepPhysicalSwitchUpdateCommand(HwvtepConnectionInstance key, TableUpdates updates, DatabaseSchema dbSchema) {
66         super(key, updates, dbSchema);
67         updatedPSRows = TyperUtils.extractRowsUpdated(PhysicalSwitch.class, getUpdates(), getDbSchema());
68         oldPSRows = TyperUtils.extractRowsOld(PhysicalSwitch.class, getUpdates(), getDbSchema());
69         try {
70             updatedTunnelRows = TyperUtils.extractRowsUpdated(Tunnel.class, getUpdates(), getDbSchema());
71         } catch (IllegalArgumentException e) {
72             LOG.debug("Tunnel Table not supported on this HWVTEP device", e.getMessage());
73         }
74     }
75
76     @Override
77     public void execute(ReadWriteTransaction transaction) {
78         for (PhysicalSwitch physicalSwitch : updatedPSRows.values()) {
79             updatePhysicalSwitch(transaction, physicalSwitch);
80         }
81     }
82
83     private void updatePhysicalSwitch(ReadWriteTransaction transaction, PhysicalSwitch pSwitch) {
84         final InstanceIdentifier<Node> connectionIId = getOvsdbConnectionInstance().getInstanceIdentifier();
85         Optional<Node> connection = HwvtepSouthboundUtil.readNode(transaction, connectionIId);
86         if (connection.isPresent()) {
87             LOG.debug("Connection {} is present", connection);
88             // Update the connection node to let it know it manages this
89             // Physical Switch
90             Node connectionNode = buildConnectionNode(pSwitch);
91             transaction.merge(LogicalDatastoreType.OPERATIONAL, connectionIId, connectionNode);
92
93             // Update the Physical Switch with whatever data we are getting
94             InstanceIdentifier<Node> psIid = getInstanceIdentifier(pSwitch);
95             Node psNode = buildPhysicalSwitchNode(connection.get(), pSwitch);
96             transaction.merge(LogicalDatastoreType.OPERATIONAL, psIid, psNode);
97             getOvsdbConnectionInstance().getDeviceInfo().putPhysicalSwitch(pSwitch.getUuid(), pSwitch);
98             // TODO: Delete entries that are no longer needed
99             // TODO: Deletion of tunnels
100             // TODO: Deletion of Tunnel BFD config and params
101             //Deleting old switch fault status entries
102             deleteEntries(transaction, getSwitchFaultStatusToRemove(psIid,pSwitch));
103         }
104     }
105
106     private Node buildPhysicalSwitchNode(Node node, PhysicalSwitch pSwitch) {
107         NodeBuilder psNodeBuilder = new NodeBuilder();
108         NodeId psNodeId = getNodeId(pSwitch);
109         psNodeBuilder.setNodeId(psNodeId);
110         PhysicalSwitchAugmentationBuilder psAugmentationBuilder = new PhysicalSwitchAugmentationBuilder();
111         psAugmentationBuilder.setPhysicalSwitchUuid(new Uuid(pSwitch.getUuid().toString()));
112         setManagedBy(psAugmentationBuilder);
113         setPhysicalSwitchId(psAugmentationBuilder, pSwitch);
114         setManagementIps(psAugmentationBuilder, pSwitch);
115         setTunnelIps(psAugmentationBuilder, pSwitch);
116         setTunnels(psAugmentationBuilder, pSwitch);
117         setSwitchFaultStatus(psAugmentationBuilder, pSwitch);
118
119         psNodeBuilder.addAugmentation(PhysicalSwitchAugmentation.class, psAugmentationBuilder.build());
120
121         LOG.trace("Built with the intent to store PhysicalSwitch data {}", psAugmentationBuilder.build());
122         return psNodeBuilder.build();
123     }
124
125     private void setTunnels(PhysicalSwitchAugmentationBuilder psAugmentationBuilder, PhysicalSwitch pSwitch) {
126         if (updatedTunnelRows != null && pSwitch.getTunnels() != null && pSwitch.getTunnels().getData() != null
127                 && !pSwitch.getTunnels().getData().isEmpty()) {
128             // Nothing to do but update deviceInfo cache
129             for(UUID uuid: pSwitch.getTunnels().getData()) {
130                 getOvsdbConnectionInstance().getDeviceInfo().putPhysicalSwitchForTunnel(uuid, pSwitch.getUuid());
131             }
132         }
133     }
134
135     private void setManagedBy(PhysicalSwitchAugmentationBuilder psAugmentationBuilder) {
136         InstanceIdentifier<Node> connectionNodePath = getOvsdbConnectionInstance().getInstanceIdentifier();
137         psAugmentationBuilder.setManagedBy(new HwvtepGlobalRef(connectionNodePath));
138     }
139
140     private void setPhysicalSwitchId(PhysicalSwitchAugmentationBuilder psAugmentationBuilder, PhysicalSwitch pSwitch) {
141         if (pSwitch.getName() != null) {
142             psAugmentationBuilder.setHwvtepNodeName(new HwvtepNodeName(pSwitch.getName()));
143         }
144         if (pSwitch.getDescription() != null) {
145             psAugmentationBuilder.setHwvtepNodeDescription(pSwitch.getDescription());
146         }
147     }
148
149     private void setManagementIps(PhysicalSwitchAugmentationBuilder psAugmentationBuilder, PhysicalSwitch pSwitch) {
150         if (pSwitch.getManagementIpsColumn() != null && pSwitch.getManagementIpsColumn().getData() != null
151                 && !pSwitch.getManagementIpsColumn().getData().isEmpty()) {
152             List<ManagementIps> mgmtIps = new ArrayList<>();
153             for (String mgmtIp : pSwitch.getManagementIpsColumn().getData()) {
154                 IpAddress ip = new IpAddress(mgmtIp.toCharArray());
155                 mgmtIps.add(
156                         new ManagementIpsBuilder().setKey(new ManagementIpsKey(ip)).setManagementIpsKey(ip).build());
157             }
158             psAugmentationBuilder.setManagementIps(mgmtIps);
159         }
160     }
161
162     private void setTunnelIps(PhysicalSwitchAugmentationBuilder psAugmentationBuilder, PhysicalSwitch pSwitch) {
163         if (pSwitch.getTunnelIpsColumn() != null && pSwitch.getTunnelIpsColumn().getData() != null
164                 && !pSwitch.getTunnelIpsColumn().getData().isEmpty()) {
165             List<TunnelIps> tunnelIps = new ArrayList<>();
166             for (String tunnelIp : pSwitch.getTunnelIpsColumn().getData()) {
167                 IpAddress ip = new IpAddress(tunnelIp.toCharArray());
168                 tunnelIps.add(new TunnelIpsBuilder().setKey(new TunnelIpsKey(ip)).setTunnelIpsKey(ip).build());
169             }
170             psAugmentationBuilder.setTunnelIps(tunnelIps);
171         }
172     }
173
174     private Node buildConnectionNode(PhysicalSwitch pSwitch) {
175         // Update node with PhysicalSwitch reference
176         NodeBuilder connectionNode = new NodeBuilder();
177         connectionNode.setNodeId(getOvsdbConnectionInstance().getNodeId());
178
179         HwvtepGlobalAugmentationBuilder hgAugmentationBuilder = new HwvtepGlobalAugmentationBuilder();
180         List<Switches> switches = new ArrayList<>();
181         InstanceIdentifier<Node> switchIid =
182                 HwvtepSouthboundMapper.createInstanceIdentifier(getOvsdbConnectionInstance(), pSwitch);
183         hgAugmentationBuilder.setSwitches(switches);
184         Switches physicalSwitch = new SwitchesBuilder().setSwitchRef(new HwvtepPhysicalSwitchRef(switchIid)).build();
185         switches.add(physicalSwitch);
186
187         connectionNode.addAugmentation(HwvtepGlobalAugmentation.class, hgAugmentationBuilder.build());
188
189         LOG.debug("Update node with physicalswitch ref {}", hgAugmentationBuilder.getSwitches().iterator().next());
190         return connectionNode.build();
191     }
192
193     private InstanceIdentifier<Node> getInstanceIdentifier(PhysicalSwitch pSwitch) {
194         return HwvtepSouthboundMapper.createInstanceIdentifier(getOvsdbConnectionInstance(), pSwitch);
195     }
196
197     private NodeId getNodeId(PhysicalSwitch pSwitch) {
198         NodeKey nodeKey = getInstanceIdentifier(pSwitch).firstKeyOf(Node.class);
199         return nodeKey.getNodeId();
200     }
201
202     private <T extends DataObject> void deleteEntries(ReadWriteTransaction transaction,
203             List<InstanceIdentifier<T>> entryIids) {
204         for (InstanceIdentifier<T> entryIid : entryIids) {
205             transaction.delete(LogicalDatastoreType.OPERATIONAL, entryIid);
206         }
207     }
208
209     private List<InstanceIdentifier<SwitchFaultStatus>> getSwitchFaultStatusToRemove(InstanceIdentifier<Node> psIid,
210             PhysicalSwitch pSwitch) {
211         Preconditions.checkNotNull(psIid);
212         Preconditions.checkNotNull(pSwitch);
213         List<InstanceIdentifier<SwitchFaultStatus>> result = new ArrayList<>();
214         PhysicalSwitch oldSwitch = oldPSRows.get(pSwitch.getUuid());
215         if (oldSwitch != null && oldSwitch.getSwitchFaultStatusColumn() != null) {
216             for (String switchFltStat : oldSwitch.getSwitchFaultStatusColumn().getData()) {
217                 if (pSwitch.getSwitchFaultStatusColumn() == null
218                         || !pSwitch.getSwitchFaultStatusColumn().getData().contains(switchFltStat)) {
219                     InstanceIdentifier<SwitchFaultStatus> iid = psIid.augmentation(PhysicalSwitchAugmentation.class)
220                             .child(SwitchFaultStatus.class, new SwitchFaultStatusKey(switchFltStat));
221                     result.add(iid);
222                 }
223             }
224         }
225         return result;
226     }
227
228     private void setSwitchFaultStatus(PhysicalSwitchAugmentationBuilder psAugmentationBuilder, PhysicalSwitch pSwitch) {
229         if (pSwitch.getSwitchFaultStatusColumn() != null && pSwitch.getSwitchFaultStatusColumn().getData() != null
230                 && !pSwitch.getSwitchFaultStatusColumn().getData().isEmpty()) {
231             List<SwitchFaultStatus> switchFaultStatusLst = new ArrayList<>();
232             for (String switchFaultStatus : pSwitch.getSwitchFaultStatusColumn().getData()) {
233                 switchFaultStatusLst
234                         .add(new SwitchFaultStatusBuilder().setKey(new SwitchFaultStatusKey(switchFaultStatus))
235                                 .setSwitchFaultStatusKey(switchFaultStatus).build());
236             }
237             psAugmentationBuilder.setSwitchFaultStatus(switchFaultStatusLst);
238         }
239     }
240
241 }