Migrate to odlparent 1.9.0
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / lisp / bvi / BviManager.java
1 /*
2  * Copyright (c) 2017 Cisco Systems. 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.groupbasedpolicy.renderer.vpp.lisp.bvi;
10
11 import com.google.common.base.Preconditions;
12 import com.google.common.eventbus.Subscribe;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommand;
15 import org.opendaylight.groupbasedpolicy.renderer.vpp.event.GbpSubnetEvent;
16 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispConfigCommandFailedException;
17 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
18 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
21 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
22 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpSubnet;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import javax.annotation.Nonnull;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.concurrent.ExecutionException;
33
34 /**
35  * Created by Shakib Ahmed on 4/26/17.
36  */
37 public class BviManager {
38     private static final Logger LOG = LoggerFactory.getLogger(BviManager.class);
39
40     private ConfigManagerHelper managerHelper;
41
42     private HashMap<String, GbpSubnet> subnetInformation;
43
44     private BviHostSpecificInfo bviHostSpecificInfo;
45     private NeutronTenantToVniMapper neutronTenantToVniMapper;
46
47     public BviManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
48         managerHelper = new ConfigManagerHelper(mountedDataBrokerProvider);
49         subnetInformation = new HashMap<>();
50         bviHostSpecificInfo = new BviHostSpecificInfo();
51         neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
52     }
53
54     @Subscribe
55     public synchronized void gbpSubnetChanged(GbpSubnetEvent event) {
56         final GbpSubnet oldGbpSubnet = event.getBefore().orNull();
57         final GbpSubnet newGbpSubnet = event.getAfter().orNull();
58         switch (event.getDtoModificationType()) {
59             case CREATED:
60                 Preconditions.checkNotNull(newGbpSubnet);
61                 processSubnetCreated(newGbpSubnet.getId(), newGbpSubnet);
62                 break;
63             case UPDATED:
64                 Preconditions.checkNotNull(oldGbpSubnet);
65                 Preconditions.checkNotNull(newGbpSubnet);
66                 processSubnetDeleted(oldGbpSubnet.getId());
67                 processSubnetCreated(newGbpSubnet.getId(), newGbpSubnet);
68                 break;
69             case DELETED:
70                 Preconditions.checkNotNull(oldGbpSubnet);
71                 processSubnetDeleted(oldGbpSubnet.getId());
72                 break;
73         }
74     }
75
76     private void processSubnetCreated(String subnetUuid, GbpSubnet subnetInfo) {
77         subnetInformation.put(subnetUuid, subnetInfo);
78     }
79
80     private void processSubnetDeleted(String subnetUuid) {
81         subnetInformation.remove(subnetUuid);
82
83         deleteBviIfExists(subnetUuid);
84     }
85
86     public GbpSubnet getSubnetInfo(String subnetUuid) {
87         return subnetInformation.get(subnetUuid);
88     }
89
90     public void createBviIfNecessary(AddressEndpointWithLocation addressEp,
91                                      String bridgeDomainName) {
92         try {
93             DataBroker vppDataBroker = managerHelper.getPotentialExternalDataBroker(addressEp).get();
94             String hostName = managerHelper.getHostName(addressEp).get();
95             String subnetUuid = managerHelper.getSubnet(addressEp);
96
97             if (bviHostSpecificInfo.bviAlreadyExists(hostName, subnetUuid)) {
98                 return;
99             }
100
101             GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(getSubnetInfo(subnetUuid),
102                     "Subnet UUID {} hasn't been created yet!", subnetUuid);
103
104             LoopbackCommand.LoopbackCommandBuilder loopbackCommandBuilder =
105                     new LoopbackCommand.LoopbackCommandBuilder();
106             loopbackCommandBuilder.setInterfaceName("loop"
107                     + bviHostSpecificInfo.getBviCount(hostName));
108             loopbackCommandBuilder.setBridgeDomain(bridgeDomainName);
109             loopbackCommandBuilder.setBvi(true);
110             loopbackCommandBuilder.setEnabled(true);
111             loopbackCommandBuilder.setVrfId(getVni(addressEp.getTenant().getValue()));
112             loopbackCommandBuilder.setIpAddress(gbpSubnetInfo.getGatewayIp());
113             loopbackCommandBuilder.setIpPrefix(gbpSubnetInfo.getCidr());
114             loopbackCommandBuilder.setOperation(General.Operations.PUT);
115             createBviInterface(hostName, vppDataBroker, loopbackCommandBuilder);
116         } catch (LispConfigCommandFailedException e) {
117             LOG.debug("LISP loopback command failed for {}", e.getMessage());
118         }
119     }
120
121     public void createBviInterface(String hostName, DataBroker vppDataBroker,
122                                    LoopbackCommand.LoopbackCommandBuilder commandBuilder) throws LispConfigCommandFailedException {
123
124         if (GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker,
125                                                      commandBuilder.build(),
126                                                      GbpNetconfTransaction.RETRY_COUNT)) {
127             bviHostSpecificInfo.addBviForHost(hostName,
128                                               commandBuilder.getBridgeDomain(),
129                                               commandBuilder.getInterfaceName());
130         } else {
131             throw new LispConfigCommandFailedException("BVI could not be created for "
132                     + hostName + " and bridge domain " + commandBuilder.getBridgeDomain());
133         }
134     }
135
136     public void deleteBviIfExists(String subnetUuid) {
137
138         List<String> hostsWithSubnet = bviHostSpecificInfo.getHostsWithSubnet(subnetUuid);
139
140         hostsWithSubnet.forEach(host -> {
141             DataBroker vppDataBroker = managerHelper.getPotentialExternalDataBroker(host).get();
142             String bviInterfaceName = bviHostSpecificInfo.getInterfaceNameForBviInHost(host, subnetUuid);
143             GbpNetconfTransaction.netconfSyncedDelete(vppDataBroker,
144                     VppIidFactory.getInterfaceIID(new InterfaceKey(bviInterfaceName)), GbpNetconfTransaction.RETRY_COUNT);
145         });
146     }
147
148     private long getVni(String tenantUuid) {
149         return neutronTenantToVniMapper.getVni(tenantUuid);
150     }
151 }