Merge "Add UT for SouthboundMapper and SouthboundProvider"
[netvirt.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / NetworkHandler.java
1 /*
2  * Copyright (c) 2013, 2015 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
9 package org.opendaylight.ovsdb.openstack.netvirt;
10
11 import java.net.HttpURLConnection;
12 import java.util.List;
13
14 import org.opendaylight.neutron.spi.INeutronNetworkAware;
15 import org.opendaylight.neutron.spi.INeutronNetworkCRUD;
16 import org.opendaylight.neutron.spi.NeutronNetwork;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
19 import org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher;
20 import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
21 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
22 import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
23 import org.opendaylight.ovsdb.openstack.netvirt.impl.NeutronL3Adapter;
24 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
26 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
27
28 import org.osgi.framework.ServiceReference;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 /**
33  * Handle requests for Neutron Network.
34  */
35 public class NetworkHandler extends AbstractHandler implements INeutronNetworkAware, ConfigInterface {
36     private static final Logger LOG = LoggerFactory.getLogger(NetworkHandler.class);
37     public static final String NETWORK_TYPE_VXLAN = "vxlan";
38     public static final String NETWORK_TYPE_GRE = "gre";
39     public static final String NETWORK_TYPE_VLAN = "vlan";
40
41     // The implementation for each of these services is resolved by the OSGi Service Manager
42     private volatile TenantNetworkManager tenantNetworkManager;
43     private volatile BridgeConfigurationManager bridgeConfigurationManager;
44     private volatile NodeCacheManager nodeCacheManager;
45     private volatile INeutronNetworkCRUD neutronNetworkCache;
46     private volatile NeutronL3Adapter neutronL3Adapter;
47     private volatile Southbound southbound;
48
49     /**
50      * Invoked when a network creation is requested
51      * to indicate if the specified network can be created.
52      *
53      * @param network  An instance of proposed new Neutron Network object.
54      * @return A HTTP status code to the creation request.
55      */
56     @Override
57     public int canCreateNetwork(NeutronNetwork network) {
58         if (network.isShared() && !network.getRouterExternal()) {
59             LOG.error("Shared attribute is only supported on external networks");
60             return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
61         }
62
63         return HttpURLConnection.HTTP_OK;
64     }
65
66     /**
67      * Invoked to take action after a network has been created.
68      *
69      * @param network  An instance of new Neutron Network object.
70      */
71     @Override
72     public void neutronNetworkCreated(NeutronNetwork network) {
73         enqueueEvent(new NorthboundEvent(network, Action.ADD));
74     }
75     private void doNeutronNetworkCreated(NeutronNetwork network) {
76         neutronL3Adapter.handleNeutronNetworkEvent(network, Action.ADD);
77     }
78
79     /**
80      * Invoked when a network update is requested
81      * to indicate if the specified network can be changed
82      * using the specified delta.
83      *
84      * @param delta     Updates to the network object using patch semantics.
85      * @param original  An instance of the Neutron Network object
86      *                  to be updated.
87      * @return A HTTP status code to the update request.
88      */
89     @Override
90     public int canUpdateNetwork(NeutronNetwork delta,
91                                 NeutronNetwork original) {
92         if (delta.isShared() && !delta.getRouterExternal()) {
93             LOG.error("Shared attribute is only supported on external networks");
94             return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
95         }
96
97         return HttpURLConnection.HTTP_OK;
98     }
99
100     /**
101      * Invoked to take action after a network has been updated.
102      *
103      * @param network An instance of modified Neutron Network object.
104      */
105     @Override
106     public void neutronNetworkUpdated(NeutronNetwork network) {
107         enqueueEvent(new NorthboundEvent(network, Action.UPDATE));
108     }
109     private void doNeutronNetworkUpdated(NeutronNetwork network) {
110         neutronL3Adapter.handleNeutronNetworkEvent(network, Action.UPDATE);
111     }
112
113     /**
114      * Invoked when a network deletion is requested
115      * to indicate if the specified network can be deleted.
116      *
117      * @param network  An instance of the Neutron Network object to be deleted.
118      * @return A HTTP status code to the deletion request.
119      */
120     @Override
121     public int canDeleteNetwork(NeutronNetwork network) {
122         return HttpURLConnection.HTTP_OK;
123     }
124
125     /**
126      * Invoked to take action after a network has been deleted.
127      *
128      * @param network  An instance of deleted Neutron Network object.
129      */
130     @Override
131     public void neutronNetworkDeleted(NeutronNetwork network) {
132         enqueueEvent(new NorthboundEvent(network, Action.DELETE));
133     }
134     private void doNeutronNetworkDeleted(NeutronNetwork network) {
135         neutronL3Adapter.handleNeutronNetworkEvent(network, Action.DELETE);
136
137         /* Is this the last Neutron tenant network */
138         List <NeutronNetwork> networks;
139         if (neutronNetworkCache != null) {
140             networks = neutronNetworkCache.getAllNetworks();
141             if (networks.isEmpty()) {
142                 LOG.trace("neutronNetworkDeleted: last tenant network, delete tunnel ports...");
143                 List<Node> nodes = nodeCacheManager.getNodes();
144
145                 for (Node node : nodes) {
146                     List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(node);
147                     try {
148                         List<OvsdbTerminationPointAugmentation> ports = southbound.getTerminationPointsOfBridge(node);
149                         for (OvsdbTerminationPointAugmentation port : ports) {
150                             if (southbound.isTunnel(port)) {
151                                 LOG.trace("Delete tunnel interface {}", port.getName());
152                                 southbound.deleteTerminationPoint(node, port.getName());
153                             } else if (!phyIfName.isEmpty() && phyIfName.contains(port.getName())) {
154                                 LOG.trace("Delete physical interface {}", port.getName());
155                                 southbound.deleteTerminationPoint(node, port.getName());
156                             }
157                         }
158                     } catch (Exception e) {
159                         LOG.error("Exception during handlingNeutron network delete", e);
160                     }
161                 }
162             }
163         }
164         tenantNetworkManager.networkDeleted(network.getID());
165     }
166
167     /**
168      * Process the event.
169      *
170      * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
171      * @see org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher
172      */
173     @Override
174     public void processEvent(AbstractEvent abstractEvent) {
175         if (!(abstractEvent instanceof NorthboundEvent)) {
176             LOG.error("Unable to process abstract event {}", abstractEvent);
177             return;
178         }
179         NorthboundEvent ev = (NorthboundEvent) abstractEvent;
180         switch (ev.getAction()) {
181             case ADD:
182                 doNeutronNetworkCreated(ev.getNeutronNetwork());
183                 break;
184             case UPDATE:
185                 doNeutronNetworkUpdated(ev.getNeutronNetwork());
186                 break;
187             case DELETE:
188                 doNeutronNetworkDeleted(ev.getNeutronNetwork());
189                 break;
190             default:
191                 LOG.warn("Unable to process event action {}", ev.getAction());
192                 break;
193         }
194     }
195
196     @Override
197     public void setDependencies(ServiceReference serviceReference) {
198         tenantNetworkManager =
199                 (TenantNetworkManager) ServiceHelper.getGlobalInstance(TenantNetworkManager.class, this);
200         bridgeConfigurationManager =
201                 (BridgeConfigurationManager) ServiceHelper.getGlobalInstance(BridgeConfigurationManager.class, this);
202         nodeCacheManager =
203                 (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
204         neutronL3Adapter =
205                 (NeutronL3Adapter) ServiceHelper.getGlobalInstance(NeutronL3Adapter.class, this);
206         southbound =
207                 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
208         eventDispatcher =
209                 (EventDispatcher) ServiceHelper.getGlobalInstance(EventDispatcher.class, this);
210         eventDispatcher.eventHandlerAdded(serviceReference, this);
211     }
212
213     @Override
214     public void setDependencies(Object impl) {
215         if (impl instanceof INeutronNetworkCRUD) {
216             neutronNetworkCache = (INeutronNetworkCRUD)impl;
217         }
218     }
219 }