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