Migrate net-virt from adsal Node to mdsal Node
[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_CREATED;
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         int result = HttpURLConnection.HTTP_BAD_REQUEST;
86         logger.trace("neutronNetworkCreated: network: {}", network);
87         result = canCreateNetwork(network);
88         if (result != HttpURLConnection.HTTP_CREATED) {
89             logger.debug("Network creation failed {} ", result);
90             return;
91         }
92
93         enqueueEvent(new NorthboundEvent(network, Action.ADD));
94     }
95     private void doNeutronNetworkCreated(NeutronNetwork network) {
96         neutronL3Adapter.handleNeutronNetworkEvent(network, Action.ADD);
97     }
98
99     /**
100      * Invoked when a network update is requested
101      * to indicate if the specified network can be changed
102      * using the specified delta.
103      *
104      * @param delta     Updates to the network object using patch semantics.
105      * @param original  An instance of the Neutron Network object
106      *                  to be updated.
107      * @return A HTTP status code to the update request.
108      */
109     @Override
110     public int canUpdateNetwork(NeutronNetwork delta,
111                                 NeutronNetwork original) {
112         logger.trace("canUpdateNetwork: network delta {} --- original {}", delta, original);
113         return HttpURLConnection.HTTP_OK;
114     }
115
116     /**
117      * Invoked to take action after a network has been updated.
118      *
119      * @param network An instance of modified Neutron Network object.
120      */
121     @Override
122     public void neutronNetworkUpdated(NeutronNetwork network) {
123         enqueueEvent(new NorthboundEvent(network, Action.UPDATE));
124     }
125     private void doNeutronNetworkUpdated(NeutronNetwork network) {
126         neutronL3Adapter.handleNeutronNetworkEvent(network, Action.UPDATE);
127     }
128
129     /**
130      * Invoked when a network deletion is requested
131      * to indicate if the specified network can be deleted.
132      *
133      * @param network  An instance of the Neutron Network object to be deleted.
134      * @return A HTTP status code to the deletion request.
135      */
136     @Override
137     public int canDeleteNetwork(NeutronNetwork network) {
138         return HttpURLConnection.HTTP_OK;
139     }
140
141     /**
142      * Invoked to take action after a network has been deleted.
143      *
144      * @param network  An instance of deleted Neutron Network object.
145      */
146     @Override
147     public void neutronNetworkDeleted(NeutronNetwork network) {
148         enqueueEvent(new NorthboundEvent(network, Action.DELETE));
149     }
150     private void doNeutronNetworkDeleted(NeutronNetwork network) {
151         neutronL3Adapter.handleNeutronNetworkEvent(network, Action.DELETE);
152
153         int result = canDeleteNetwork(network);
154         logger.trace("canDeleteNetwork: network: {}", network);
155         if  (result != HttpURLConnection.HTTP_OK) {
156             logger.error(" deleteNetwork validation failed for result - {} ",
157                     result);
158             return;
159         }
160         /* Is this the last Neutron tenant network */
161         List <NeutronNetwork> networks;
162         if (neutronNetworkCache != null) {
163             networks = neutronNetworkCache.getAllNetworks();
164             if (networks.isEmpty()) {
165                 logger.trace("neutronNetworkDeleted: last tenant network, delete tunnel ports...");
166                 List<Node> nodes = connectionService.getNodes();
167
168                 for (Node node : nodes) {
169                     List<String> phyIfName = bridgeConfigurationManager.getAllPhysicalInterfaceNames(node);
170                     try {
171                         ConcurrentMap<String, Row> ports =
172                                 this.ovsdbConfigurationService.getRows(node,
173                                                                 ovsdbConfigurationService.getTableName(node, Port.class));
174                         if (ports != null) {
175                             for (Row portRow : ports.values()) {
176                                 Port port = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
177                                 for (UUID interfaceUuid : port.getInterfacesColumn().getData()) {
178                                     Row ifaceRow = ovsdbConfigurationService
179                                             .getRow(node,
180                                                     ovsdbConfigurationService.getTableName(node, Interface.class),
181                                                     interfaceUuid.toString());
182                                     Interface iface = ovsdbConfigurationService.getTypedRow(node, Interface.class, ifaceRow);
183                                     String interfaceType = iface.getTypeColumn().getData();
184                                     if (interfaceType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)
185                                         || interfaceType.equalsIgnoreCase(
186                                             NetworkHandler.NETWORK_TYPE_GRE)) {
187                                         /* delete tunnel ports on this node */
188                                         logger.trace("Delete tunnel interface {}", iface.getName());
189                                         ovsdbConfigurationService.deleteRow(node,
190                                                                      ovsdbConfigurationService.getTableName(node, Port.class),
191                                                                      port.getUuid().toString());
192                                         break;
193                                     } else if (!phyIfName.isEmpty() && phyIfName.contains(iface.getName())) {
194                                         logger.trace("Delete physical interface {}", iface.getName());
195                                         ovsdbConfigurationService.deleteRow(node,
196                                                                      ovsdbConfigurationService.getTableName(node, Port.class),
197                                                                      port.getUuid().toString());
198                                         break;
199                                     }
200                                 }
201                             }
202                         }
203                     } catch (Exception e) {
204                         logger.error("Exception during handlingNeutron network delete", e);
205                     }
206                 }
207             }
208         }
209         tenantNetworkManager.networkDeleted(network.getID());
210     }
211
212     /**
213      * Process the event.
214      *
215      * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
216      * @see org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher
217      */
218     @Override
219     public void processEvent(AbstractEvent abstractEvent) {
220         if (!(abstractEvent instanceof NorthboundEvent)) {
221             logger.error("Unable to process abstract event " + abstractEvent);
222             return;
223         }
224         NorthboundEvent ev = (NorthboundEvent) abstractEvent;
225         switch (ev.getAction()) {
226             case ADD:
227                 doNeutronNetworkCreated(ev.getNeutronNetwork());
228                 break;
229             case UPDATE:
230                 doNeutronNetworkUpdated(ev.getNeutronNetwork());
231                 break;
232             case DELETE:
233                 doNeutronNetworkDeleted(ev.getNeutronNetwork());
234                 break;
235             default:
236                 logger.warn("Unable to process event action " + ev.getAction());
237                 break;
238         }
239     }
240
241 }