68916b9946269174ca092b3716f0313c56e2ab42
[ovsdb.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / PortHandler.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
9  */
10 package org.opendaylight.ovsdb.openstack.netvirt;
11
12 import org.opendaylight.neutron.spi.INeutronPortAware;
13 import org.opendaylight.neutron.spi.NeutronPort;
14 import org.opendaylight.ovsdb.lib.notation.Row;
15 import org.opendaylight.ovsdb.lib.notation.UUID;
16 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
18 import org.opendaylight.ovsdb.openstack.netvirt.impl.NeutronL3Adapter;
19 import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
20 import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
21 import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryListener;
22 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
23 import org.opendaylight.ovsdb.schema.openvswitch.Port;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
25
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import java.net.HttpURLConnection;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.concurrent.ConcurrentMap;
33
34 /**
35  * Handle requests for Neutron Port.
36  */
37 public class PortHandler extends AbstractHandler
38                          implements INeutronPortAware {
39
40     /**
41      * Logger instance.
42      */
43     static final Logger logger = LoggerFactory.getLogger(PortHandler.class);
44
45     // The implementation for each of these services is resolved by the OSGi Service Manager
46     private volatile OvsdbConfigurationService ovsdbConfigurationService;
47     private volatile OvsdbConnectionService connectionService;
48     private volatile NeutronL3Adapter neutronL3Adapter;
49
50     /**
51      * Invoked when a port creation is requested
52      * to indicate if the specified port can be created.
53      *
54      * @param port     An instance of proposed new Port object.
55      * @return A HTTP status code to the creation request.
56      */
57     @Override
58     public int canCreatePort(NeutronPort port) {
59         return HttpURLConnection.HTTP_OK;
60     }
61
62     /**
63      * Invoked to take action after a port has been created.
64      *
65      * @param neutronPort An instance of new Neutron Port object.
66      */
67     @Override
68     public void neutronPortCreated(NeutronPort neutronPort) {
69         enqueueEvent(new NorthboundEvent(neutronPort, Action.ADD));
70     }
71     private void doNeutronPortCreated(NeutronPort neutronPort) {
72         logger.debug(" Port-ADD successful for tenant-id - {}," +
73                      " network-id - {}, port-id - {}",
74                      neutronPort.getTenantID(), neutronPort.getNetworkUUID(),
75                      neutronPort.getID());
76         neutronL3Adapter.handleNeutronPortEvent(neutronPort, Action.ADD);
77     }
78
79     /**
80      * Invoked when a port update is requested
81      * to indicate if the specified port can be changed
82      * using the specified delta.
83      *
84      * @param delta    Updates to the port object using patch semantics.
85      * @param original An instance of the Neutron Port object
86      *                  to be updated.
87      * @return A HTTP status code to the update request.
88      */
89     @Override
90     public int canUpdatePort(NeutronPort delta,
91                              NeutronPort original) {
92         return HttpURLConnection.HTTP_OK;
93     }
94
95     /**
96      * Invoked to take action after a port has been updated.
97      *
98      * @param neutronPort An instance of modified Neutron Port object.
99      */
100     @Override
101     public void neutronPortUpdated(NeutronPort neutronPort) {
102         enqueueEvent(new NorthboundEvent(neutronPort, Action.UPDATE));
103     }
104     private void doNeutronPortUpdated(NeutronPort neutronPort) {
105         logger.debug("Handling neutron update port " + neutronPort);
106         neutronL3Adapter.handleNeutronPortEvent(neutronPort, Action.UPDATE);
107     }
108
109     /**
110      * Invoked when a port deletion is requested
111      * to indicate if the specified port can be deleted.
112      *
113      * @param port     An instance of the Neutron Port object to be deleted.
114      * @return A HTTP status code to the deletion request.
115      */
116     @Override
117     public int canDeletePort(NeutronPort port) {
118         return HttpURLConnection.HTTP_OK;
119     }
120
121     /**
122      * Invoked to take action after a port has been deleted.
123      *
124      * @param neutronPort  An instance of deleted Neutron Port object.
125      */
126     @Override
127     public void neutronPortDeleted(NeutronPort neutronPort) {
128         enqueueEvent(new NorthboundEvent(neutronPort, Action.DELETE));
129     }
130     private void doNeutronPortDeleted(NeutronPort neutronPort) {
131         logger.debug("Handling neutron delete port " + neutronPort);
132         neutronL3Adapter.handleNeutronPortEvent(neutronPort, Action.DELETE);
133
134         List<Node> nodes = connectionService.getNodes();
135         for (Node node : nodes) {
136             try {
137                 ConcurrentMap<String, Row> portRows =
138                         this.ovsdbConfigurationService.getRows(node,
139                                                         ovsdbConfigurationService.getTableName(node, Port.class));
140                 if (portRows != null) {
141                     for (Row portRow : portRows.values()) {
142                         Port port = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
143                         for (UUID interfaceUuid : port.getInterfacesColumn().getData()) {
144                             Row ifaceRow = ovsdbConfigurationService
145                                     .getRow(node,
146                                             ovsdbConfigurationService.getTableName(node, Interface.class),
147                                             interfaceUuid.toString());
148                             Interface iface = ovsdbConfigurationService.getTypedRow(node, Interface.class, ifaceRow);
149                             Map<String, String> externalIds = iface.getExternalIdsColumn().getData();
150
151                             if (externalIds == null) {
152                                 logger.trace("No external_ids seen in {}", iface.getName());
153                                 continue;
154                             }
155
156                             /* Compare Neutron port uuid */
157                             String neutronPortId = externalIds.get(Constants.EXTERNAL_ID_INTERFACE_ID);
158                             if (neutronPortId == null) {
159                                 continue;
160                             }
161
162                             if (neutronPortId.equalsIgnoreCase(neutronPort.getPortUUID())) {
163                                 logger.trace("neutronPortDeleted: Delete interface {}", iface.getName());
164                                 ovsdbConfigurationService.deleteRow(node,
165                                                              ovsdbConfigurationService.getTableName(node, Port.class),
166                                                              port.getUuid().toString());
167                                 break;
168                             }
169                         }
170                     }
171                 }
172             } catch (Exception e) {
173                 logger.error("Exception during handlingNeutron port delete", e);
174             }
175         }
176         logger.debug(" PORT delete successful for tenant-id - {}, " +
177                      " network-id - {}, port-id - {}",
178                      neutronPort.getTenantID(), neutronPort.getNetworkUUID(),
179                      neutronPort.getID());
180
181     }
182
183     /**
184      * Process the event.
185      *
186      * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
187      * @see org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher
188      */
189     @Override
190     public void processEvent(AbstractEvent abstractEvent) {
191         if (!(abstractEvent instanceof NorthboundEvent)) {
192             logger.error("Unable to process abstract event " + abstractEvent);
193             return;
194         }
195         NorthboundEvent ev = (NorthboundEvent) abstractEvent;
196         switch (ev.getAction()) {
197             case ADD:
198                 doNeutronPortCreated(ev.getPort());
199                 break;
200             case DELETE:
201                 doNeutronPortDeleted(ev.getPort());
202                 break;
203             case UPDATE:
204                 doNeutronPortUpdated(ev.getPort());
205                 break;
206             default:
207                 logger.warn("Unable to process event action " + ev.getAction());
208                 break;
209         }
210     }
211 }