154 lines
6.9 KiB
Python
154 lines
6.9 KiB
Python
# Copyright 2020 Red Hat, Inc.
|
|
#
|
|
# 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 oslo_config import cfg as oslo_cfg
|
|
from oslo_log import log as logging
|
|
|
|
from kuryr_kubernetes import clients
|
|
from kuryr_kubernetes import constants
|
|
from kuryr_kubernetes.controller.drivers import base as drivers
|
|
from kuryr_kubernetes.controller.drivers import utils as driver_utils
|
|
from kuryr_kubernetes import exceptions as k_exc
|
|
from kuryr_kubernetes.handlers import k8s_base
|
|
from kuryr_kubernetes import utils
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class KuryrNetworkHandler(k8s_base.ResourceEventHandler):
|
|
"""Controller side of KuryrNetwork process for Kubernetes pods.
|
|
|
|
`KuryrNetworkHandler` runs on the Kuryr-Kubernetes controller and is
|
|
responsible for creating the OpenStack resources associated to the
|
|
newly created namespaces, and update the KuryrNetwork CRD status with
|
|
them.
|
|
"""
|
|
OBJECT_KIND = constants.K8S_OBJ_KURYRNETWORK
|
|
OBJECT_WATCH_PATH = constants.K8S_API_CRD_KURYRNETWORKS
|
|
|
|
def __init__(self):
|
|
super(KuryrNetworkHandler, self).__init__()
|
|
self._drv_project = drivers.NamespaceProjectDriver.get_instance()
|
|
self._drv_subnets = drivers.PodSubnetsDriver.get_instance()
|
|
self._drv_sg = drivers.PodSecurityGroupsDriver.get_instance()
|
|
self._drv_vif_pool = drivers.VIFPoolDriver.get_instance(
|
|
specific_driver='multi_pool')
|
|
self._drv_vif_pool.set_vif_driver()
|
|
if driver_utils.is_network_policy_enabled():
|
|
self._drv_lbaas = drivers.LBaaSDriver.get_instance()
|
|
self._drv_svc_sg = (
|
|
drivers.ServiceSecurityGroupsDriver.get_instance())
|
|
|
|
def on_present(self, kuryrnet_crd):
|
|
ns_name = kuryrnet_crd['spec']['nsName']
|
|
project_id = kuryrnet_crd['spec']['projectId']
|
|
kns_status = kuryrnet_crd.get('status', {})
|
|
|
|
crd_creation = False
|
|
net_id = kns_status.get('netId')
|
|
if not net_id:
|
|
net_id = self._drv_subnets.create_network(ns_name, project_id)
|
|
status = {'netId': net_id}
|
|
self._patch_kuryrnetwork_crd(kuryrnet_crd, status)
|
|
crd_creation = True
|
|
subnet_id = kns_status.get('subnetId')
|
|
if not subnet_id or crd_creation:
|
|
subnet_id, subnet_cidr = self._drv_subnets.create_subnet(
|
|
ns_name, project_id, net_id)
|
|
status = {'subnetId': subnet_id, 'subnetCIDR': subnet_cidr}
|
|
self._patch_kuryrnetwork_crd(kuryrnet_crd, status)
|
|
crd_creation = True
|
|
if not kns_status.get('routerId') or crd_creation:
|
|
router_id = self._drv_subnets.add_subnet_to_router(subnet_id)
|
|
status = {'routerId': router_id, 'populated': False}
|
|
self._patch_kuryrnetwork_crd(kuryrnet_crd, status)
|
|
crd_creation = True
|
|
|
|
# check labels to create sg rules
|
|
ns_labels = kns_status.get('nsLabels', {})
|
|
if (crd_creation or
|
|
ns_labels != kuryrnet_crd['spec']['nsLabels']):
|
|
# update SG and svc SGs
|
|
namespace = driver_utils.get_namespace(ns_name)
|
|
crd_selectors = self._drv_sg.update_namespace_sg_rules(namespace)
|
|
if (driver_utils.is_network_policy_enabled() and crd_selectors and
|
|
oslo_cfg.CONF.octavia_defaults.enforce_sg_rules):
|
|
services = driver_utils.get_services()
|
|
self._update_services(services, crd_selectors, project_id)
|
|
# update status
|
|
status = {'nsLabels': kuryrnet_crd['spec']['nsLabels']}
|
|
self._patch_kuryrnetwork_crd(kuryrnet_crd, status, labels=True)
|
|
|
|
def on_finalize(self, kuryrnet_crd):
|
|
LOG.debug("Deleting kuryrnetwork CRD resources: %s", kuryrnet_crd)
|
|
|
|
net_id = kuryrnet_crd.get('status', {}).get('netId')
|
|
if net_id:
|
|
self._drv_vif_pool.delete_network_pools(
|
|
kuryrnet_crd['status']['netId'])
|
|
try:
|
|
self._drv_subnets.delete_namespace_subnet(kuryrnet_crd)
|
|
except k_exc.ResourceNotReady:
|
|
LOG.debug("Subnet is not ready to be removed.")
|
|
# TODO(ltomasbo): Once KuryrPort CRDs is supported, we should
|
|
# execute a delete network ports method here to remove the
|
|
# ports associated to the namespace/subnet, ensuring next
|
|
# retry will be successful
|
|
raise
|
|
|
|
namespace = {
|
|
'metadata': {'name': kuryrnet_crd['spec']['nsName']}}
|
|
crd_selectors = self._drv_sg.delete_namespace_sg_rules(namespace)
|
|
|
|
if (driver_utils.is_network_policy_enabled() and crd_selectors and
|
|
oslo_cfg.CONF.octavia_defaults.enforce_sg_rules):
|
|
project_id = kuryrnet_crd['spec']['projectId']
|
|
services = driver_utils.get_services()
|
|
self._update_services(services, crd_selectors, project_id)
|
|
|
|
kubernetes = clients.get_kubernetes_client()
|
|
LOG.debug('Removing finalizer for KuryrNet CRD %s', kuryrnet_crd)
|
|
try:
|
|
kubernetes.remove_finalizer(kuryrnet_crd,
|
|
constants.KURYRNETWORK_FINALIZER)
|
|
except k_exc.K8sClientException:
|
|
LOG.exception('Error removing kuryrnetwork CRD finalizer for %s',
|
|
kuryrnet_crd)
|
|
raise
|
|
|
|
def _update_services(self, services, crd_selectors, project_id):
|
|
for service in services.get('items'):
|
|
if not driver_utils.service_matches_affected_pods(
|
|
service, crd_selectors):
|
|
continue
|
|
sgs = self._drv_svc_sg.get_security_groups(service,
|
|
project_id)
|
|
self._drv_lbaas.update_lbaas_sg(service, sgs)
|
|
|
|
def _patch_kuryrnetwork_crd(self, kuryrnet_crd, status, labels=False):
|
|
kubernetes = clients.get_kubernetes_client()
|
|
LOG.debug('Patching KuryrNetwork CRD %s', kuryrnet_crd)
|
|
try:
|
|
if labels:
|
|
kubernetes.patch_crd('status',
|
|
utils.get_res_link(kuryrnet_crd), status)
|
|
else:
|
|
kubernetes.patch('status', utils.get_res_link(kuryrnet_crd),
|
|
status)
|
|
except k_exc.K8sResourceNotFound:
|
|
LOG.debug('KuryrNetwork CRD not found %s', kuryrnet_crd)
|
|
except k_exc.K8sClientException:
|
|
LOG.exception('Error updating kuryrNetwork CRD %s', kuryrnet_crd)
|
|
raise
|