Merge "L3 Neutron plumbing"
[ovsdb.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / NetworkHandler.java
1 /*
2  * Copyright (C) 2013 Red Hat, Inc.
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  * Authors : Madhu Venugopal, Brent Salisbury, Hsin-Yi Shen
9  */
10 package org.opendaylight.ovsdb.openstack.netvirt;
11
12 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware;
13 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
14 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
15 import org.opendaylight.controller.sal.core.Node;
16 import org.opendaylight.ovsdb.lib.notation.Row;
17 import org.opendaylight.ovsdb.lib.notation.UUID;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
19 import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
20 import org.opendaylight.ovsdb.openstack.netvirt.impl.NeutronL3Adapter;
21 import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
22 import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
23 import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryListener;
24 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
25 import org.opendaylight.ovsdb.schema.openvswitch.Port;
26
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 import java.net.HttpURLConnection;
31 import java.util.List;
32 import java.util.concurrent.ConcurrentMap;
33
34 /**
35  * Handle requests for Neutron Network.
36  */
37 public class NetworkHandler extends AbstractHandler
38                             implements INeutronNetworkAware {
39
40     public static final String NETWORK_TYPE_VXLAN = "vxlan";
41     public static final String NETWORK_TYPE_GRE = "gre";
42     public static final String NETWORK_TYPE_VLAN = "vlan";
43
44     /**
45      * Logger instance.
46      */
47     static final Logger logger = LoggerFactory.getLogger(NetworkHandler.class);
48
49     // The implementation for each of these services is resolved by the OSGi Service Manager
50     private volatile TenantNetworkManager tenantNetworkManager;
51     private volatile BridgeConfigurationManager bridgeConfigurationManager;
52     private volatile org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService configurationService;
53     private volatile OvsdbConfigurationService ovsdbConfigurationService;
54     private volatile OvsdbConnectionService connectionService;
55     private volatile INeutronNetworkCRUD neutronNetworkCache;
56     private volatile OvsdbInventoryListener ovsdbInventoryListener;
57     private volatile NeutronL3Adapter neutronL3Adapter;
58
59     /**
60      * Invoked when a network creation is requested
61      * to indicate if the specified network can be created.
62      *
63      * @param network  An instance of proposed new Neutron Network object.
64      * @return A HTTP status code to the creation request.
65      */
66     @Override
67     public int canCreateNetwork(NeutronNetwork network) {
68         if (network.isShared()) {
69             logger.error(" Network shared attribute not supported ");
70             return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
71         }
72
73         return HttpURLConnection.HTTP_CREATED;
74     }
75
76     /**
77      * Invoked to take action after a network has been created.
78      *
79      * @param network  An instance of new Neutron Network object.
80      */
81     @Override
82     public void neutronNetworkCreated(NeutronNetwork network) {
83         int result = HttpURLConnection.HTTP_BAD_REQUEST;
84         logger.trace("neutronNetworkCreated: network: {}", network);
85         result = canCreateNetwork(network);
86         if (result != HttpURLConnection.HTTP_CREATED) {
87             logger.debug("Network creation failed {} ", result);
88             return;
89         }
90
91         enqueueEvent(new NorthboundEvent(network, AbstractEvent.Action.ADD));
92     }
93     private void doNeutronNetworkCreated(NeutronNetwork network) {
94         neutronL3Adapter.handleNeutronNetworkEvent(network, AbstractEvent.Action.ADD);
95     }
96
97     /**
98      * Invoked when a network update is requested
99      * to indicate if the specified network can be changed
100      * using the specified delta.
101      *
102      * @param delta     Updates to the network object using patch semantics.
103      * @param original  An instance of the Neutron Network object
104      *                  to be updated.
105      * @return A HTTP status code to the update request.
106      */
107     @Override
108     public int canUpdateNetwork(NeutronNetwork delta,
109                                 NeutronNetwork original) {
110         logger.trace("canUpdateNetwork: network delta {} --- original {}", delta, original);
111         return HttpURLConnection.HTTP_OK;
112     }
113
114     /**
115      * Invoked to take action after a network has been updated.
116      *
117      * @param network An instance of modified Neutron Network object.
118      */
119     @Override
120     public void neutronNetworkUpdated(NeutronNetwork network) {
121         enqueueEvent(new NorthboundEvent(network, AbstractEvent.Action.UPDATE));
122     }
123     private void doNeutronNetworkUpdated(NeutronNetwork network) {
124         neutronL3Adapter.handleNeutronNetworkEvent(network, AbstractEvent.Action.UPDATE);
125     }
126
127     /**
128      * Invoked when a network deletion is requested
129      * to indicate if the specified network can be deleted.
130      *
131      * @param network  An instance of the Neutron Network object to be deleted.
132      * @return A HTTP status code to the deletion request.
133      */
134     @Override
135     public int canDeleteNetwork(NeutronNetwork network) {
136         return HttpURLConnection.HTTP_OK;
137     }
138
139     /**
140      * Invoked to take action after a network has been deleted.
141      *
142      * @param network  An instance of deleted Neutron Network object.
143      */
144     @Override
145     public void neutronNetworkDeleted(NeutronNetwork network) {
146         enqueueEvent(new NorthboundEvent(network, AbstractEvent.Action.DELETE));
147     }
148     private void doNeutronNetworkDeleted(NeutronNetwork network) {
149         neutronL3Adapter.handleNeutronNetworkEvent(network, AbstractEvent.Action.DELETE);
150
151         int result = canDeleteNetwork(network);
152         logger.trace("canDeleteNetwork: network: {}", network);
153         if  (result != HttpURLConnection.HTTP_OK) {
154             logger.error(" deleteNetwork validation failed for result - {} ",
155                     result);
156             return;
157         }
158         /* Is this the last Neutron tenant network */
159         List <NeutronNetwork> networks;
160         if (neutronNetworkCache != null) {
161             networks = neutronNetworkCache.getAllNetworks();
162             if (networks.isEmpty()) {
163                 logger.trace("neutronNetworkDeleted: last tenant network, delete tunnel ports...");
164                 List<Node> nodes = connectionService.getNodes();
165
166                 for (Node node : nodes) {
167                     List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(node);
168                     try {
169                         ConcurrentMap<String, Row> ports =
170                                 this.ovsdbConfigurationService.getRows(node,
171                                                                 ovsdbConfigurationService.getTableName(node, Port.class));
172                         if (ports != null) {
173                             for (Row portRow : ports.values()) {
174                                 Port port = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
175                                 for (UUID interfaceUuid : port.getInterfacesColumn().getData()) {
176                                     Interface interfaceRow = (Interface) ovsdbConfigurationService
177                                             .getRow(node,
178                                                     ovsdbConfigurationService.getTableName(node, Interface.class),
179                                                     interfaceUuid.toString());
180
181                                     String interfaceType = interfaceRow.getTypeColumn().getData();
182                                     if (interfaceType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)
183                                         || interfaceType.equalsIgnoreCase(
184                                             NetworkHandler.NETWORK_TYPE_GRE)) {
185                                         /* delete tunnel ports on this node */
186                                         logger.trace("Delete tunnel interface {}", interfaceRow);
187                                         ovsdbConfigurationService.deleteRow(node,
188                                                                      ovsdbConfigurationService.getTableName(node, Port.class),
189                                                                      port.getUuid().toString());
190                                         break;
191                                     } else if (!phyIfName.isEmpty() && phyIfName.contains(interfaceRow.getName())) {
192                                         logger.trace("Delete physical interface {}", interfaceRow);
193                                         ovsdbConfigurationService.deleteRow(node,
194                                                                      ovsdbConfigurationService.getTableName(node, Port.class),
195                                                                      port.getUuid().toString());
196                                         break;
197                                     }
198                                 }
199                             }
200                         }
201                     } catch (Exception e) {
202                         logger.error("Exception during handlingNeutron network delete");
203                     }
204                 }
205             }
206         }
207         tenantNetworkManager.networkDeleted(network.getID());
208     }
209
210     /**
211      * Process the event.
212      *
213      * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
214      * @see org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher
215      */
216     @Override
217     public void processEvent(AbstractEvent abstractEvent) {
218         if (!(abstractEvent instanceof NorthboundEvent)) {
219             logger.error("Unable to process abstract event " + abstractEvent);
220             return;
221         }
222         NorthboundEvent ev = (NorthboundEvent) abstractEvent;
223         switch (ev.getAction()) {
224             case ADD:
225                 doNeutronNetworkCreated(ev.getNeutronNetwork());
226                 break;
227             case UPDATE:
228                 doNeutronNetworkUpdated(ev.getNeutronNetwork());
229                 break;
230             case DELETE:
231                 doNeutronNetworkDeleted(ev.getNeutronNetwork());
232                 break;
233             default:
234                 logger.warn("Unable to process event action " + ev.getAction());
235                 break;
236         }
237     }
238
239 }