Tacker: ETSI MANO NFV Orchestrator / VNF Manager. See https://wiki.openstack.org/wiki/Tacker
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1119 lines
28 KiB

# Copyright (C) 2020 FUJITSU
# 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.
import datetime
from kubernetes import client
from oslo_serialization import jsonutils
from oslo_utils import uuidutils
from tacker.db.db_sqlalchemy import models
from tacker import objects
from tacker.objects import vim_connection
from tacker.tests import uuidsentinel
CREATE_K8S_FALSE_VALUE = None
def fake_k8s_dict():
k8s_client_dict = {
'namespace': 'curryns',
'object': fake_k8s_obj()
}
return k8s_client_dict
def fake_k8s_obj():
return client.V1Deployment(
api_version='apps/v1',
kind='Deployment',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
spec=client.V1DeploymentSpec(
replicas=2,
selector=client.V1LabelSelector(
match_labels={'app': 'webserver'}
),
template=client.V1PodTemplateSpec(
metadata=client.V1ObjectMeta(
labels={'app': 'webserver',
'scaling_name': 'SP1'}
),
spec=client.V1PodSpec(
containers=[
client.V1Container(
env=[
client.V1EnvVar(
name='param0',
value_from=client.V1EnvVarSource(
config_map_key_ref=client.
V1ConfigMapKeySelector(
key='param0',
name='curry-test001'
)
)
),
client.V1EnvVar(
name='param1',
value_from=client.V1EnvVarSource(
config_map_key_ref=client.
V1ConfigMapKeySelector(
key='param1',
name='curry-test001'
)
)
)
],
image='celebdor/kuryr-demo',
image_pull_policy='IfNotPresent',
name='web-server',
ports=[
client.V1ContainerPort(
container_port=8080
)
],
resources=client.V1ResourceRequirements(
limits={
'cpu': '500m', 'memory': '512M'
},
requests={
'cpu': '500m', 'memory': '512M'
}
),
volume_mounts=[
client.V1VolumeMount(
name='curry-claim-volume',
mount_path='/data'
)
]
)
],
volumes=[
client.V1Volume(
name='curry-claim-volume',
persistent_volume_claim=client.
V1PersistentVolumeClaimVolumeSource(
claim_name='curry-pv-claim'
)
)
],
termination_grace_period_seconds=0
)
)
)
)
def fake_k8s_client_dict():
k8s_client_dict = {
'v1': client.CoreV1Api(),
'apiregistration.k8s.io/v1': client.ApiregistrationV1Api(),
'apps/v1': client.AppsV1Api(),
'authentication.k8s.io/v1': client.AuthenticationV1Api(),
'authorization.k8s.io/v1': client.AuthorizationV1Api(),
'autoscaling/v1': client.AutoscalingV1Api(),
'batch/v1': client.BatchV1Api(),
'coordination.k8s.io/v1': client.CoordinationV1Api(),
'networking.k8s.io/v1': client.NetworkingV1Api(),
'rbac.authorization.k8s.io/v1': client.RbacAuthorizationV1Api(),
'scheduling.k8s.io/v1': client.SchedulingV1Api(),
'storage.k8s.io/v1': client.StorageV1Api()
}
return k8s_client_dict
def fake_k8s_objs_node():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_node()
}
]
return objs
def fake_node():
return client.V1Node(
api_version='v1',
kind='Node',
metadata=client.V1ObjectMeta(
name='curry-node-test',
labels={'name': 'curry-node-test'}
),
status=client.V1NodeStatus(
conditions=[
client.V1NodeCondition(
status='True',
type='Ready'
)
]
)
)
def fake_k8s_objs_node_status_false():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_node_false()
}
]
return objs
def fake_node_false():
return client.V1Node(
api_version='v1',
kind='Node',
metadata=client.V1ObjectMeta(
name='curry-node-test',
labels={'name': 'curry-node-test'}
),
status=client.V1NodeStatus(
conditions=[
client.V1NodeCondition(
status='False',
type='Ready'
)
]
)
)
def fake_k8s_objs_pvc():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_pvc()
}
]
return objs
def fake_pvc():
return client.V1PersistentVolumeClaim(
api_version='v1',
kind='PersistentVolumeClaim',
metadata=client.V1ObjectMeta(
name='curry-sc-pvc'
),
status=client.V1PersistentVolumeClaimStatus(
phase='Bound'
)
)
def fake_k8s_objs_pvc_false_phase():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_pvc_false()
}
]
return objs
def fake_pvc_false():
return client.V1PersistentVolumeClaim(
api_version='v1',
kind='PersistentVolumeClaim',
metadata=client.V1ObjectMeta(
name='curry-sc-pvc'
),
status=client.V1PersistentVolumeClaimStatus(
phase='UnBound'
)
)
def fake_k8s_objs_namespace():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_namespace()
}
]
return objs
def fake_namespace():
return client.V1Namespace(
api_version='v1',
kind='Namespace',
metadata=client.V1ObjectMeta(
name='curry-ns'
),
status=client.V1NamespaceStatus(
phase='Active'
)
)
def fake_k8s_objs_namespace_false_phase():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_namespace_false()
}
]
return objs
def fake_namespace_false():
return client.V1Namespace(
api_version='v1',
kind='Namespace',
metadata=client.V1ObjectMeta(
name='curry-ns'
),
status=client.V1NamespaceStatus(
phase='NotActive'
)
)
def fake_k8s_objs_service():
objs = [
{
'namespace': 'default',
'status': 'Creating',
'object': fake_service()
}
]
return objs
def fake_service():
return client.V1Service(
api_version='v1',
kind='Service',
metadata=client.V1ObjectMeta(
labels={
'app': 'webserver',
'vdu_name': 'curry-svc-vdu001'
},
name='curry-svc-vdu001',
namespace='default'
),
spec=client.V1ServiceSpec(
cluster_ip=''
)
)
def fake_k8s_objs_service_false_cluster_ip():
objs = [
{
'namespace': 'default',
'status': 'Creating',
'object': fake_service_false()
}
]
return objs
def fake_service_false():
return client.V1Service(
api_version='v1',
kind='Service',
metadata=client.V1ObjectMeta(
labels={
'app': 'webserver',
'vdu_name': 'curry-svc-vdu001'
},
name='curry-svc-vdu001',
namespace='default'
),
spec=client.V1ServiceSpec(
cluster_ip='127.0.0.1'
)
)
def fake_endpoinds():
return client.V1Endpoints(
api_version='v1',
kind='Endpoints',
metadata=client.V1ObjectMeta(
namespace='default'
)
)
def fake_k8s_objs_deployment():
obj = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_v1_deployment()
}
]
return obj
def fake_k8s_objs_deployment_error():
obj = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_v1_deployment_error()
}
]
return obj
def fake_k8s_objs_replica_set():
obj = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_v1_replica_set()
}
]
return obj
def fake_k8s_objs_replica_set_error():
obj = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_v1_replica_set_error()
}
]
return obj
def fake_k8s_objs_stateful_set():
obj = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_v1_stateful_set()
}
]
return obj
def fake_k8s_objs_stateful_set_error():
obj = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_v1_stateful_set_error()
}
]
return obj
def fake_k8s_objs_job():
obj = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_v1_job()
}
]
return obj
def fake_k8s_objs_job_error():
obj = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_v1_job_error()
}
]
return obj
def fake_k8s_objs_volume_attachment():
obj = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_v1_volume_attachment()
}
]
return obj
def fake_k8s_objs_volume_attachment_error():
obj = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_v1_volume_attachment_error()
}
]
return obj
def fake_v1_deployment():
return client.V1Deployment(
api_version='apps/v1',
kind='Deployment',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1DeploymentStatus(
replicas=1,
ready_replicas=1
),
spec=client.V1DeploymentSpec(
replicas=2,
selector=client.V1LabelSelector(
match_labels={'app': 'webserver'}
),
template=client.V1PodTemplateSpec(
metadata=client.V1ObjectMeta(
labels={'app': 'webserver'}
)
)
)
)
def fake_v1_deployment_error():
return client.V1Deployment(
api_version='apps/v1',
kind='Deployment',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1DeploymentStatus(
replicas=2,
ready_replicas=1
)
)
def fake_v1_replica_set():
return client.V1ReplicaSet(
api_version='apps/v1',
kind='ReplicaSet',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1ReplicaSetStatus(
replicas=1,
ready_replicas=1
),
spec=client.V1ReplicaSetSpec(
replicas=2,
selector=client.V1LabelSelector(
match_labels={'app': 'webserver'}
),
template=client.V1PodTemplateSpec(
metadata=client.V1ObjectMeta(
labels={'app': 'webserver'}
)
)
)
)
def fake_v1_replica_set_error():
return client.V1ReplicaSet(
api_version='apps/v1',
kind='ReplicaSet',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1ReplicaSetStatus(
replicas=2,
ready_replicas=1
)
)
def fake_v1_job():
return client.V1Job(
api_version='batch/v1',
kind='Job',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
spec=client.V1JobSpec(
completions=1,
template=client.V1PodTemplateSpec(
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
spec=client.V1PodSpec(
hostname='job',
containers=['image']
)
)
),
status=client.V1JobStatus(
succeeded=1,
)
)
def fake_v1_job_error():
return client.V1Job(
api_version='batch/v1',
kind='Job',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
spec=client.V1JobSpec(
completions=1,
template=client.V1PodTemplateSpec(
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
spec=client.V1PodSpec(
hostname='job',
containers=['image']
)
)
),
status=client.V1JobStatus(
succeeded=2,
)
)
def fake_v1_volume_attachment():
return client.V1VolumeAttachment(
api_version='storage.k8s.io/v1',
kind='VolumeAttachment',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
spec=client.V1VolumeAttachmentSpec(
attacher='nginx',
node_name='nginx',
source=client.V1VolumeAttachmentSource(
persistent_volume_name='curry-sc-pvc'
)
),
status=client.V1VolumeAttachmentStatus(
attached=True,
)
)
def fake_v1_volume_attachment_error():
return client.V1VolumeAttachment(
api_version='storage.k8s.io/v1',
kind='VolumeAttachment',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
spec=client.V1VolumeAttachmentSpec(
attacher='nginx',
node_name='nginx',
source=client.V1VolumeAttachmentSource(
persistent_volume_name='curry-sc-pvc'
)
),
status=client.V1VolumeAttachmentStatus(
attached=False,
)
)
def fake_v1_stateful_set():
return client.V1StatefulSet(
api_version='apps/v1',
kind='StatefulSet',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
spec=client.V1StatefulSetSpec(
replicas=1,
volume_claim_templates=[
client.V1PersistentVolumeClaim(
metadata=client.V1ObjectMeta(
name='www'
)
)
],
selector=client.V1LabelSelector(
match_labels={'app': 'nginx'}
),
template=client.V1PodTemplateSpec(
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
)
),
service_name='nginx'
),
status=client.V1StatefulSetStatus(
replicas=1,
ready_replicas=1
),
)
def fake_v1_stateful_set_error():
return client.V1StatefulSet(
api_version='apps/v1',
kind='StatefulSet',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
spec=client.V1StatefulSetSpec(
replicas=1,
volume_claim_templates=[
client.V1PersistentVolumeClaim(
metadata=client.V1ObjectMeta(
name='www'
)
)
],
selector=client.V1LabelSelector(
match_labels={'app': 'nginx'}
),
template=client.V1PodTemplateSpec(
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
)
),
service_name='nginx'
),
status=client.V1StatefulSetStatus(
replicas=2,
ready_replicas=1
)
)
def fake_v1_persistent_volume_claim():
return client.V1PersistentVolumeClaim(
api_version='v1',
kind='PersistentVolumeClaim',
metadata=client.V1ObjectMeta(
name='www-curry-test001-0',
namespace='curryns'
),
status=client.V1PersistentVolumeClaimStatus(
phase='Bound'
)
)
def fake_v1_persistent_volume_claim_error():
return client.V1PersistentVolumeClaim(
api_version='v1',
kind='PersistentVolumeClaim',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1PersistentVolumeClaimStatus(
phase='Bound1'
)
)
def fake_k8s_objs_pod():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_pod()
}
]
return objs
def fake_k8s_objs_pod_error():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_pod_error()
}
]
return objs
def fake_pod():
return client.V1Pod(
api_version='v1',
kind='Pod',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1PodStatus(
phase='Running',
)
)
def fake_pod_error():
return client.V1Pod(
api_version='v1',
kind='Pod',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1PodStatus(
phase='Terminated',
)
)
def fake_k8s_objs_persistent_volume():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_persistent_volume()
}
]
return objs
def fake_k8s_objs_persistent_volume_error():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_persistent_volume_error()
}
]
return objs
def fake_persistent_volume():
return client.V1PersistentVolume(
api_version='v1',
kind='PersistentVolume',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1PersistentVolumeStatus(
phase='Available',
)
)
def fake_persistent_volume_error():
return client.V1PersistentVolume(
api_version='v1',
kind='PersistentVolume',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1PersistentVolumeStatus(
phase='UnBound',
)
)
def fake_k8s_objs_api_service():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_api_service()
}
]
return objs
def fake_k8s_objs_api_service_error():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_api_service_error()
}
]
return objs
def fake_api_service():
return client.V1APIService(
api_version='apiregistration.k8s.io/v1',
kind='APIService',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1APIServiceStatus(
conditions=[
client.V1APIServiceCondition(
type='Available',
status='True'
)
]
)
)
def fake_api_service_error():
return client.V1APIService(
api_version='apiregistration.k8s.io/v1',
kind='APIService',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1APIServiceStatus(
conditions=[
client.V1APIServiceCondition(
type='Unavailable',
status='True'
)
]
)
)
def fake_k8s_objs_daemon_set():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_daemon_set()
}
]
return objs
def fake_k8s_objs_daemon_set_error():
objs = [
{
'namespace': 'test',
'status': 'Creating',
'object': fake_daemon_set_error()
}
]
return objs
def fake_daemon_set():
return client.V1DaemonSet(
api_version='apps/v1',
kind='DaemonSet',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1DaemonSetStatus(
number_ready=13,
desired_number_scheduled=13,
current_number_scheduled=4,
number_misscheduled=2,
),
spec=client.V1DaemonSetSpec(
selector=client.V1LabelSelector(
match_labels={'app': 'webserver'}
),
template=client.V1PodTemplateSpec(
metadata=client.V1ObjectMeta(
labels={'app': 'webserver'}
)
)
)
)
def fake_daemon_set_error():
return client.V1DaemonSet(
api_version='apps/v1',
kind='DaemonSet',
metadata=client.V1ObjectMeta(
name='curry-test001',
namespace='curryns'
),
status=client.V1DaemonSetStatus(
number_ready=13,
desired_number_scheduled=12,
current_number_scheduled=4,
number_misscheduled=2,
)
)
def fake_auth_attr():
return {
'username': 'fake_user_name',
'password': 'fake_password',
'ssl_ca_cert': '-----BEGIN CERTIFICATE-----\
samplevalues\
-----END CERTIFICATE-----',
'auth_url': 'http://fake-url/identity/v3'
}
def fake_vnf_dict(updates=None):
vnf_dict = {
'id': 'fake-id,fake-name',
'status': 'fake-status',
'attributes': {
'monitoring_policy': 'fake-monitoring-policy',
'failure_count': '1',
'dead_instance_id_1': '00000000-0000-0000-0000-00000000001'},
'vim_id': 'fake-vim-id',
'vim_auth': 'fake-vim-auth',
'instance_id': '00000000-0000-0000-0000-000000000002',
'placement_attr': {
'region_name': 'fake-region-name'}}
if updates:
vnf_dict.update(updates)
return vnf_dict
def fake_pod_list():
return client.V1PodList(
items=[client.V1Pod(
metadata=client.V1ObjectMeta(
name="fake-name"
),
status=client.V1PodStatus(
phase="Successed"
)
)]
)
def get_scale_policy(type, aspect_id='vdu1', delta_num=1, is_legacy=False):
policy = dict()
policy['action'] = type
policy['name'] = aspect_id
if is_legacy:
policy['instance_id'] = "fake_namespace,fake_name"
else:
policy['vnf_instance_id'] = uuidsentinel.vnf_instance_id
policy['delta_num'] = delta_num
policy['vdu_defs'] = {
'VDU1': {
'type': 'tosca.nodes.nfv.Vdu.Compute',
'properties': {
'name': 'fake_name',
'description': 'test description',
'vdu_profile': {
'min_number_of_instances': 1,
'max_number_of_instances': 3}}}}
return policy
def get_vnf_resource_list(kind, name='fake_name'):
vnf_resource = models.VnfResource()
vnf_resource.vnf_instance_id = uuidsentinel.vnf_instance_id
vnf_resource.resource_name = \
_("fake_namespace,{name}").format(name=name)
vnf_resource.resource_type = \
_("v1,{kind}").format(kind=kind)
return [vnf_resource]
def get_fake_pod_info(kind, name='fake_name', pod_status='Running',
pod_name=None):
if not pod_name:
if kind == 'Deployment':
pod_name = _('{name}-1234567890-abcde').format(name=name)
elif kind == 'ReplicaSet' or kind == 'DaemonSet':
pod_name = _('{name}-12345').format(name=name)
elif kind == 'StatefulSet':
pod_name = _('{name}-1').format(name=name)
elif kind == 'Pod':
pod_name = name
return client.V1Pod(
metadata=client.V1ObjectMeta(name=pod_name,
creation_timestamp=datetime.datetime.now().isoformat('T')),
status=client.V1PodStatus(phase=pod_status))
def fake_vnfc_resource_info(vdu_id='VDU1', rsc_kind='Deployment',
rsc_name='fake_name', pod_name=None,
namespace=None):
def _get_metadata_str(name, namespace="fake_namespace"):
if namespace == "brank":
namespace = ""
metadata = {
'name': name,
'namespace': namespace}
return jsonutils.dumps(metadata)
vnfc_obj = objects.VnfcResourceInfo()
vnfc_obj.id = uuidutils.generate_uuid()
vnfc_obj.vdu_id = vdu_id
if not pod_name:
v1_pod = get_fake_pod_info(rsc_kind, rsc_name)
pod_name = v1_pod.metadata.name
compute_resource = objects.ResourceHandle(
resource_id=pod_name,
vim_level_resource_type=rsc_kind)
vnfc_obj.compute_resource = compute_resource
metadata = {}
if namespace:
metadata['Pod'] = _get_metadata_str(
name=pod_name, namespace=namespace)
if rsc_kind != 'Pod':
metadata[rsc_kind] = _get_metadata_str(
name=rsc_name, namespace=namespace)
else:
metadata['Pod'] = _get_metadata_str(name=pod_name)
if rsc_kind != 'Pod':
metadata[rsc_kind] = _get_metadata_str(name=rsc_name)
vnfc_obj.metadata = metadata
return vnfc_obj
def fake_vim_connection_info():
access_info = {
'auth_url': 'http://fake_url:6443',
'ssl_ca_cert': None}
return vim_connection.VimConnectionInfo(
vim_type="kubernetes",
access_info=access_info)