2 * Copyright (C) 2014 SDN Hub, LLC.
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
8 * Authors : Srini Seetharaman
11 package org.opendaylight.ovsdb.openstack.netvirt;
13 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerAware;
14 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolCRUD;
15 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolMemberCRUD;
16 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
17 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancer;
18 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPool;
19 import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPoolMember;
20 import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
21 import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;
22 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
23 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerConfiguration;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
27 import com.google.common.collect.Maps;
29 import java.net.HttpURLConnection;
30 import java.util.Iterator;
31 import java.util.List;
35 * Handle requests for OpenStack Neutron v2.0 LBaaS API calls for /v2.0/loadbalancers.
38 //TODO: Implement INeutronLoadBalancerHealthMonitorAware, INeutronLoadBalancerListenerAware, INeutronLoadBalancerPoolMemberAware,
40 public class LBaaSHandler extends AbstractHandler
41 implements INeutronLoadBalancerAware {
43 private static final Logger logger = LoggerFactory.getLogger(LBaaSHandler.class);
45 // The implementation for each of these services is resolved by the OSGi Service Manager
46 private volatile INeutronLoadBalancerPoolCRUD neutronLBPoolCache;
47 private volatile INeutronLoadBalancerPoolMemberCRUD neutronLBPoolMemberCache;
48 private volatile INeutronPortCRUD neutronPortsCache;
49 private Map<String, LoadBalancerConfiguration> loadbalancersCache = Maps.newHashMap();
52 public int canCreateNeutronLoadBalancer(NeutronLoadBalancer neutronLoadBalancer) {
53 if (loadbalancersCache.containsKey(neutronLoadBalancer.getLoadBalancerID()))
54 return HttpURLConnection.HTTP_CONFLICT;
55 return HttpURLConnection.HTTP_OK;
59 * Assuming that the pool information is fully populated before this call is made,
60 * we go with creating the LoadBalancerConfiguration object for this call with
61 * all information that is necessary to insert flow_mods
64 public void neutronLoadBalancerCreated(NeutronLoadBalancer neutronLoadBalancer) {
65 logger.debug("Neutron LB Creation : {}", neutronLoadBalancer.toString());
66 enqueueEvent(new NorthboundEvent(neutronLoadBalancer, Action.ADD));
69 private void doNeutronLoadBalancerCreate(NeutronLoadBalancer neutronLoadBalancer) {
70 int result = canCreateNeutronLoadBalancer(neutronLoadBalancer);
71 if (result != HttpURLConnection.HTTP_OK) {
72 logger.debug("Neutron Load Balancer creation failed {} ", result);
76 String loadBalancerID = neutronLoadBalancer.getLoadBalancerID();
77 String loadBalancerName = neutronLoadBalancer.getLoadBalancerName();
78 String loadBalancerVip = neutronLoadBalancer.getLoadBalancerVipAddress();
79 String loadBalancerSubnetID = neutronLoadBalancer.getLoadBalancerVipSubnetID();
80 LoadBalancerConfiguration newLB = new LoadBalancerConfiguration(loadBalancerName, loadBalancerVip);
82 String memberID, memberIP, memberMAC, memberProtocol;
85 for (NeutronLoadBalancerPool neutronLBPool: neutronLBPoolCache.getAllNeutronLoadBalancerPools()) {
86 List<? extends NeutronLoadBalancerPoolMember> members =
87 (List<? extends NeutronLoadBalancerPoolMember>)neutronLBPool.getLoadBalancerPoolMembers();
88 memberProtocol = neutronLBPool.getLoadBalancerPoolProtocol();
90 * Only HTTP and HTTPS are supported as of this version
91 * TODO: Support all TCP load-balancers
93 if (!(memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
94 memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS)))
96 for (NeutronLoadBalancerPoolMember neutronLBPoolMember: members) {
97 if (neutronLBPoolMember.getPoolMemberSubnetID().equals(loadBalancerSubnetID)) {
98 memberID = neutronLBPoolMember.getPoolMemberID();
99 memberIP = neutronLBPoolMember.getPoolMemberAddress();
100 memberPort = neutronLBPoolMember.getPoolMemberProtoPort();
101 memberMAC = this.getMacAddress(memberIP);
102 if (memberMAC == null)
104 newLB.addMember(memberID, memberIP, memberMAC, memberProtocol, memberPort);
108 if (newLB.isValid()) {
109 logger.trace("Neutron LB pool configuration invalid for {} ", loadBalancerName);
112 loadbalancersCache.put(loadBalancerID, newLB);
113 //TODO: Trigger flowmod addition
118 public int canUpdateNeutronLoadBalancer(NeutronLoadBalancer delta, NeutronLoadBalancer original) {
119 return HttpURLConnection.HTTP_OK;
123 public void neutronLoadBalancerUpdated(NeutronLoadBalancer neutronLoadBalancer) {
124 enqueueEvent(new NorthboundEvent(neutronLoadBalancer, Action.UPDATE));
129 public int canDeleteNeutronLoadBalancer(NeutronLoadBalancer neutronLoadBalancer) {
130 if (!loadbalancersCache.containsKey(neutronLoadBalancer.getLoadBalancerID()))
131 return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
132 return HttpURLConnection.HTTP_OK;
136 public void neutronLoadBalancerDeleted(NeutronLoadBalancer neutronLoadBalancer) {
137 logger.debug("Neutron LB Deletion : {}", neutronLoadBalancer.toString());
138 enqueueEvent(new NorthboundEvent(neutronLoadBalancer, Action.DELETE));
141 private void doNeutronLoadBalancerDelete(NeutronLoadBalancer neutronLoadBalancer) {
142 int result = canDeleteNeutronLoadBalancer(neutronLoadBalancer);
143 if (result != HttpURLConnection.HTTP_OK) {
144 logger.error(" delete Neutron NeutronLoadBalancer Pool validation failed for result - {} ", result);
147 loadbalancersCache.remove(neutronLoadBalancer.getLoadBalancerID());
148 //TODO: Trigger flowmod removals
154 * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
155 * @see org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher
158 public void processEvent(AbstractEvent abstractEvent) {
159 if (!(abstractEvent instanceof NorthboundEvent)) {
160 logger.error("Unable to process abstract event " + abstractEvent);
163 NorthboundEvent ev = (NorthboundEvent) abstractEvent;
164 switch (ev.getAction()) {
166 doNeutronLoadBalancerCreate(ev.getLoadBalancer());
168 doNeutronLoadBalancerDelete(ev.getLoadBalancer());
171 doNeutronLoadBalancerDelete(ev.getLoadBalancer());
172 doNeutronLoadBalancerCreate(ev.getLoadBalancer());
175 logger.warn("Unable to process event action " + ev.getAction());
181 * Look up in the NeutronPortsCRUD cache and return the MAC address for a corresponding IP address
182 * @param ipAddr IP address of a member or VM
183 * @return MAC address registered with that IP address
185 private String getMacAddress(String ipAddr) {
186 List<Neutron_IPs> fixedIPs;
187 Iterator<Neutron_IPs> fixedIPIterator;
190 List<NeutronPort> allPorts = neutronPortsCache.getAllPorts();
191 Iterator<NeutronPort> i = allPorts.iterator();
192 while (i.hasNext()) {
193 NeutronPort port = i.next();
194 fixedIPs = port.getFixedIPs();
195 if (fixedIPs != null && fixedIPs.size() > 0) {
196 fixedIPIterator = fixedIPs.iterator();
197 while (fixedIPIterator.hasNext()) {
198 ip = fixedIPIterator.next();
199 if (ip.getIpAddress().equals(ipAddr))
200 return port.getMacAddress();