2 * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.ovsdb.openstack.netvirt.translator.iaware.impl;
10 import java.util.ArrayList;
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.List;
15 import java.util.Map.Entry;
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.ovsdb.openstack.netvirt.translator.NeutronPort;
25 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronPort_AllowedAddressPairs;
26 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronPort_ExtraDHCPOption;
27 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronPort_VIFDetail;
28 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup;
29 import org.opendaylight.ovsdb.openstack.netvirt.translator.Neutron_IPs;
30 import org.opendaylight.ovsdb.openstack.netvirt.translator.crud.INeutronSecurityGroupCRUD;
31 import org.opendaylight.ovsdb.openstack.netvirt.translator.crud.NeutronCRUDInterfaces;
32 import org.opendaylight.ovsdb.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.rev150712.Neutron;
42 import org.opendaylight.yangtools.concepts.ListenerRegistration;
43 import org.opendaylight.yangtools.yang.binding.DataObject;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
48 public class NeutronPortChangeListener implements ClusteredDataChangeListener, AutoCloseable{
49 private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class);
51 private ListenerRegistration<DataChangeListener> registration;
52 private DataBroker db;
54 public NeutronPortChangeListener(DataBroker db){
56 InstanceIdentifier<Port> path = InstanceIdentifier
57 .create(Neutron.class)
60 LOG.debug("Register listener for Neutron Port model data changes");
62 this.db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, path, this, DataChangeScope.ONE);
67 public void onDataChanged(
68 AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
69 LOG.trace("Data changes : {}",changes);
71 Object[] subscribers = NeutronIAwareUtil.getInstances(INeutronPortAware.class, this);
72 createPort(changes, subscribers);
73 updatePort(changes, subscribers);
74 deletePort(changes, subscribers);
77 private void createPort(
78 AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes,
79 Object[] subscribers) {
80 for (Entry<InstanceIdentifier<?>, DataObject> newPort : changes.getCreatedData().entrySet()) {
81 if(newPort.getValue() instanceof Port){
82 NeutronPort port = fromMd((Port)newPort.getValue());
83 for(Object entry: subscribers){
84 INeutronPortAware subscriber = (INeutronPortAware)entry;
85 subscriber.neutronPortCreated(port);
91 private void updatePort(
92 AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes,
93 Object[] subscribers) {
94 Map<String, NeutronPort> originalPortMap = getChangedPorts(changes.getOriginalData());
95 for (Entry<InstanceIdentifier<?>, DataObject> updatePort : changes.getUpdatedData().entrySet()) {
96 if (updatePort.getValue() instanceof Port) {
97 NeutronPort port = fromMd((Port)updatePort.getValue());
98 NeutronPort originalPort = originalPortMap.get(port.getID());
99 if (originalPort != null) {
100 port.setOriginalPort(originalPort);
102 LOG.warn("Original Port data is missing");
104 for (Object entry: subscribers) {
105 INeutronPortAware subscriber = (INeutronPortAware)entry;
106 subscriber.neutronPortUpdated(port);
112 private void deletePort(
113 AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes,
114 Object[] subscribers) {
115 for (InstanceIdentifier<?> deletedPortPath : changes.getRemovedPaths()) {
116 if(deletedPortPath.getTargetType().equals(Port.class)){
117 NeutronPort port = fromMd((Port)changes.getOriginalData().get(deletedPortPath));
118 for(Object entry: subscribers){
119 INeutronPortAware subscriber = (INeutronPortAware)entry;
120 subscriber.neutronPortDeleted(port);
127 * This method is borrowed from NeutronPortInterface.java class of Neutron Northbound class.
128 * We will be utilizing similar code from other classes from the same package of neutron project.
130 private NeutronPort fromMd(Port port) {
132 NeutronPort result = new NeutronPort();
133 result.setAdminStateUp(port.isAdminStateUp());
134 if (port.getAllowedAddressPairs() != null) {
135 List<NeutronPort_AllowedAddressPairs> pairs = new ArrayList<>();
136 for (AllowedAddressPairs mdPair : port.getAllowedAddressPairs()) {
137 NeutronPort_AllowedAddressPairs pair = new NeutronPort_AllowedAddressPairs();
138 pair.setIpAddress(mdPair.getIpAddress());
139 pair.setMacAddress(mdPair.getMacAddress());
142 result.setAllowedAddressPairs(pairs);
144 result.setDeviceID(port.getDeviceId());
145 result.setDeviceOwner(port.getDeviceOwner());
146 if (port.getExtraDhcpOpts() != null) {
147 List<NeutronPort_ExtraDHCPOption> options = new ArrayList<>();
148 for (ExtraDhcpOpts opt : port.getExtraDhcpOpts()) {
149 NeutronPort_ExtraDHCPOption arg = new NeutronPort_ExtraDHCPOption();
150 arg.setName(opt.getOptName());
151 arg.setValue(opt.getOptValue());
154 result.setExtraDHCPOptions(options);
156 if (port.getFixedIps() != null) {
157 List<Neutron_IPs> ips = new ArrayList<>();
158 for (FixedIps mdIP : port.getFixedIps()) {
159 Neutron_IPs ip = new Neutron_IPs();
160 ip.setIpAddress(String.valueOf(mdIP.getIpAddress().getValue()));
161 ip.setSubnetUUID(mdIP.getSubnetId().getValue());
164 result.setFixedIPs(ips);
166 result.setMacAddress(port.getMacAddress());
167 result.setName(port.getName());
168 result.setNetworkUUID(String.valueOf(port.getNetworkId().getValue()));
169 if (port.getSecurityGroups() != null) {
170 Set<NeutronSecurityGroup> allGroups = new HashSet<>();
171 NeutronCRUDInterfaces interfaces = new NeutronCRUDInterfaces().fetchINeutronSecurityGroupCRUD(this);
172 INeutronSecurityGroupCRUD sgIf = interfaces.getSecurityGroupInterface();
173 for (Uuid sgUuid : port.getSecurityGroups()) {
174 NeutronSecurityGroup secGroup = sgIf.getNeutronSecurityGroup(sgUuid.getValue());
175 if (secGroup != null) {
176 allGroups.add(sgIf.getNeutronSecurityGroup(sgUuid.getValue()));
179 List<NeutronSecurityGroup> groups = new ArrayList<>();
180 groups.addAll(allGroups);
181 result.setSecurityGroups(groups);
183 result.setStatus(port.getStatus());
184 if (port.getTenantId() != null) {
185 result.setTenantID(String.valueOf(port.getTenantId().getValue()).replace("-", ""));
187 result.setPortUUID(String.valueOf(port.getUuid().getValue()));
188 addExtensions(port, result);
192 protected void addExtensions(Port port, NeutronPort result) {
193 PortBindingExtension binding = port.getAugmentation(PortBindingExtension.class);
194 result.setBindinghostID(binding.getHostId());
195 if (binding.getVifDetails() != null) {
196 List<NeutronPort_VIFDetail> details = new ArrayList<>();
197 for (VifDetails vifDetail : binding.getVifDetails()) {
198 NeutronPort_VIFDetail detail = new NeutronPort_VIFDetail();
199 detail.setPortFilter(vifDetail.isPortFilter());
200 detail.setOvsHybridPlug(vifDetail.isOvsHybridPlug());
203 result.setVIFDetail(details);
205 result.setBindingvifType(binding.getVifType());
206 result.setBindingvnicType(binding.getVnicType());
209 private Map<String,NeutronPort> getChangedPorts(Map<InstanceIdentifier<?>, DataObject> changedData) {
210 LOG.trace("getChangedPorts:" + changedData);
211 Map<String,NeutronPort> portMap = new HashMap<>();
212 for (Map.Entry<InstanceIdentifier<?>, DataObject> changed : changedData.entrySet()) {
213 if (changed.getValue() instanceof Port) {
214 NeutronPort port = fromMd((Port)changed.getValue());
215 portMap.put(port.getID(), port);
222 public void close() throws Exception {
223 registration.close();