Bug 8055: various performance issues
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / transact / PhysicalPortUpdateCommand.java
1 /*
2  * Copyright © 2015, 2017 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 static org.opendaylight.ovsdb.lib.operations.Operations.op;
12
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.HashMap;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Map.Entry;
19
20 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
22 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundMapper;
23 import org.opendaylight.ovsdb.lib.notation.Mutator;
24 import org.opendaylight.ovsdb.lib.notation.UUID;
25 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
26 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
27 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalPort;
28 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalSwitch;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import com.google.common.base.Optional;
41 import com.google.common.collect.Sets;
42
43 public class PhysicalPortUpdateCommand extends AbstractTransactCommand {
44     private static final Logger LOG = LoggerFactory.getLogger(PhysicalPortUpdateCommand.class);
45
46     public PhysicalPortUpdateCommand(HwvtepOperationalState state,
47             Collection<DataTreeModification<Node>> changes) {
48         super(state, changes);
49     }
50
51     @Override
52     public void execute(TransactionBuilder transaction) {
53         Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> createds =
54                 extractCreated(getChanges(),HwvtepPhysicalPortAugmentation.class);
55         Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> createdPhysicalSwitches =
56                 extractCreatedPhyscialSwitch(getChanges(),PhysicalSwitchAugmentation.class);
57         if (!createds.isEmpty()) {
58             for (Entry<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> created:
59                 createds.entrySet()) {
60                 updatePhysicalPort(transaction,  created.getKey(), created.getValue(), createdPhysicalSwitches);
61             }
62         }
63         Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> updateds =
64                 extractUpdatedPorts(getChanges(), HwvtepPhysicalPortAugmentation.class);
65         if (!updateds.isEmpty()) {
66             for (Entry<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> updated:
67                 updateds.entrySet()) {
68                 updatePhysicalPort(transaction,  updated.getKey(), updated.getValue(), createdPhysicalSwitches);
69             }
70         }
71     }
72
73     private void updatePhysicalPort(TransactionBuilder transaction,
74             InstanceIdentifier<Node> psNodeiid,
75             List<HwvtepPhysicalPortAugmentation> listPort,
76             Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> createdPhysicalSwitches ) {
77         //Get physical switch which the port belong to: in operation DS or new created
78         PhysicalSwitchAugmentation physicalSwitchBelong = getPhysicalSwitchBelong(psNodeiid, createdPhysicalSwitches);
79         for (HwvtepPhysicalPortAugmentation port : listPort) {
80             LOG.debug("Creating a physical port named: {}", port.getHwvtepNodeName().getValue());
81             Optional<HwvtepPhysicalPortAugmentation> operationalPhysicalPortOptional =
82                     getOperationalState().getPhysicalPortAugmentation(psNodeiid, port.getHwvtepNodeName());
83             PhysicalPort physicalPort = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), PhysicalPort.class);
84             //get managing global node of physicalSwitchBelong
85             InstanceIdentifier<?> globalNodeIid = physicalSwitchBelong.getManagedBy().getValue();
86             setVlanBindings(globalNodeIid, physicalPort, port);
87             setDescription(physicalPort, port);
88             if (!operationalPhysicalPortOptional.isPresent()) {
89                 //create a physical port
90                 setName(physicalPort, port, operationalPhysicalPortOptional);
91                 String portUuid = "PhysicalPort_" + HwvtepSouthboundMapper.getRandomUUID();
92                 LOG.trace("execute: creating physical port: {}", physicalPort);
93                 transaction.add(op.insert(physicalPort).withId(portUuid));
94                 transaction.add(op.comment("Physical Port: Creating " + port.getHwvtepNodeName().getValue()));
95                 //update physical switch table
96                 PhysicalSwitch physicalSwitch = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), PhysicalSwitch.class);
97                 physicalSwitch.setName(physicalSwitchBelong.getHwvtepNodeName().getValue());
98                 physicalSwitch.setPorts(Sets.newHashSet(new UUID(portUuid)));
99                 LOG.trace("execute: mutating physical switch: {}", physicalSwitch);
100                 transaction.add(op.mutate(physicalSwitch)
101                         .addMutation(physicalSwitch.getPortsColumn().getSchema(), Mutator.INSERT,
102                                 physicalSwitch.getPortsColumn().getData())
103                         .where(physicalSwitch.getNameColumn().getSchema().opEqual(physicalSwitch.getNameColumn().getData()))
104                         .build());
105                 transaction.add(op.comment("Physical Switch: Mutating " +
106                                 port.getHwvtepNodeName().getValue() + " " + portUuid));
107             } else {
108                 //updated physical port only
109                 HwvtepPhysicalPortAugmentation updatedPhysicalPort = operationalPhysicalPortOptional.get();
110                 String existingPhysicalPortName = updatedPhysicalPort.getHwvtepNodeName().getValue();
111                 PhysicalPort extraPhyscialPort =
112                         TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), PhysicalPort.class);
113                 extraPhyscialPort.setName("");
114                 LOG.trace("execute: updating physical port: {}", physicalPort);
115                 transaction.add(op.update(physicalPort)
116                         .where(extraPhyscialPort.getNameColumn().getSchema().opEqual(existingPhysicalPortName))
117                         .build());
118                 transaction.add(op.comment("Physical Port: Updating " + existingPhysicalPortName));
119             }
120         }
121     }
122
123     private PhysicalSwitchAugmentation getPhysicalSwitchBelong(InstanceIdentifier<Node> psNodeiid,
124             Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> createdPhysicalSwitches) {
125         Optional<PhysicalSwitchAugmentation> physicalSwitchOptional =
126                     getOperationalState().getPhysicalSwitchAugmentation(psNodeiid);
127         PhysicalSwitchAugmentation physicalSwitchAugmentation = null;
128         if (physicalSwitchOptional.isPresent()) {
129             physicalSwitchAugmentation = physicalSwitchOptional.get();
130         } else {
131             physicalSwitchAugmentation = createdPhysicalSwitches.get(psNodeiid);
132         }
133         return physicalSwitchAugmentation;
134     }
135
136     private void setName(PhysicalPort physicalPort, HwvtepPhysicalPortAugmentation inputPhysicalPort,
137             Optional<HwvtepPhysicalPortAugmentation> operationalLogicalSwitchOptional) {
138         if (inputPhysicalPort.getHwvtepNodeName() != null) {
139             physicalPort.setName(inputPhysicalPort.getHwvtepNodeName().getValue());
140         } else if (operationalLogicalSwitchOptional.isPresent()
141                 && operationalLogicalSwitchOptional.get().getHwvtepNodeName() != null) {
142             physicalPort.setName(operationalLogicalSwitchOptional.get().getHwvtepNodeName().getValue());
143         }
144     }
145
146     private void setDescription(PhysicalPort physicalPort, HwvtepPhysicalPortAugmentation inputPhysicalPort) {
147         if (inputPhysicalPort.getHwvtepNodeDescription() != null) {
148             physicalPort.setDescription(inputPhysicalPort.getHwvtepNodeDescription());
149         }
150     }
151
152     private void setVlanBindings(InstanceIdentifier<?> globalNodeIid, PhysicalPort physicalPort,
153             HwvtepPhysicalPortAugmentation inputPhysicalPort) {
154         if (inputPhysicalPort.getVlanBindings() != null) {
155             //get UUID by LogicalSwitchRef
156             Map<Long, UUID> bindingMap = new HashMap<>();
157             for (VlanBindings vlanBinding: inputPhysicalPort.getVlanBindings()) {
158                 @SuppressWarnings("unchecked")
159                 InstanceIdentifier<LogicalSwitches> lswitchIid =
160                         (InstanceIdentifier<LogicalSwitches>) vlanBinding.getLogicalSwitchRef().getValue();
161                 Optional<LogicalSwitches> operationalSwitchOptional =
162                         getOperationalState().getLogicalSwitches(lswitchIid);
163                 if (operationalSwitchOptional.isPresent()) {
164                     Uuid logicalSwitchUuid = operationalSwitchOptional.get().getLogicalSwitchUuid();
165                     bindingMap.put(vlanBinding.getVlanIdKey().getValue().longValue(), new UUID(logicalSwitchUuid.getValue()));
166                 }else{
167                     bindingMap.put(vlanBinding.getVlanIdKey().getValue().longValue(), TransactUtils.getLogicalSwitchUUID(lswitchIid));
168                 }
169             }
170             physicalPort.setVlanBindings(bindingMap);
171         }
172     }
173
174     private Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> extractCreated(
175             Collection<DataTreeModification<Node>> changes, Class<HwvtepPhysicalPortAugmentation> class1) {
176         Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> result = new HashMap<>();
177         if (changes != null && !changes.isEmpty()) {
178             for (DataTreeModification<Node> change : changes) {
179                 final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
180                 final DataObjectModification<Node> mod = change.getRootNode();
181                 Node created = TransactUtils.getCreated(mod);
182                 if (created != null) {
183                     List<HwvtepPhysicalPortAugmentation> portListUpdated = new ArrayList<>();
184                     if (created.getTerminationPoint() != null) {
185                         for (TerminationPoint tp : created.getTerminationPoint()) {
186                             HwvtepPhysicalPortAugmentation hppAugmentation = tp.getAugmentation(HwvtepPhysicalPortAugmentation.class);
187                             if (hppAugmentation != null) {
188                                 portListUpdated.add(hppAugmentation);
189                             }
190                         }
191                     }
192                     result.put(key, portListUpdated);
193                 }
194             }
195         }
196         return result;
197     }
198
199     private Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> extractCreatedPhyscialSwitch(
200             Collection<DataTreeModification<Node>> changes, Class<PhysicalSwitchAugmentation> class1) {
201         Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> result = new HashMap<>();
202         if (changes != null && !changes.isEmpty()) {
203             for (DataTreeModification<Node> change : changes) {
204                 final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
205                 final DataObjectModification<Node> mod = change.getRootNode();
206                 Node created = TransactUtils.getCreated(mod);
207                 if (created != null) {
208                     PhysicalSwitchAugmentation physicalSwitch = created.getAugmentation(PhysicalSwitchAugmentation.class);
209                     if (physicalSwitch != null) {
210                         result.put(key, physicalSwitch);
211                     }
212                 }
213             }
214         }
215         return result;
216     }
217
218     private Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> extractUpdatedPorts(
219             Collection<DataTreeModification<Node>> changes, Class<HwvtepPhysicalPortAugmentation> class1) {
220         Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> result = new HashMap<>();
221         if (changes != null && !changes.isEmpty()) {
222             for (DataTreeModification<Node> change : changes) {
223                 final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
224                 final DataObjectModification<Node> mod = change.getRootNode();
225                 Node updated = TransactUtils.getUpdated(mod);
226                 Node before = mod.getDataBefore();
227                 if (updated != null && before != null) {
228                     List<HwvtepPhysicalPortAugmentation> portListUpdated = new ArrayList<>();
229                     List<HwvtepPhysicalPortAugmentation> portListBefore = new ArrayList<>();
230                     if (updated.getTerminationPoint() != null) {
231                         for (TerminationPoint tp : updated.getTerminationPoint()) {
232                             HwvtepPhysicalPortAugmentation hppAugmentation = tp.getAugmentation(HwvtepPhysicalPortAugmentation.class);
233                             if (hppAugmentation != null) {
234                                 portListUpdated.add(hppAugmentation);
235                             }
236                         }
237                     }
238                     if (before.getTerminationPoint() != null) {
239                         for (TerminationPoint tp : before.getTerminationPoint()) {
240                             HwvtepPhysicalPortAugmentation hppAugmentation = tp.getAugmentation(HwvtepPhysicalPortAugmentation.class);
241                             if (hppAugmentation != null) {
242                                 portListBefore.add(hppAugmentation);
243                             }
244                         }
245                     }
246                     portListUpdated.removeAll(portListBefore);
247                     result.put(key, portListUpdated);
248                 }
249             }
250         }
251         return result;
252     }
253 }