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.INeutronLoadBalancerCRUD;
14 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolCRUD;
15 import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolMemberAware;
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.sal.core.Node;
21 import org.opendaylight.controller.switchmanager.ISwitchManager;
22 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
23 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerConfiguration;
24 import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerProvider;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
28 import com.google.common.base.Preconditions;
30 import java.net.HttpURLConnection;
31 import java.util.List;
34 * Handle requests for OpenStack Neutron v2.0 LBaaS API calls for
35 * /v2.0/pools/{pool_id}/members
38 public class LBaaSPoolMemberHandler extends AbstractHandler
39 implements INeutronLoadBalancerPoolMemberAware {
41 private static final Logger logger = LoggerFactory.getLogger(LBaaSPoolMemberHandler.class);
43 // The implementation for each of these services is resolved by the OSGi Service Manager
44 private volatile INeutronLoadBalancerPoolCRUD neutronLBPoolCache;
45 private volatile INeutronLoadBalancerCRUD neutronLBCache;
46 private volatile INeutronPortCRUD neutronPortsCache;
47 private volatile LoadBalancerProvider loadBalancerProvider;
48 private volatile ISwitchManager switchManager;
51 public int canCreateNeutronLoadBalancerPoolMember(NeutronLoadBalancerPoolMember neutronLBPoolMember) {
52 LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLBPoolMember);
54 return HttpURLConnection.HTTP_BAD_REQUEST;
55 else if (!lbConfig.isValid())
56 return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
58 return HttpURLConnection.HTTP_OK;
62 * Assuming that the pool information is fully populated before this call is made,
63 * we go with creating the LoadBalancerConfiguration object for this call with
64 * all information that is necessary to insert flow_mods
67 public void neutronLoadBalancerPoolMemberCreated(NeutronLoadBalancerPoolMember neutronLBPoolMember) {
68 logger.debug("Neutron LB Pool Member Creation : {}", neutronLBPoolMember.toString());
69 enqueueEvent(new NorthboundEvent(neutronLBPoolMember, Action.ADD));
72 private void doNeutronLoadBalancerPoolMemberCreate(NeutronLoadBalancerPoolMember neutronLBPoolMember) {
73 Preconditions.checkNotNull(loadBalancerProvider);
74 LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLBPoolMember);
75 if (lbConfig == null) {
76 logger.trace("Neutron LB configuration invalid for member {} ", neutronLBPoolMember.getPoolMemberAddress());
78 else if (!lbConfig.isValid()) {
79 logger.trace("Neutron LB pool configuration invalid for {} ", lbConfig.getName());
81 for (Node node: this.switchManager.getNodes())
82 loadBalancerProvider.programLoadBalancerPoolMemberRules(node, lbConfig,
83 lbConfig.getMembers().get(neutronLBPoolMember.getPoolMemberID()), Action.ADD);
88 public int canUpdateNeutronLoadBalancerPoolMember(NeutronLoadBalancerPoolMember delta, NeutronLoadBalancerPoolMember original) {
89 return HttpURLConnection.HTTP_OK;
93 public void neutronLoadBalancerPoolMemberUpdated(NeutronLoadBalancerPoolMember neutronLBPoolMember) {
94 enqueueEvent(new NorthboundEvent(neutronLBPoolMember, Action.UPDATE));
99 public int canDeleteNeutronLoadBalancerPoolMember(NeutronLoadBalancerPoolMember neutronLBPoolMember) {
100 LoadBalancerConfiguration lbConfig = extractLBConfiguration(neutronLBPoolMember);
101 if (lbConfig == null)
102 return HttpURLConnection.HTTP_BAD_REQUEST;
103 else if (!lbConfig.isValid())
104 return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
106 return HttpURLConnection.HTTP_OK;
110 public void neutronLoadBalancerPoolMemberDeleted(NeutronLoadBalancerPoolMember neutronLBPoolMember) {
111 logger.debug("Neutron LB Pool Member Deletion : {}", neutronLBPoolMember.toString());
113 /* As of now, deleting a member involves recomputing member indices.
114 * This is best done through a complete update of the load balancer instance.
116 for (NeutronLoadBalancer neutronLB: neutronLBCache.getAllNeutronLoadBalancers()) {
117 String loadBalancerSubnetID = neutronLB.getLoadBalancerVipSubnetID();
118 if (neutronLBPoolMember.getPoolMemberSubnetID().equals(loadBalancerSubnetID)) {
119 enqueueEvent(new NorthboundEvent(neutronLB, Action.UPDATE));
128 * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
129 * @see org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher
132 public void processEvent(AbstractEvent abstractEvent) {
133 if (!(abstractEvent instanceof NorthboundEvent)) {
134 logger.error("Unable to process abstract event " + abstractEvent);
137 NorthboundEvent ev = (NorthboundEvent) abstractEvent;
138 switch (ev.getAction()) {
140 doNeutronLoadBalancerPoolMemberCreate(ev.getLoadBalancerPoolMember());
142 logger.warn("Load balancer pool member delete event should not have been triggered");
145 * Typical upgrade involves changing weights. Since weights are not
146 * supported yet, updates are not supported either.
148 logger.warn("Load balancer pool member update is not supported");
151 logger.warn("Unable to process event action " + ev.getAction());
157 * Useful utility for extracting the loadbalancer instance
158 * configuration from the neutron LB cache based on member info
160 public LoadBalancerConfiguration extractLBConfiguration(NeutronLoadBalancerPoolMember neutronLBPoolMember) {
161 String memberIP = neutronLBPoolMember.getPoolMemberAddress();
162 String memberMAC = NeutronCacheUtils.getMacAddress(neutronPortsCache, memberIP);
163 if (memberMAC == null)
166 String memberID = neutronLBPoolMember.getPoolMemberID();
167 Integer memberPort = neutronLBPoolMember.getPoolMemberProtoPort();
168 String memberProtocol = null;
169 boolean found = false;
171 for (NeutronLoadBalancerPool neutronLBPool: neutronLBPoolCache.getAllNeutronLoadBalancerPools()) {
172 List<? extends NeutronLoadBalancerPoolMember> members =
173 (List<? extends NeutronLoadBalancerPoolMember>)neutronLBPool.getLoadBalancerPoolMembers();
174 for (NeutronLoadBalancerPoolMember member: members) {
175 //TODO: Allow member to be present in more than 1 pool
176 if (member.getPoolMemberID().equals(neutronLBPoolMember.getPoolMemberID())) {
178 memberProtocol = neutronLBPool.getLoadBalancerPoolProtocol();
179 if (!(memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTP) ||
180 memberProtocol.equalsIgnoreCase(LoadBalancerConfiguration.PROTOCOL_HTTPS)))
181 memberProtocol = null;
188 if (memberProtocol == null)
191 String loadBalancerSubnetID, loadBalancerVip, loadBalancerName;
192 for (NeutronLoadBalancer neutronLB: neutronLBCache.getAllNeutronLoadBalancers()) {
193 loadBalancerSubnetID = neutronLB.getLoadBalancerVipSubnetID();
194 if (neutronLBPoolMember.getPoolMemberSubnetID().equals(loadBalancerSubnetID)) {
195 loadBalancerName = neutronLB.getLoadBalancerName();
196 loadBalancerVip = neutronLB.getLoadBalancerVipAddress();
197 LoadBalancerConfiguration lbConfig = new LoadBalancerConfiguration(loadBalancerName, loadBalancerVip);
198 lbConfig.addMember(memberID, memberIP, memberMAC, memberProtocol, memberPort);