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