kuryr-kubernetes/kuryr_kubernetes/controller/drivers/lb_public_ip.py

114 lines
4.4 KiB
Python

# Copyright (c) 2017 RedHat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from kuryr_kubernetes import config
from kuryr_kubernetes.controller.drivers import base
from kuryr_kubernetes.controller.drivers import public_ip
from oslo_log import log as logging
LOG = logging.getLogger(__name__)
class FloatingIpServicePubIPDriver(base.ServicePubIpDriver):
"""Manages floating ip for neutron lbaas.
Service loadbalancerIP support the following :
1. No loadbalancer IP - k8s service.spec.type != 'LoadBalancer'
2. Floating IP allocated from pool -
k8s service.spec.type = 'LoadBalancer' and
service.spec.loadBalancerIP NOT defined
3. Floating IP specified by the user -
k8s service.spec.type = 'LoadBalancer' and
service.spec.loadBalancerIP is defined.
"""
def __init__(self):
super(FloatingIpServicePubIPDriver, self).__init__()
self._drv_pub_ip = public_ip.FipPubIpDriver()
def acquire_service_pub_ip_info(self, spec_type, spec_lb_ip, project_id,
port_id_to_be_associated=None):
if spec_type != 'LoadBalancer':
return None
# get public network/subnet ids from kuryr.conf
public_network_id = config.CONF.neutron_defaults.external_svc_net
public_subnet_id = config.CONF.neutron_defaults.external_svc_subnet
if not public_network_id:
LOG.warning('Skipping Floating IP allocation on port: %s. '
'Missing value for external_svc_net config.',
port_id_to_be_associated)
return None
if spec_lb_ip:
user_specified_ip = spec_lb_ip.format()
res_id = self._drv_pub_ip.is_ip_available(user_specified_ip,
port_id_to_be_associated)
if res_id:
service_pub_ip_info = {
'ip_id': res_id,
'ip_addr': str(user_specified_ip),
'alloc_method': 'user'
}
return service_pub_ip_info
else:
# user specified IP is not valid
LOG.error("IP=%s is not available", user_specified_ip)
return None
else:
LOG.debug("Trying to allocate public ip from pool")
try:
res_id, alloc_ip_addr = (self._drv_pub_ip.allocate_ip(
public_network_id, project_id, pub_subnet_id=public_subnet_id,
description='kuryr_lb',
port_id_to_be_associated=port_id_to_be_associated))
except Exception:
LOG.exception("Failed to allocate public IP - net_id:%s",
public_network_id)
return None
service_pub_ip_info = {
'ip_id': res_id,
'ip_addr': alloc_ip_addr,
'alloc_method': 'pool'
}
return service_pub_ip_info
def release_pub_ip(self, service_pub_ip_info):
if not service_pub_ip_info:
return True
if service_pub_ip_info['alloc_method'] == 'pool':
retcode = self._drv_pub_ip.free_ip(service_pub_ip_info['ip_id'])
if not retcode:
LOG.error("Failed to delete public_ip_id =%s !",
service_pub_ip_info['ip_id'])
return False
return True
def associate_pub_ip(self, service_pub_ip_info, vip_port_id):
if (not service_pub_ip_info or
not vip_port_id or
not service_pub_ip_info['ip_id']):
return
self._drv_pub_ip.associate(
service_pub_ip_info['ip_id'], vip_port_id)
def disassociate_pub_ip(self, service_pub_ip_info):
if not service_pub_ip_info or not service_pub_ip_info['ip_id']:
return
self._drv_pub_ip.disassociate(service_pub_ip_info['ip_id'])