neutron: unbreak of neutron northbound yang model revise
[netvirt.git] / openstack / net-virt / src / main / java / org / opendaylight / netvirt / openstack / netvirt / translator / iaware / impl / NeutronPortChangeListener.java
1 /*
2  * Copyright (c) 2015 Brocade Communications Systems, 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.openstack.netvirt.translator.iaware.impl;
9
10 import java.util.ArrayList;
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Map.Entry;
16 import java.util.Set;
17
18 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
21 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
22 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronPort_AllowedAddressPairs;
25 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronPort_ExtraDHCPOption;
26 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronPort_VIFDetail;
27 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronPort;
28 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityGroup;
29 import org.opendaylight.netvirt.openstack.netvirt.translator.Neutron_IPs;
30 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronSecurityGroupCRUD;
31 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.NeutronCRUDInterfaces;
32 import org.opendaylight.netvirt.openstack.netvirt.translator.iaware.INeutronPortAware;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.binding.attributes.VifDetails;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.ExtraDhcpOpts;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.portsecurity.rev150712.PortSecurityExtension;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
43 import org.opendaylight.yangtools.concepts.ListenerRegistration;
44 import org.opendaylight.yangtools.yang.binding.DataObject;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 public class NeutronPortChangeListener implements ClusteredDataChangeListener, AutoCloseable{
50     private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class);
51
52     private ListenerRegistration<DataChangeListener> registration;
53     private DataBroker db;
54
55     public NeutronPortChangeListener(DataBroker db){
56         this.db = db;
57         InstanceIdentifier<Port> path = InstanceIdentifier
58                 .create(Neutron.class)
59                 .child(Ports.class)
60                 .child(Port.class);
61         LOG.debug("Register listener for Neutron Port model data changes");
62         registration =
63                 this.db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, path, this, DataChangeScope.ONE);
64
65     }
66
67     @Override
68     public void onDataChanged(
69             AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
70         LOG.trace("Data changes : {}",changes);
71
72         Object[] subscribers = NeutronIAwareUtil.getInstances(INeutronPortAware.class, this);
73         createPort(changes, subscribers);
74         updatePort(changes, subscribers);
75         deletePort(changes, subscribers);
76     }
77
78     private void createPort(
79             AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes,
80             Object[] subscribers) {
81         for (Entry<InstanceIdentifier<?>, DataObject> newPort : changes.getCreatedData().entrySet()) {
82                 if(newPort.getValue() instanceof Port){
83                 NeutronPort port = fromMd((Port)newPort.getValue());
84                 for(Object entry: subscribers){
85                     INeutronPortAware subscriber = (INeutronPortAware)entry;
86                     subscriber.neutronPortCreated(port);
87                 }
88                 }
89         }
90     }
91
92     private void updatePort(
93             AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes,
94             Object[] subscribers) {
95         Map<String, NeutronPort> originalPortMap = getChangedPorts(changes.getOriginalData());
96         for (Entry<InstanceIdentifier<?>, DataObject> updatePort : changes.getUpdatedData().entrySet()) {
97             if (updatePort.getValue() instanceof Port) {
98                 NeutronPort port = fromMd((Port)updatePort.getValue());
99                 NeutronPort originalPort = originalPortMap.get(port.getID());
100                 if (originalPort != null) {
101                     port.setOriginalPort(originalPort);
102                 } else {
103                     LOG.warn("Original Port data is missing");
104                 }
105                 for (Object entry: subscribers) {
106                     INeutronPortAware subscriber = (INeutronPortAware)entry;
107                     subscriber.neutronPortUpdated(port);
108                 }
109             }
110         }
111     }
112
113     private void deletePort(
114             AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes,
115             Object[] subscribers) {
116         for (InstanceIdentifier<?> deletedPortPath : changes.getRemovedPaths()) {
117             if(deletedPortPath.getTargetType().equals(Port.class)){
118                 NeutronPort port = fromMd((Port)changes.getOriginalData().get(deletedPortPath));
119                 for(Object entry: subscribers){
120                     INeutronPortAware subscriber = (INeutronPortAware)entry;
121                     subscriber.neutronPortDeleted(port);
122                 }
123             }
124         }
125     }
126
127     /*
128      * This method is borrowed from NeutronPortInterface.java class of Neutron Northbound class.
129      * We will be utilizing similar code from other classes from the same package of neutron project.
130      */
131     private NeutronPort fromMd(Port port) {
132
133         NeutronPort result = new NeutronPort();
134         result.setAdminStateUp(port.isAdminStateUp());
135         if (port.getAllowedAddressPairs() != null) {
136             List<NeutronPort_AllowedAddressPairs> pairs = new ArrayList<>();
137             for (AllowedAddressPairs mdPair : port.getAllowedAddressPairs()) {
138                 NeutronPort_AllowedAddressPairs pair = new NeutronPort_AllowedAddressPairs();
139                 pair.setIpAddress(String.valueOf(mdPair.getIpAddress().getValue()));
140                 pair.setMacAddress(mdPair.getMacAddress().getValue());
141                 pairs.add(pair);
142             }
143             result.setAllowedAddressPairs(pairs);
144         }
145         result.setDeviceID(port.getDeviceId());
146         result.setDeviceOwner(port.getDeviceOwner());
147         if (port.getExtraDhcpOpts() != null) {
148             List<NeutronPort_ExtraDHCPOption> options = new ArrayList<>();
149             for (ExtraDhcpOpts opt : port.getExtraDhcpOpts()) {
150                 NeutronPort_ExtraDHCPOption arg = new NeutronPort_ExtraDHCPOption();
151                 arg.setName(opt.getOptName());
152                 arg.setValue(opt.getOptValue());
153                 options.add(arg);
154             }
155             result.setExtraDHCPOptions(options);
156         }
157         if (port.getFixedIps() != null) {
158             List<Neutron_IPs> ips = new ArrayList<>();
159             for (FixedIps mdIP : port.getFixedIps()) {
160                 Neutron_IPs ip = new Neutron_IPs();
161                 ip.setIpAddress(String.valueOf(mdIP.getIpAddress().getValue()));
162                 ip.setSubnetUUID(mdIP.getSubnetId().getValue());
163                 ips.add(ip);
164             }
165             result.setFixedIPs(ips);
166         }
167         result.setMacAddress(port.getMacAddress().getValue());
168         result.setName(port.getName());
169         result.setNetworkUUID(String.valueOf(port.getNetworkId().getValue()));
170         if (port.getSecurityGroups() != null) {
171             Set<NeutronSecurityGroup> allGroups = new HashSet<>();
172             NeutronCRUDInterfaces interfaces = new NeutronCRUDInterfaces().fetchINeutronSecurityGroupCRUD(this);
173             INeutronSecurityGroupCRUD sgIf = interfaces.getSecurityGroupInterface();
174             for (Uuid sgUuid : port.getSecurityGroups()) {
175                 NeutronSecurityGroup secGroup = sgIf.getNeutronSecurityGroup(sgUuid.getValue());
176                 if (secGroup != null) {
177                     allGroups.add(sgIf.getNeutronSecurityGroup(sgUuid.getValue()));
178                 }
179             }
180             List<NeutronSecurityGroup> groups = new ArrayList<>();
181             groups.addAll(allGroups);
182             result.setSecurityGroups(groups);
183         }
184         result.setStatus(port.getStatus());
185         if (port.getTenantId() != null) {
186             result.setTenantID(String.valueOf(port.getTenantId().getValue()).replace("-", ""));
187         }
188         result.setPortUUID(String.valueOf(port.getUuid().getValue()));
189         addExtensions(port, result);
190         return result;
191     }
192
193     protected void addExtensions(Port port, NeutronPort result) {
194         PortBindingExtension binding = port.getAugmentation(PortBindingExtension.class);
195         result.setBindinghostID(binding.getHostId());
196         if (binding.getVifDetails() != null) {
197             final Map<String, String> details = new HashMap<String, String>(binding.getVifDetails().size());
198             for (final VifDetails vifDetail : binding.getVifDetails()) {
199                 details.put(vifDetail.getDetailsKey(), vifDetail.getValue());
200             }
201             result.setVIFDetails(details);
202         }
203         result.setBindingvifType(binding.getVifType());
204         result.setBindingvnicType(binding.getVnicType());
205         PortSecurityExtension portSecurity = port.getAugmentation(PortSecurityExtension.class);
206         if (portSecurity != null && portSecurity.isPortSecurityEnabled() != null) {
207             result.setPortSecurityEnabled(portSecurity.isPortSecurityEnabled());
208         }
209     }
210
211     private  Map<String,NeutronPort> getChangedPorts(Map<InstanceIdentifier<?>, DataObject> changedData) {
212         LOG.trace("getChangedPorts:" + changedData);
213         Map<String,NeutronPort> portMap = new HashMap<>();
214         for (Map.Entry<InstanceIdentifier<?>, DataObject> changed : changedData.entrySet()) {
215             if (changed.getValue() instanceof Port) {
216                 NeutronPort port = fromMd((Port)changed.getValue());
217                 portMap.put(port.getID(), port);
218             }
219         }
220         return portMap;
221     }
222
223     @Override
224     public void close() throws Exception {
225         registration.close();
226     }
227 }