8f241eaae301ddf95a89e16257d0b717c9ff3561
[netvirt.git] / ipv6service / impl / src / main / java / org / opendaylight / netvirt / ipv6service / NeutronPortChangeListener.java
1 /*
2  * Copyright (c) 2016, 2017 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.ipv6service;
9
10 import com.google.common.base.Strings;
11 import java.util.Collections;
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Set;
15 import javax.annotation.PostConstruct;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
22 import org.opendaylight.netvirt.ipv6service.utils.Ipv6ServiceConstants;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 @Singleton
33 public class NeutronPortChangeListener extends AsyncClusteredDataTreeChangeListenerBase<Port,
34         NeutronPortChangeListener> {
35     private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class);
36     private final DataBroker dataBroker;
37     private final IfMgr ifMgr;
38
39     @Inject
40     public NeutronPortChangeListener(final DataBroker dataBroker, IfMgr ifMgr) {
41         this.dataBroker = dataBroker;
42         this.ifMgr = ifMgr;
43     }
44
45     @PostConstruct
46     public void init() {
47         LOG.info("{} init", getClass().getSimpleName());
48         registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
49     }
50
51     @Override
52     protected InstanceIdentifier<Port> getWildCardPath() {
53         return InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class);
54     }
55
56     @Override
57     protected void add(InstanceIdentifier<Port> identifier, Port port) {
58         if (Ipv6ServiceConstants.NETWORK_ROUTER_GATEWAY.equalsIgnoreCase(port.getDeviceOwner())) {
59             // Todo: revisit when IPv6 north-south support is implemented.
60             LOG.info("IPv6Service (TODO): Skipping router_gateway port {} for add event", port);
61             return;
62         }
63         if (Ipv6ServiceConstants.DEVICE_OWNER_DHCP.equalsIgnoreCase(port.getDeviceOwner())) {
64             LOG.info("IPv6Service: Skipping network_dhcp port {} for add event", port);
65             return;
66         }
67
68         LOG.debug("Add port notification handler is invoked for port {} ", port);
69         for (FixedIps fixedip : port.nonnullFixedIps()) {
70             if (fixedip.getIpAddress().getIpv4Address() != null) {
71                 continue;
72             }
73             addInterfaceInfo(port, fixedip);
74         }
75     }
76
77     @Override
78     protected void remove(InstanceIdentifier<Port> identifier, Port port) {
79         if (Ipv6ServiceConstants.NETWORK_ROUTER_GATEWAY.equalsIgnoreCase(port.getDeviceOwner())) {
80             // Todo: revisit when IPv6 north-south support is implemented.
81             LOG.info("IPv6Service (TODO): Skipping router_gateway port {} for remove event", port);
82             return;
83         }
84         if (Ipv6ServiceConstants.DEVICE_OWNER_DHCP.equalsIgnoreCase(port.getDeviceOwner())) {
85             LOG.info("IPv6Service: Skipping network_dhcp port {} for remove event", port);
86             return;
87         }
88
89         LOG.debug("remove port notification handler is invoked for port {}", port);
90         ifMgr.removePort(port.getUuid());
91     }
92
93     @Override
94     protected void update(InstanceIdentifier<Port> identifier, Port original, Port update) {
95         if (Ipv6ServiceConstants.NETWORK_ROUTER_GATEWAY.equalsIgnoreCase(update.getDeviceOwner())) {
96             // Todo: revisit when IPv6 north-south support is implemented.
97             LOG.info("IPv6Service (TODO): Skipping router_gateway port {} for update event", update);
98             return;
99         }
100         if (Ipv6ServiceConstants.DEVICE_OWNER_DHCP.equalsIgnoreCase(update.getDeviceOwner())) {
101             LOG.info("IPv6Service: Skipping network_dhcp port {} for update event", update);
102             return;
103         }
104
105         LOG.debug("update port notification handler is invoked for port {} ", update);
106
107         Set<FixedIps> ipsBefore = getFixedIpSet(original.getFixedIps());
108         Set<FixedIps> ipsAfter = getFixedIpSet(update.getFixedIps());
109
110         Set<FixedIps> deletedIps = new HashSet<>(ipsBefore);
111         deletedIps.removeAll(ipsAfter);
112
113         if (!ipsBefore.equals(ipsAfter)) {
114             Boolean portIncludesV6Address = Boolean.FALSE;
115             ifMgr.clearAnyExistingSubnetInfo(update.getUuid());
116
117             Set<FixedIps> remainingIps = new HashSet<>(ipsAfter);
118             remainingIps.removeAll(deletedIps);
119             for (FixedIps fixedip : remainingIps) {
120                 if (fixedip.getIpAddress().getIpv4Address() != null) {
121                     continue;
122                 }
123                 portIncludesV6Address = Boolean.TRUE;
124                 addInterfaceInfo(update, fixedip);
125             }
126
127             if (update.getDeviceOwner().equalsIgnoreCase(Ipv6ServiceConstants.NETWORK_ROUTER_INTERFACE)) {
128                 ifMgr.updateRouterIntf(update.getUuid(), new Uuid(update.getDeviceId()), update.getFixedIps(),
129                         deletedIps);
130             } else {
131                 ifMgr.updateHostIntf(update.getUuid(), portIncludesV6Address);
132             }
133         }
134         //Neutron Port update with proper device owner information
135         if ((Strings.isNullOrEmpty(original.getDeviceOwner()) || Strings.isNullOrEmpty(original.getDeviceId()))
136                 && !Strings.isNullOrEmpty(update.getDeviceOwner()) && !Strings.isNullOrEmpty(update.getDeviceId())) {
137             for (FixedIps fixedip : update.nonnullFixedIps()) {
138                 if (fixedip.getIpAddress().getIpv4Address() != null) {
139                     continue;
140                 }
141                 addInterfaceInfo(update, fixedip);
142             }
143         }
144     }
145
146     protected void addInterfaceInfo(Port port, FixedIps fixedip) {
147         if (Ipv6ServiceConstants.NETWORK_ROUTER_INTERFACE.equalsIgnoreCase(port.getDeviceOwner())) {
148             LOG.info("IPv6: addInterfaceInfo is invoked for a router interface {}, fixedIp: {}", port, fixedip);
149             // Add router interface
150             ifMgr.addRouterIntf(port.getUuid(),
151                     new Uuid(port.getDeviceId()),
152                     fixedip.getSubnetId(),
153                     port.getNetworkId(),
154                     fixedip.getIpAddress(),
155                     port.getMacAddress().getValue(),
156                     port.getDeviceOwner());
157         } else {
158             LOG.info("IPv6: addInterfaceInfo is invoked for a host interface {}, fixedIp: {}", port, fixedip);
159             // Add host interface
160             ifMgr.addHostIntf(port.getUuid(),
161                     fixedip.getSubnetId(),
162                     port.getNetworkId(),
163                     fixedip.getIpAddress(),
164                     port.getMacAddress().getValue(),
165                     port.getDeviceOwner());
166         }
167     }
168
169     private Set<FixedIps> getFixedIpSet(@Nullable List<FixedIps> fixedIps) {
170         return fixedIps != null ? new HashSet<>(fixedIps) : Collections.emptySet();
171     }
172
173     @Override
174     protected NeutronPortChangeListener getDataTreeChangeListener() {
175         return NeutronPortChangeListener.this;
176     }
177 }