NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / SnatExternalRoutersListener.java
1 /*
2  * Copyright (c) 2018 Red Hat, Inc. 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 package org.opendaylight.netvirt.natservice.internal;
9
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11
12 import java.util.Objects;
13 import javax.annotation.PreDestroy;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
17 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
18 import org.opendaylight.infrautils.utils.concurrent.Executors;
19 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
20 import org.opendaylight.mdsal.binding.api.DataBroker;
21 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
22 import org.opendaylight.netvirt.natservice.api.CentralizedSwitchScheduler;
23 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
24 import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
25 import org.opendaylight.serviceutils.upgrade.UpgradeState;
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.idmanager.rev160406.IdManagerService;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.opendaylight.yangtools.yang.common.Uint32;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 @Singleton
38 public class SnatExternalRoutersListener extends AbstractAsyncDataTreeChangeListener<Routers> {
39     private static final Logger LOG = LoggerFactory.getLogger(SnatExternalRoutersListener.class);
40
41     private final DataBroker dataBroker;
42     private final ManagedNewTransactionRunner txRunner;
43     private final IdManagerService idManager;
44     private final CentralizedSwitchScheduler  centralizedSwitchScheduler;
45     private final NatMode natMode;
46     private final UpgradeState upgradeState;
47     private final SnatServiceManager natServiceManager;
48
49     @Inject
50     public SnatExternalRoutersListener(final DataBroker dataBroker,
51                                        final IdManagerService idManager,
52                                        final CentralizedSwitchScheduler centralizedSwitchScheduler,
53                                        final NatserviceConfig config,
54                                        final SnatServiceManager natServiceManager,
55                                        final UpgradeState upgradeState) {
56         super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(ExtRouters.class)
57                 .child(Routers.class),
58                 Executors.newListeningSingleThreadExecutor("SnatExternalRoutersListener", LOG));
59         this.dataBroker = dataBroker;
60         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
61         this.idManager = idManager;
62         this.centralizedSwitchScheduler = centralizedSwitchScheduler;
63         this.upgradeState = upgradeState;
64         this.natServiceManager = natServiceManager;
65         if (config != null) {
66             this.natMode = config.getNatMode();
67         } else {
68             this.natMode = NatMode.Conntrack;
69         }
70         init();
71     }
72
73     public void init() {
74         LOG.info("{} init", getClass().getSimpleName());
75         // This class handles ExternalRouters for Conntrack SNAT mode.
76         // For Controller SNAT mode, its handled in ExternalRoutersListeners.java
77         if (natMode == NatMode.Conntrack) {
78             NatUtil.createGroupIdPool(idManager);
79         }
80     }
81
82     @Override
83     @PreDestroy
84     public void close() {
85         super.close();
86         Executors.shutdownAndAwaitTermination(getExecutorService());
87     }
88
89     @Override
90     @SuppressWarnings("checkstyle:IllegalCatch")
91     public void add(InstanceIdentifier<Routers> identifier, Routers routers) {
92         if (natMode != NatMode.Conntrack) {
93             return;
94         }
95         String routerName = routers.getRouterName();
96         if (upgradeState.isUpgradeInProgress()) {
97             LOG.warn("add event for ext-router {}, but upgrade is in progress.", routerName);
98             return;
99         }
100
101         LOG.info("add : external router event for {}", routerName);
102         Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
103         NatUtil.createRouterIdsConfigDS(dataBroker, routerId, routerName);
104         Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
105         if (bgpVpnUuid != null) {
106             // Router associated to BGPVPN, ignoring it.
107             return;
108         }
109         // Allocate Primary NAPTSwitch for this router
110         centralizedSwitchScheduler.scheduleCentralizedSwitch(routers);
111     }
112
113     @Override
114     public void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
115         if (natMode != NatMode.Conntrack) {
116             return;
117         }
118         String routerName = original.getRouterName();
119         Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
120         if (routerId == NatConstants.INVALID_ID) {
121             LOG.error("update : external router event - Invalid routerId for routerName {}", routerName);
122             return;
123         }
124         LOG.info("update :called for router {} with originalSNATStatus {} and updatedSNATStatus {}",
125                 routerName, original.isEnableSnat(), update.isEnableSnat());
126         if (!upgradeState.isUpgradeInProgress()) {
127             centralizedSwitchScheduler.updateCentralizedSwitch(original, update);
128         }
129         if (!Objects.equals(original.getSubnetIds(), update.getSubnetIds())
130                 || !Objects.equals(original.getExternalIps(), update.getExternalIps())) {
131             ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
132                 confTx -> natServiceManager.notify(confTx, update, original, null, null,
133                             SnatServiceManager.Action.SNAT_ROUTER_UPDATE)), LOG,
134                     "error handling external router update");
135         }
136     }
137
138     @Override
139     public void remove(InstanceIdentifier<Routers> identifier, Routers router) {
140         if (natMode != NatMode.Conntrack) {
141             return;
142         }
143         if (identifier == null || router == null) {
144             LOG.error("remove : returning without processing since ext-router is null");
145             return;
146         }
147
148         LOG.info("remove : external router event for {}", router.getRouterName());
149         centralizedSwitchScheduler.releaseCentralizedSwitch(router);
150     }
151 }