2016-09-26 00:43:46 +03:00
|
|
|
# Copyright (c) 2016 Mirantis, 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.
|
|
|
|
|
2020-09-04 13:41:38 +02:00
|
|
|
from kuryr_kubernetes import utils
|
|
|
|
|
2016-09-26 00:43:46 +03:00
|
|
|
|
|
|
|
class K8sClientException(Exception):
|
|
|
|
pass
|
2016-10-19 10:26:52 +03:00
|
|
|
|
|
|
|
|
2016-11-20 15:45:45 +03:00
|
|
|
class IntegrityError(RuntimeError):
|
2021-11-04 13:44:32 +01:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class InvalidKuryrConfiguration(RuntimeError):
|
2016-11-20 15:45:45 +03:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
2016-11-21 04:18:05 +03:00
|
|
|
class ResourceNotReady(Exception):
|
|
|
|
def __init__(self, resource):
|
2020-09-04 13:41:38 +02:00
|
|
|
msg = resource
|
|
|
|
if type(resource) == dict:
|
|
|
|
if resource.get('metadata', {}).get('name', None):
|
|
|
|
res_name = utils.get_res_unique_name(resource)
|
|
|
|
kind = resource.get('kind')
|
|
|
|
if kind:
|
|
|
|
msg = f'{kind} {res_name}'
|
|
|
|
else:
|
|
|
|
msg = res_name
|
2021-12-03 11:49:32 +01:00
|
|
|
self.message = "Resource not ready: %r" % msg
|
|
|
|
super(ResourceNotReady, self).__init__(self.message)
|
2016-11-21 04:18:05 +03:00
|
|
|
|
|
|
|
|
2021-12-03 18:41:16 +01:00
|
|
|
class KuryrLoadBalancerNotCreated(Exception):
|
|
|
|
def __init__(self, res):
|
|
|
|
name = utils.get_res_unique_name(res)
|
|
|
|
super().__init__(
|
|
|
|
'KuryrLoadBalancer not created yet for the Service %s' % name)
|
|
|
|
|
|
|
|
|
2021-06-17 17:30:17 +02:00
|
|
|
class LoadBalancerNotReady(ResourceNotReady):
|
|
|
|
def __init__(self, loadbalancer_id, status):
|
|
|
|
super().__init__(
|
|
|
|
'Loadbalancer %s is stuck in %s status for several minutes. This '
|
|
|
|
'is unexpected and indicates problem with OpenStack Octavia. '
|
|
|
|
'Please contact your OpenStack administrator.' % (
|
|
|
|
loadbalancer_id, status))
|
|
|
|
|
|
|
|
|
|
|
|
class PortNotReady(ResourceNotReady):
|
|
|
|
def __init__(self, port_id, status):
|
|
|
|
super().__init__(
|
|
|
|
'Port %s is stuck in %s status for several minutes. This '
|
|
|
|
'is unexpected and indicates problem with OpenStack Neutron. '
|
|
|
|
'Please contact your OpenStack administrator.' % (port_id, status))
|
|
|
|
|
|
|
|
|
2018-02-21 23:54:52 +02:00
|
|
|
class K8sResourceNotFound(K8sClientException):
|
|
|
|
def __init__(self, resource):
|
|
|
|
super(K8sResourceNotFound, self).__init__("Resource not "
|
|
|
|
"found: %r" % resource)
|
|
|
|
|
|
|
|
|
2020-07-24 15:44:29 +02:00
|
|
|
class K8sConflict(K8sClientException):
|
|
|
|
def __init__(self, message):
|
|
|
|
super(K8sConflict, self).__init__("Conflict: %r" % message)
|
|
|
|
|
|
|
|
|
2020-07-31 10:46:00 +02:00
|
|
|
class K8sForbidden(K8sClientException):
|
|
|
|
def __init__(self, message):
|
|
|
|
super(K8sForbidden, self).__init__("Forbidden: %r" % message)
|
|
|
|
|
|
|
|
|
|
|
|
class K8sNamespaceTerminating(K8sForbidden):
|
|
|
|
# This is raised when K8s complains about operation failing because
|
|
|
|
# namespace is being terminated.
|
|
|
|
def __init__(self, message):
|
|
|
|
super(K8sNamespaceTerminating, self).__init__(
|
|
|
|
"Namespace already terminated: %r" % message)
|
|
|
|
|
|
|
|
|
2020-09-07 20:50:53 +00:00
|
|
|
class K8sUnprocessableEntity(K8sClientException):
|
|
|
|
def __init__(self, message):
|
|
|
|
super(K8sUnprocessableEntity, self).__init__(
|
|
|
|
"Unprocessable: %r" % message)
|
|
|
|
|
|
|
|
|
2020-09-10 12:47:43 +02:00
|
|
|
class K8sFieldValueForbidden(K8sUnprocessableEntity):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2018-06-25 21:24:19 +08:00
|
|
|
class InvalidKuryrNetworkAnnotation(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2016-11-29 09:34:37 +03:00
|
|
|
class CNIError(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2016-10-19 10:26:52 +03:00
|
|
|
def format_msg(exception):
|
|
|
|
return "%s: %s" % (exception.__class__.__name__, exception)
|
2016-12-14 12:58:58 +05:30
|
|
|
|
|
|
|
|
|
|
|
class K8sNodeTrunkPortFailure(Exception):
|
|
|
|
"""Exception represents that error is related to K8s node trunk port
|
|
|
|
|
2017-05-31 16:41:54 +01:00
|
|
|
This exception is thrown when Neutron port is not associated to a Neutron
|
|
|
|
vlan trunk.
|
2016-12-14 12:58:58 +05:30
|
|
|
"""
|
2017-03-02 16:26:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
class AllowedAddressAlreadyPresent(Exception):
|
|
|
|
"""Exception indicates an already present 'allowed address pair' on port
|
|
|
|
|
|
|
|
This exception is raised when an attempt to add an already inserted
|
|
|
|
'allowed address pair' on a port is made. Such a condition likely indicates
|
|
|
|
a bad program state or a programming bug.
|
|
|
|
"""
|
2017-12-15 17:56:07 +01:00
|
|
|
|
|
|
|
|
|
|
|
class MultiPodDriverPoolConfigurationNotSupported(Exception):
|
|
|
|
"""Exception indicates a wrong configuration of the multi pod driver pool
|
|
|
|
|
|
|
|
This exception is raised when the multi pod driver pool is not properly
|
|
|
|
configured. This could be due to three different reasons:
|
|
|
|
1. One of the pool drivers is not supported
|
|
|
|
2. One of the pod drivers is not supported
|
|
|
|
3. One of the pod drivers is not supported by its selected pool driver
|
|
|
|
"""
|
2020-02-20 18:54:09 +01:00
|
|
|
|
|
|
|
|
2021-12-10 12:28:55 +01:00
|
|
|
class CNITimeout(Exception):
|
|
|
|
"""Exception groups various timeouts happening in the CNI """
|
|
|
|
|
|
|
|
|
|
|
|
class CNIKuryrPortTimeout(CNITimeout):
|
|
|
|
"""Excepton raised on timeout waiting for KuryrPort to be created"""
|
|
|
|
def __init__(self, name):
|
|
|
|
super().__init__(
|
|
|
|
f'Timed out waiting for KuryrPort to be created for pod {name}. '
|
|
|
|
f'kuryr-controller is responsible for that, check logs there.')
|
|
|
|
|
|
|
|
|
|
|
|
class CNINeutronPortActivationTimeout(CNITimeout):
|
|
|
|
"""Excepton raised on time out waiting for Neutron ports to be ACITVE"""
|
|
|
|
def __init__(self, name, vifs):
|
|
|
|
inactive = ', '.join(vif.id for vif in vifs.values() if not vif.active)
|
|
|
|
super().__init__(
|
|
|
|
f'Timed out waiting for Neutron port(s) {inactive} to be marked '
|
|
|
|
f'as ACTIVE after being bound to a Pod {name}. Most likely this '
|
|
|
|
f'indicates an issue with OpenStack Neutron. You can also check '
|
|
|
|
f'logs of kuryr-controller to confirm.')
|
|
|
|
|
|
|
|
|
2020-02-20 18:54:09 +01:00
|
|
|
class CNIBindingFailure(Exception):
|
|
|
|
"""Exception indicates a binding/unbinding VIF failure in CNI"""
|
|
|
|
def __init__(self, message):
|
|
|
|
super(CNIBindingFailure, self).__init__(message)
|
2021-04-09 21:56:59 +01:00
|
|
|
|
|
|
|
|
2022-01-27 18:06:08 +01:00
|
|
|
class CNIPodUidMismatch(Exception):
|
2022-01-19 18:16:37 +01:00
|
|
|
"""Excepton raised on a mismatch of CNI request's pod UID and KuryrPort"""
|
|
|
|
def __init__(self, name, expected, observed):
|
|
|
|
super().__init__(
|
|
|
|
f'uid {observed} of the pod {name} does not match the uid '
|
|
|
|
f'{expected} requested by the CNI. Dropping CNI request to prevent'
|
|
|
|
f' race conditions.')
|
|
|
|
|
|
|
|
|
2022-01-27 18:06:08 +01:00
|
|
|
class CNIPodGone(Exception):
|
|
|
|
"""Excepton raised when Pod got deleted while processing a CNI request"""
|
|
|
|
def __init__(self, name):
|
|
|
|
super().__init__(
|
|
|
|
f'Pod {name} got deleted while processing the CNI ADD request.')
|
|
|
|
|
|
|
|
|
2021-04-09 21:56:59 +01:00
|
|
|
class UnreachableOctavia(Exception):
|
|
|
|
"""Exception indicates Octavia API failure and can not be reached
|
|
|
|
|
|
|
|
This exception is raised when Kuryr can not reach Octavia. The Octavia
|
|
|
|
API call returns 'None' on the version field and we need to properly log
|
|
|
|
a message informing the user
|
|
|
|
"""
|
|
|
|
def __init__(self, message):
|
|
|
|
super(UnreachableOctavia, self).__init__(message)
|