Ensure External Connectivity for NAPT Switch
[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 javax.annotation.PostConstruct;
11 import javax.inject.Inject;
12 import javax.inject.Singleton;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
15 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
16 import org.opendaylight.netvirt.natservice.api.CentralizedSwitchScheduler;
17 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
18 import org.opendaylight.serviceutils.upgrade.UpgradeState;
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.genius.idmanager.rev160406.IdManagerService;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 @Singleton
30 public class SnatExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Routers, SnatExternalRoutersListener> {
31     private static final Logger LOG = LoggerFactory.getLogger(SnatExternalRoutersListener.class);
32
33     private final DataBroker dataBroker;
34     private final IdManagerService idManager;
35     private final CentralizedSwitchScheduler  centralizedSwitchScheduler;
36     private final NatMode natMode;
37     private final UpgradeState upgradeState;
38     private final SnatServiceManager natServiceManager;
39
40     @Inject
41     public SnatExternalRoutersListener(final DataBroker dataBroker,
42                                        final IdManagerService idManager,
43                                        final CentralizedSwitchScheduler centralizedSwitchScheduler,
44                                        final NatserviceConfig config,
45                                        final SnatServiceManager natServiceManager,
46                                        final UpgradeState upgradeState) {
47         super(Routers.class, SnatExternalRoutersListener.class);
48         this.dataBroker = dataBroker;
49         this.idManager = idManager;
50         this.centralizedSwitchScheduler = centralizedSwitchScheduler;
51         this.upgradeState = upgradeState;
52         this.natServiceManager = natServiceManager;
53         if (config != null) {
54             this.natMode = config.getNatMode();
55         } else {
56             this.natMode = NatMode.Conntrack;
57         }
58     }
59
60     @Override
61     @PostConstruct
62     public void init() {
63         LOG.info("{} init", getClass().getSimpleName());
64         // This class handles ExternalRouters for Conntrack SNAT mode.
65         // For Controller SNAT mode, its handled in ExternalRoutersListeners.java
66         if (natMode == NatMode.Conntrack) {
67             registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
68             NatUtil.createGroupIdPool(idManager);
69         }
70     }
71
72     @Override
73     protected InstanceIdentifier<Routers> getWildCardPath() {
74         return InstanceIdentifier.create(ExtRouters.class).child(Routers.class);
75     }
76
77     @Override
78     @SuppressWarnings("checkstyle:IllegalCatch")
79     protected void add(InstanceIdentifier<Routers> identifier, Routers routers) {
80         String routerName = routers.getRouterName();
81         if (upgradeState.isUpgradeInProgress()) {
82             LOG.warn("add event for ext-router {}, but upgrade is in progress.", routerName);
83             return;
84         }
85
86         LOG.info("add : external router event for {}", routerName);
87         long routerId = NatUtil.getVpnId(dataBroker, routerName);
88         NatUtil.createRouterIdsConfigDS(dataBroker, routerId, routerName);
89         Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
90         if (bgpVpnUuid != null) {
91             // Router associated to BGPVPN, ignoring it.
92             return;
93         }
94         // Allocate Primary NAPTSwitch for this router
95         centralizedSwitchScheduler.scheduleCentralizedSwitch(routers);
96     }
97
98     @Override
99     protected void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
100         String routerName = original.getRouterName();
101         Long routerId = NatUtil.getVpnId(dataBroker, routerName);
102         if (routerId == NatConstants.INVALID_ID) {
103             LOG.error("update : external router event - Invalid routerId for routerName {}", routerName);
104             return;
105         }
106
107         // Check if its update on SNAT flag
108         boolean originalSNATEnabled = original.isEnableSnat();
109         boolean updatedSNATEnabled = update.isEnableSnat();
110         LOG.info("update :called for router {} with originalSNATStatus {} and updatedSNATStatus {}",
111                 routerName, originalSNATEnabled, updatedSNATEnabled);
112         if (!upgradeState.isUpgradeInProgress()) {
113             centralizedSwitchScheduler.scheduleCentralizedSwitch(update);
114         }
115     }
116
117     @Override
118     protected void remove(InstanceIdentifier<Routers> identifier, Routers router) {
119         if (identifier == null || router == null) {
120             LOG.error("remove : returning without processing since ext-router is null");
121             return;
122         }
123
124         LOG.info("remove : external router event for {}", router.getRouterName());
125         centralizedSwitchScheduler.releaseCentralizedSwitch(router);
126     }
127
128     @Override
129     protected SnatExternalRoutersListener getDataTreeChangeListener() {
130         return SnatExternalRoutersListener.this;
131     }
132 }