2 * Copyright (c) 2017 Red Hat, Inc. 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.netvirt.natservice.ha;
11 import com.google.common.base.Optional;
13 import java.math.BigInteger;
14 import java.util.HashMap;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
23 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
24 import org.opendaylight.netvirt.natservice.api.CentralizedSwitchScheduler;
25 import org.opendaylight.netvirt.natservice.internal.NatUtil;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 public class WeightedCentralizedSwitchScheduler implements CentralizedSwitchScheduler {
40 private final Map<BigInteger,Integer> switchWeightsMap = new HashMap<>();
41 private final DataBroker dataBroker;
42 private final NatDataUtil natDataUtil;
43 final OdlInterfaceRpcService interfaceManager;
44 private final int initialSwitchWeight = 0;
47 public WeightedCentralizedSwitchScheduler(DataBroker dataBroker, OdlInterfaceRpcService interfaceManager,
48 NatDataUtil natDataUtil) {
49 this.dataBroker = dataBroker;
50 this.interfaceManager = interfaceManager;
51 this.natDataUtil = natDataUtil;
55 public boolean scheduleCentralizedSwitch(String routerName) {
56 BigInteger nextSwitchId = getSwitchWithLowestWeight();
57 RouterToNaptSwitchBuilder routerToNaptSwitchBuilder =
58 new RouterToNaptSwitchBuilder().setRouterName(routerName);
59 RouterToNaptSwitch id = routerToNaptSwitchBuilder.setPrimarySwitchId(nextSwitchId).build();
61 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
62 Routers router = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
63 String vpnName = router.getRouterName();
64 long vpnId = NatUtil.getVpnId(dataBroker, routerName);
65 for (Uuid subnetUuid :router.getSubnetIds()) {
66 Optional<Subnetmap> subnetMapEntry = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
67 getSubnetMapIdentifier(subnetUuid));
68 if (subnetMapEntry.isPresent()) {
69 Uuid routerPortUuid = subnetMapEntry.get().getRouterInterfacePortId();
70 NatUtil.createOrUpdateVpnToDpnList(dataBroker, vpnId, nextSwitchId, routerPortUuid.getValue(),
71 vpnName, writeOperTxn);
72 NatUtil.addToNeutronRouterDpnsMap(dataBroker, routerName, routerPortUuid.getValue(),
73 nextSwitchId, writeOperTxn);
74 NatUtil.addToDpnRoutersMap(dataBroker, routerName, routerPortUuid.getValue(),
75 nextSwitchId, writeOperTxn);
80 writeOperTxn.submit();
81 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
82 getNaptSwitchesIdentifier(routerName), id);
83 switchWeightsMap.put(nextSwitchId,switchWeightsMap.get(nextSwitchId) + 1);
85 } catch (TransactionCommitFailedException e) {
86 // TODO Auto-generated catch block
93 public boolean releaseCentralizedSwitch(String routerName) {
94 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
96 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
97 Routers router = natDataUtil.getRouter(routerName);
98 String vpnName = router.getRouterName();
99 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
100 for (Uuid subnetUuid :router.getSubnetIds()) {
101 Optional<Subnetmap> subnetMapEntry = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
102 getSubnetMapIdentifier(subnetUuid));
103 if (subnetMapEntry.isPresent()) {
104 Uuid routerPortUuid = subnetMapEntry.get().getRouterInterfacePortId();
105 NatUtil.removeOrUpdateVpnToDpnList(dataBroker, vpnId, primarySwitchId, routerPortUuid.getValue(),
106 vpnName, writeOperTxn);
107 NatUtil.removeFromNeutronRouterDpnsMap(dataBroker, routerName, primarySwitchId, writeOperTxn);
108 NatUtil.removeFromDpnRoutersMap(dataBroker, routerName, routerName, interfaceManager,
112 writeOperTxn.submit();
113 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
114 getNaptSwitchesIdentifier(routerName));
115 switchWeightsMap.put(primarySwitchId,switchWeightsMap.get(primarySwitchId) - 1);
116 } catch (TransactionCommitFailedException e) {
123 public boolean addSwitch(BigInteger dpnId) {
124 /* Initialize the switch in the map with weight 0 */
125 switchWeightsMap.put(dpnId, initialSwitchWeight);
131 public boolean removeSwitch(BigInteger dpnId) {
132 if (switchWeightsMap.get(dpnId) != initialSwitchWeight) {
133 NaptSwitches naptSwitches = getNaptSwitches(dataBroker);
134 for (RouterToNaptSwitch routerToNaptSwitch : naptSwitches.getRouterToNaptSwitch()) {
135 if (dpnId.equals(routerToNaptSwitch.getPrimarySwitchId())) {
136 releaseCentralizedSwitch(routerToNaptSwitch.getRouterName());
137 switchWeightsMap.remove(dpnId);
138 scheduleCentralizedSwitch(routerToNaptSwitch.getRouterName());
143 switchWeightsMap.remove(dpnId);
148 public static NaptSwitches getNaptSwitches(DataBroker dataBroker) {
149 InstanceIdentifier<NaptSwitches> id = InstanceIdentifier.builder(NaptSwitches.class).build();
150 Optional<NaptSwitches> naptSwitches = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
151 return naptSwitches.isPresent() ? naptSwitches.get() : null;
154 private BigInteger getSwitchWithLowestWeight() {
155 int lowestWeight = Integer.MAX_VALUE;
156 BigInteger nextSwitchId = BigInteger.valueOf(0);
157 for (BigInteger dpnId : switchWeightsMap.keySet()) {
158 if (lowestWeight > switchWeightsMap.get(dpnId)) {
159 lowestWeight = switchWeightsMap.get(dpnId);
160 nextSwitchId = dpnId;
166 private InstanceIdentifier<RouterToNaptSwitch> getNaptSwitchesIdentifier(String routerName) {
167 return InstanceIdentifier.builder(NaptSwitches.class)
168 .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
171 private InstanceIdentifier<Subnetmap> getSubnetMapIdentifier(Uuid subnetId) {
172 return InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
173 new SubnetmapKey(subnetId)).build();
177 public boolean getCentralizedSwitch(String routerName) {
178 // TODO Auto-generated method stub