bug 6579 added dependency queue
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / transact / UcastMacsRemoteUpdateCommand.java
1 /*
2  * Copyright (c) 2015, 2016 China Telecom Beijing Research Institute 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.transact;
10
11 import com.google.common.base.Optional;
12 import com.google.common.collect.Lists;
13 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
14 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
15 import org.opendaylight.ovsdb.lib.notation.UUID;
16 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
17 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
18 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
24 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Map.Entry;
36
37 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
38
39 public class UcastMacsRemoteUpdateCommand extends AbstractTransactCommand<RemoteUcastMacs> {
40     private static final Logger LOG = LoggerFactory.getLogger(UcastMacsRemoteUpdateCommand.class);
41     private static final UcastMacUnMetDependencyGetter UCAST_MAC_DATA_VALIDATOR = new UcastMacUnMetDependencyGetter();
42
43     public UcastMacsRemoteUpdateCommand(HwvtepOperationalState state,
44             Collection<DataTreeModification<Node>> changes) {
45         super(state, changes);
46     }
47
48     @Override
49     public void execute(TransactionBuilder transaction) {
50         Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> createds =
51                 extractCreated(getChanges(),RemoteUcastMacs.class);
52         if (!createds.isEmpty()) {
53             for (Entry<InstanceIdentifier<Node>, List<RemoteUcastMacs>> created:
54                 createds.entrySet()) {
55                 updateUcastMacsRemote(transaction,  created.getKey(), created.getValue());
56             }
57         }
58         Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> updateds =
59                 extractUpdated(getChanges(),RemoteUcastMacs.class);
60         if (!updateds.isEmpty()) {
61             for (Entry<InstanceIdentifier<Node>, List<RemoteUcastMacs>> updated:
62                 updateds.entrySet()) {
63                 updateUcastMacsRemote(transaction,  updated.getKey(), updated.getValue());
64             }
65         }
66     }
67
68     private void updateUcastMacsRemote(TransactionBuilder transaction,
69                                        InstanceIdentifier<Node> instanceIdentifier,
70                                        List<RemoteUcastMacs> remoteUcastMacs) {
71         if (remoteUcastMacs == null) {
72             return;
73         }
74         for (RemoteUcastMacs remoteUcastMac : remoteUcastMacs) {
75             onConfigUpdate(transaction, instanceIdentifier, remoteUcastMac);
76         }
77     }
78
79     @Override
80     public void onConfigUpdate(TransactionBuilder transaction,
81                                   InstanceIdentifier<Node> nodeIid,
82                                   RemoteUcastMacs remoteUcastMacs) {
83         InstanceIdentifier<RemoteUcastMacs> macIid = nodeIid.augmentation(HwvtepGlobalAugmentation.class).
84                 child(RemoteUcastMacs.class, remoteUcastMacs.getKey());
85         //TODO uncommet in next commit
86         //processDependencies(UCAST_MAC_DATA_VALIDATOR, transaction, nodeIid, macIid, remoteUcastMacs);
87         doDeviceTransaction(transaction, nodeIid, remoteUcastMacs);
88     }
89
90     @Override
91     public void doDeviceTransaction(TransactionBuilder transaction,
92                                        InstanceIdentifier<Node> instanceIdentifier, RemoteUcastMacs remoteUcastMac) {
93             LOG.debug("Creating remoteUcastMacs, mac address: {}", remoteUcastMac.getMacEntryKey().getValue());
94             Optional<RemoteUcastMacs> operationalMacOptional =
95                     getOperationalState().getRemoteUcastMacs(instanceIdentifier, remoteUcastMac.getKey());
96             UcastMacsRemote ucastMacsRemote = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), UcastMacsRemote.class);
97             setIpAddress(ucastMacsRemote, remoteUcastMac);
98             setLocator(transaction, ucastMacsRemote, remoteUcastMac);
99             setLogicalSwitch(ucastMacsRemote, remoteUcastMac);
100             if (!operationalMacOptional.isPresent()) {
101                 setMac(ucastMacsRemote, remoteUcastMac, operationalMacOptional);
102                 LOG.trace("doDeviceTransaction: creating RemotUcastMac entry: {}", ucastMacsRemote);
103                 transaction.add(op.insert(ucastMacsRemote));
104                 transaction.add(op.comment("UcastMacRemote: Creating " + remoteUcastMac.getMacEntryKey().getValue()));
105             } else if (operationalMacOptional.get().getMacEntryUuid() != null) {
106                 UUID macEntryUUID = new UUID(operationalMacOptional.get().getMacEntryUuid().getValue());
107                 UcastMacsRemote extraMac = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
108                                 UcastMacsRemote.class, null);
109                 extraMac.getUuidColumn().setData(macEntryUUID);
110                 LOG.trace("doDeviceTransaction: updating RemotUcastMac entry: {}", ucastMacsRemote);
111                 transaction.add(op.update(ucastMacsRemote)
112                         .where(extraMac.getUuidColumn().getSchema().opEqual(macEntryUUID))
113                         .build());
114                 transaction.add(op.comment("UcastMacRemote: Updating " + remoteUcastMac.getMacEntryKey().getValue()));
115             } else {
116                 LOG.warn("Unable to update remoteMcastMacs {} because uuid not found in the operational store",
117                                 remoteUcastMac.getMacEntryKey().getValue());
118             }
119     }
120
121     private void setLogicalSwitch(UcastMacsRemote ucastMacsRemote, RemoteUcastMacs inputMac) {
122         if (inputMac.getLogicalSwitchRef() != null) {
123             @SuppressWarnings("unchecked")
124             InstanceIdentifier<LogicalSwitches> lswitchIid = (InstanceIdentifier<LogicalSwitches>) inputMac.getLogicalSwitchRef().getValue();
125             Optional<LogicalSwitches> operationalSwitchOptional =
126                     getOperationalState().getLogicalSwitches(lswitchIid);
127             if (operationalSwitchOptional.isPresent()) {
128                 Uuid logicalSwitchUuid = operationalSwitchOptional.get().getLogicalSwitchUuid();
129                 UUID logicalSwitchUUID = new UUID(logicalSwitchUuid.getValue());
130                 ucastMacsRemote.setLogicalSwitch(logicalSwitchUUID);
131             } else {
132                 ucastMacsRemote.setLogicalSwitch(TransactUtils.getLogicalSwitchUUID(lswitchIid));
133             }
134         }
135     }
136
137     private void setLocator(TransactionBuilder transaction, UcastMacsRemote ucastMacsRemote, RemoteUcastMacs inputMac) {
138         //get UUID by locatorRef
139         if (inputMac.getLocatorRef() != null) {
140             UUID locatorUuid = null;
141             @SuppressWarnings("unchecked")
142             InstanceIdentifier<TerminationPoint> iid = (InstanceIdentifier<TerminationPoint>) inputMac.getLocatorRef().getValue();
143             //try to find locator in operational DS
144             Optional<HwvtepPhysicalLocatorAugmentation> operationalLocatorOptional =
145                     getOperationalState().getPhysicalLocatorAugmentation(iid);
146             if (operationalLocatorOptional.isPresent()) {
147                 //if exist, get uuid
148                 HwvtepPhysicalLocatorAugmentation locatorAugmentation = operationalLocatorOptional.get();
149                 locatorUuid = new UUID(locatorAugmentation.getPhysicalLocatorUuid().getValue());
150             } else {
151                 //TODO: need to optimize by eliminating reading Configuration datastore
152                 //if no, get it from config DS and create id
153                 locatorUuid = getOperationalState().getPhysicalLocatorInFlight(iid);
154                 if (locatorUuid == null) {
155                     Optional<TerminationPoint> configLocatorOptional =
156                             TransactUtils.readNodeFromConfig(getOperationalState().getReadWriteTransaction(), iid);
157                     if (configLocatorOptional.isPresent()) {
158                         HwvtepPhysicalLocatorAugmentation locatorAugmentation =
159                                 configLocatorOptional.get().getAugmentation(HwvtepPhysicalLocatorAugmentation.class);
160                         locatorUuid = TransactUtils.createPhysicalLocator(transaction, locatorAugmentation);
161                         getOperationalState().setPhysicalLocatorInFlight(iid, locatorUuid);
162                     } else {
163                         LOG.warn("Create or update remoteUcastMac: No physical locator found in operational datastore!"
164                                 + "Its indentifier is {}", inputMac.getLocatorRef().getValue());
165                     }
166                 }
167             }
168             if (locatorUuid != null) {
169                 ucastMacsRemote.setLocator(locatorUuid);
170             }
171         }
172     }
173
174     private void setIpAddress(UcastMacsRemote ucastMacsRemote, RemoteUcastMacs inputMac) {
175         if (inputMac.getIpaddr() != null) {
176             ucastMacsRemote.setIpAddress(inputMac.getIpaddr().getIpv4Address().getValue());
177         }
178     }
179
180     private void setMac(UcastMacsRemote ucastMacsRemote, RemoteUcastMacs inputMac,
181             Optional<RemoteUcastMacs> inputSwitchOptional) {
182         if (inputMac.getMacEntryKey() != null) {
183             ucastMacsRemote.setMac(inputMac.getMacEntryKey().getValue());
184         } else if (inputSwitchOptional.isPresent() && inputSwitchOptional.get().getMacEntryKey() != null) {
185             ucastMacsRemote.setMac(inputSwitchOptional.get().getMacEntryKey().getValue());
186         }
187     }
188
189     private Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> extractCreated(
190             Collection<DataTreeModification<Node>> changes, Class<RemoteUcastMacs> class1) {
191         Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> result
192             = new HashMap<InstanceIdentifier<Node>, List<RemoteUcastMacs>>();
193         if (changes != null && !changes.isEmpty()) {
194             for (DataTreeModification<Node> change : changes) {
195                 final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
196                 final DataObjectModification<Node> mod = change.getRootNode();
197                 Node created = TransactUtils.getCreated(mod);
198                 if (created != null) {
199                     List<RemoteUcastMacs> macListUpdated = null;
200                     HwvtepGlobalAugmentation hgAugmentation = created.getAugmentation(HwvtepGlobalAugmentation.class);
201                     if (hgAugmentation != null) {
202                         macListUpdated = hgAugmentation.getRemoteUcastMacs();
203                     }
204                     if (macListUpdated != null) {
205                         result.put(key, macListUpdated);
206                     }
207                 }
208             }
209         }
210         return result;
211     }
212
213     private Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> extractUpdated(
214             Collection<DataTreeModification<Node>> changes, Class<RemoteUcastMacs> class1) {
215         Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> result
216             = new HashMap<InstanceIdentifier<Node>, List<RemoteUcastMacs>>();
217         if (changes != null && !changes.isEmpty()) {
218             for (DataTreeModification<Node> change : changes) {
219                 final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
220                 final DataObjectModification<Node> mod = change.getRootNode();
221                 Node updated = TransactUtils.getUpdated(mod);
222                 Node before = mod.getDataBefore();
223                 if (updated != null && before != null) {
224                     List<RemoteUcastMacs> macListUpdated = null;
225                     List<RemoteUcastMacs> macListBefore = null;
226                     HwvtepGlobalAugmentation hgUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class);
227                     if (hgUpdated != null) {
228                         macListUpdated = hgUpdated.getRemoteUcastMacs();
229                     }
230                     HwvtepGlobalAugmentation hgBefore = before.getAugmentation(HwvtepGlobalAugmentation.class);
231                     if (hgBefore != null) {
232                         macListBefore = hgBefore.getRemoteUcastMacs();
233                     }
234                     if (macListUpdated != null) {
235                         if (macListBefore != null) {
236                             macListUpdated.removeAll(macListBefore);
237                         }
238                         result.put(key, macListUpdated);
239                     }
240                 }
241             }
242         }
243         return result;
244     }
245
246     static class UcastMacUnMetDependencyGetter extends UnMetDependencyGetter<RemoteUcastMacs> {
247
248         public List<InstanceIdentifier<?>> getLogicalSwitchDependencies(RemoteUcastMacs data) {
249             if (data == null) {
250                 return Collections.EMPTY_LIST;
251             }
252             return Lists.newArrayList(data.getLogicalSwitchRef().getValue());
253         }
254
255         public List<InstanceIdentifier<?>> getTerminationPointDependencies(RemoteUcastMacs data) {
256             if (data == null) {
257                 return Collections.EMPTY_LIST;
258             }
259             return Lists.newArrayList(data.getLocatorRef().getValue());
260         }
261     }
262 }