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