Add blueprint wiring for neutronvpn
[netvirt.git] / vpnservice / neutronvpn / neutronvpn-impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronHostConfigChangeListener.java
1 /*
2  * Copyright (c) 2016 Intel Corporation.  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.neutronvpn;
9
10 import com.google.common.collect.Maps;
11 import java.util.Map;
12 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
13 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
14 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
17 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
18 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.hostconfig.rev150712.hostconfig.attributes.Hostconfigs;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.hostconfig.rev150712.hostconfig.attributes.hostconfigs.Hostconfig;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.hostconfig.rev150712.hostconfig.attributes.hostconfigs.HostconfigBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchExternalIds;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
26 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
28 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
29 import org.opendaylight.yangtools.concepts.ListenerRegistration;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 public class NeutronHostConfigChangeListener extends AbstractDataChangeListener<Node> implements AutoCloseable {
35     private static final Logger LOG = LoggerFactory.getLogger(NeutronHostConfigChangeListener.class);
36     private ListenerRegistration<DataChangeListener>listenerRegistration;
37     private final DataBroker dataBroker;
38     private final SouthboundUtils southboundUtils;
39     private final MdsalUtils mdsalUtils;
40     private static final String OS_HOST_CONFIG_HOST_ID_KEY = "odl_os_hostconfig_hostid";
41     private static final String OS_HOST_CONFIG_CONFIG_KEY_PREFIX = "odl_os_hostconfig_config_odl_";
42     private static int HOST_TYPE_STR_LEN = 8;
43
44     private enum Action {
45         ADD,
46         UPDATE,
47         DELETE
48     }
49
50     public NeutronHostConfigChangeListener(final DataBroker dataBroker){
51         super(Node.class);
52         this.dataBroker = dataBroker;
53         this.mdsalUtils = new MdsalUtils(dataBroker);
54         this.southboundUtils = new SouthboundUtils(mdsalUtils);
55     }
56
57     public void start() {
58         LOG.info("{} start", getClass().getSimpleName());
59         listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
60                 getWildCardPath(), this, AsyncDataBroker.DataChangeScope.SUBTREE);
61     }
62
63     private InstanceIdentifier<Node> getWildCardPath(){
64         return InstanceIdentifier
65                 .create(NetworkTopology.class)
66                 .child(Topology.class,new TopologyKey(SouthboundUtils.OVSDB_TOPOLOGY_ID))
67                 .child(Node.class);
68     }
69
70     @Override
71     public void close() throws Exception {
72         if (listenerRegistration != null) {
73             listenerRegistration.close();
74             listenerRegistration = null;
75         }
76         LOG.info("{} close", getClass().getSimpleName());
77     }
78
79     @Override
80     protected void remove(InstanceIdentifier<Node>identifier, Node del){
81         LOG.trace("NeutronHostConfigChangeListener.remove {}",del);
82         updateHostConfig(del, Action.DELETE);
83     }
84
85     @Override
86     protected void update(InstanceIdentifier<Node>identifier, Node original, Node update){
87         LOG.trace("NeutronHostConfigChangeListener.update {}",update);
88         updateHostConfig(update, Action.UPDATE);
89     }
90
91     @Override
92     protected void add(InstanceIdentifier<Node>identifier, Node add){
93         LOG.trace("NeutronHostConfigChangeListener.add {}",add);
94         updateHostConfig(add, Action.ADD);
95
96     }
97
98     private void updateHostConfig(Node node, Action action) {
99         String hostId = getExternalId(node, OS_HOST_CONFIG_HOST_ID_KEY);
100         if (hostId == null){
101             return;
102         }
103         for(Map.Entry<String,String> entry : extractHostConfig(node).entrySet()) {
104             updateMdsal(buildHostConfigInfo(hostId, entry.getKey(), entry.getValue()), action);
105         }
106     }
107
108     private Map<String, String> extractHostConfig(Node node) {
109         Map<String, String> config = Maps.newHashMap();
110         OvsdbNodeAugmentation ovsdbNode = getOvsdbNodeAugmentation(node);
111         if (ovsdbNode != null && ovsdbNode.getOpenvswitchExternalIds() != null) {
112             for (OpenvswitchExternalIds openvswitchExternalIds : ovsdbNode.getOpenvswitchExternalIds()) {
113                 if (openvswitchExternalIds.getExternalIdKey().startsWith(OS_HOST_CONFIG_CONFIG_KEY_PREFIX)) {
114                     // Extract the host type. Max 8 characters after
115                     // suffix OS_HOST_CONFIG_CONFIG_KEY_PREFIX.length()
116                     String hostType = openvswitchExternalIds.getExternalIdKey().substring(
117                             OS_HOST_CONFIG_CONFIG_KEY_PREFIX.length());
118                     if (null != hostType && hostType.length() > 0) {
119                         if (hostType.length() > HOST_TYPE_STR_LEN) {
120                             hostType = hostType.substring(0, HOST_TYPE_STR_LEN);
121                         }
122                         hostType = "ODL " + hostType.toUpperCase();
123                         if (null != openvswitchExternalIds.getExternalIdValue())
124                             config.put(hostType, openvswitchExternalIds.getExternalIdValue());
125                     }
126                 }
127             }
128         }
129         return config;
130     }
131
132     private void updateMdsal(Hostconfig hostConfig, Action action) {
133         boolean result;
134         InstanceIdentifier<Hostconfig> hostConfigId;
135         if (hostConfig == null) {
136             return;
137         }
138         switch (action) {
139             case ADD:
140             case UPDATE:
141                 hostConfigId = createInstanceIdentifier(hostConfig);
142                 result = mdsalUtils.put(LogicalDatastoreType.OPERATIONAL, hostConfigId, hostConfig);
143                 LOG.trace("Add Node: result: {}", result);
144                 break;
145             case DELETE:
146                 hostConfigId = createInstanceIdentifier(hostConfig);
147                 result = mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, hostConfigId);
148                 LOG.trace("Delete Node: result: {}", result);
149                 break;
150         }
151     }
152
153     private Hostconfig buildHostConfigInfo(String hostId, String hostType, String hostConfig) {
154         HostconfigBuilder hostconfigBuilder = new HostconfigBuilder();
155         hostconfigBuilder.setHostId(hostId);
156         hostconfigBuilder.setHostType(hostType);
157         hostconfigBuilder.setConfig(hostConfig);
158         return hostconfigBuilder.build();
159     }
160
161     private String getExternalId(Node node, String key) {
162         OvsdbNodeAugmentation ovsdbNode = getOvsdbNodeAugmentation(node);
163         if (ovsdbNode != null && ovsdbNode.getOpenvswitchExternalIds() != null) {
164             for (OpenvswitchExternalIds openvswitchExternalIds : ovsdbNode.getOpenvswitchExternalIds()) {
165                 if (openvswitchExternalIds.getExternalIdKey().equals(key)) {
166                     return openvswitchExternalIds.getExternalIdValue();
167                 }
168             }
169         }
170         return null;
171     }
172
173     private OvsdbNodeAugmentation getOvsdbNodeAugmentation(Node node)
174     {
175         OvsdbNodeAugmentation ovsdbNode = southboundUtils.extractOvsdbNode(node);
176         if (ovsdbNode == null) {
177             Node nodeFromReadOvsdbNode = southboundUtils.readOvsdbNode(node);
178             if (nodeFromReadOvsdbNode != null) {
179                 ovsdbNode = southboundUtils.extractOvsdbNode(nodeFromReadOvsdbNode);
180             }
181         }
182         return ovsdbNode;
183     }
184
185     private InstanceIdentifier<Hostconfig> createInstanceIdentifier() {
186         return InstanceIdentifier.create(Neutron.class)
187                 .child(Hostconfigs.class)
188                 .child(Hostconfig.class);
189     }
190
191     private InstanceIdentifier<Hostconfig> createInstanceIdentifier(Hostconfig hostconfig) {
192         return InstanceIdentifier.create(Neutron.class)
193                 .child(Hostconfigs.class)
194                 .child(Hostconfig.class, hostconfig.getKey());
195     }
196 }