Merge "Enhance Container Update Function"

This commit is contained in:
Zuul 2022-09-12 17:39:51 +00:00 committed by Gerrit Code Review
commit b025a1bfce
23 changed files with 1334 additions and 98 deletions

View File

@ -47,8 +47,8 @@ Use Cases
In this user guide, the provided sample VNF Packages will be instantiated In this user guide, the provided sample VNF Packages will be instantiated
and then updated. The sample Mgmt Driver will update resources on and then updated. The sample Mgmt Driver will update resources on
Kubernetes during update. Update the ConfigMap and Secret, and also Kubernetes during update. Update the ConfigMap and Secret, and also
update the image in the Pod and Deployment, and other resources will update the image in the Pod, Deployment, DaemonSet and ReplicaSet, and other
not change. resources will not change.
Prerequisites Prerequisites
------------- -------------
@ -199,7 +199,13 @@ You can see resource definition files are included as a value of
"Files/kubernetes/pod_env.yaml", "Files/kubernetes/pod_env.yaml",
"Files/kubernetes/pod_volume.yaml", "Files/kubernetes/pod_volume.yaml",
"Files/kubernetes/replicaset.yaml", "Files/kubernetes/replicaset.yaml",
"Files/kubernetes/secret_1.yaml" "Files/kubernetes/secret_1.yaml",
"Files/kubernetes/configmap_3.yaml",
"Files/kubernetes/pod_env_2.yaml",
"Files/kubernetes/pod_volume_2.yaml",
"Files/kubernetes/daemonset.yaml",
"Files/kubernetes/deployment_2.yaml",
"Files/kubernetes/secret_3.yaml"
], ],
"namespace": "default" "namespace": "default"
}, },
@ -228,27 +234,27 @@ As mentioned in Prerequisites, the VNF must be instantiated before performing
updating. updating.
Next, the user can use the original vnf package as a template to make a new Next, the user can use the original vnf package as a template to make a new
vnf package, in which the yaml of ConfigMap, Secret, Pod and Deployment can vnf package, in which the yaml of ConfigMap, Secret, Pod, Deployment, DaemonSet
be changed. and ReplicaSet can be changed.
.. note:: .. note::
* The yaml of ConfigMap and Secret can be changed. The kind, namespace * The yaml of ConfigMap and Secret can be changed. The kind, namespace
and name cannot be changed, but the file name and file path can and name cannot be changed, but the file name and file path can
be changed. be changed.
* The yaml of Pod and Deployment can also be changed, but only the * The yaml of Pod, Deployment, DaemonSet and ReplicaSet can also be
image field can be changed, and no other fields can be changed. changed, but only the image field can be changed, and no other fields can
be changed.
* No other yaml is allowed to be changed. * No other yaml is allowed to be changed.
* If changes other than images are made to the yaml of Pod, Deployment,
* If changes other than images are made to the yaml of Pod and DaemonSet and ReplicaSet , those will not take effect. However, if heal
Deployment, those will not take effect. However, if heal entire entire VNF at this time, the resource will be based on the new yaml
VNF at this time, the resource will be based on the new yaml during the instantiation, and all changes will take effect.
during the instantiation, and all changes will take effect.
Then after creating and uploading the new vnf package, you can perform the Then after creating and uploading the new vnf package, you can perform the
update operation. update operation.
After the update, the Mgmt Driver will restart the pod to update and After the update, the Mgmt Driver will restart the pod to update and
recreate the deployment to update. recreate the deployment, DaemonSet and ReplicaSet to update.
.. note:: .. note::
@ -274,8 +280,9 @@ The resources information before update:
$ kubectl get configmaps $ kubectl get configmaps
NAME DATA AGE NAME DATA AGE
cm-data 1 3h55m cm-data 1 32m
kube-root-ca.crt 1 23h cm-data2 1 32m
kube-root-ca.crt 1 20h
$ $
$ kubectl describe configmaps cm-data $ kubectl describe configmaps cm-data
Name: cm-data Name: cm-data
@ -283,6 +290,21 @@ The resources information before update:
Labels: <none> Labels: <none>
Annotations: <none> Annotations: <none>
Data
====
cmKey1.txt:
----
configmap data
foo
bar
Events: <none>
$
$ kubectl describe configmaps cm-data2
Name: cm-data2
Namespace: default
Labels: <none>
Annotations: <none>
Data Data
==== ====
cmKey1.txt: cmKey1.txt:
@ -298,8 +320,9 @@ The resources information before update:
$ kubectl get secrets $ kubectl get secrets
NAME TYPE DATA AGE NAME TYPE DATA AGE
default-token-ctq4p kubernetes.io/service-account-token 3 23h default-token-w59gg kubernetes.io/service-account-token 3 20h
secret-data Opaque 2 3h55m secret-data Opaque 2 37m
secret-data2 Opaque 2 37m
$ $
$ kubectl describe secrets secret-data $ kubectl describe secrets secret-data
Name: secret-data Name: secret-data
@ -309,6 +332,19 @@ The resources information before update:
Type: Opaque Type: Opaque
Data
====
password: 15 bytes
secKey1.txt: 15 bytes
$
$ kubectl describe secrets secret-data2
Name: secret-data2
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data Data
==== ====
password: 15 bytes password: 15 bytes
@ -319,21 +355,25 @@ The resources information before update:
.. code-block:: console .. code-block:: console
$ kubectl get pod -o wide $ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
env-test 1/1 Running 0 4h28m 10.233.96.4 node2 <none> <none> daemonset-nv79l 1/1 Running 0 39m 10.233.96.20 node2 <none> <none>
vdu1-85dd489b89-w72dr 1/1 Running 0 4h28m 10.233.96.5 node2 <none> <none> deployment1-85dd489b89-p7m9q 1/1 Running 0 39m 10.233.96.17 node2 <none> <none>
vdu2-mfn78 1/1 Running 0 4h28m 10.233.96.2 node2 <none> <none> deployment2-5c6b485699-mdx9v 1/1 Running 0 39m 10.233.96.22 node2 <none> <none>
volume-test 1/1 Running 0 4h28m 10.233.96.3 node2 <none> <none> env-test1 1/1 Running 0 39m 10.233.96.21 node2 <none> <none>
env-test2 1/1 Running 0 39m 10.233.96.19 node2 <none> <none>
replicaset-bv6cp 1/1 Running 0 39m 10.233.96.24 node2 <none> <none>
volume-test1 1/1 Running 0 39m 10.233.96.18 node2 <none> <none>
volume-test2 1/1 Running 0 39m 10.233.96.23 node2 <none> <none>
$ $
$ kubectl describe pod volume-test $ kubectl describe pod volume-test1
Name: volume-test Name: volume-test1
Namespace: default Namespace: default
... ...
Containers: Containers:
nginx: nginx:
Container ID: docker://01273fa7cd595b49d866b755ea6cc2707d90cca70ecb9f5a86c4db3eacad2dde Container ID: docker://623c652c7ab71d268e18129475d0391b72c88b1a8a778bbdd3d479fad2521bc2
Image: nginx Image: nginx
Image ID: docker-pullable://nginx@sha256:e9712bdfa40c19cc2cee4f06e5b1215138926250165e26fe69822a9ddc525eaf Image ID: docker-pullable://nginx@sha256:ecc068890de55a75f1a32cc8063e79f90f0b043d70c5fcf28f1713395a4b3d49
... ...
Volumes: Volumes:
cm-volume: cm-volume:
@ -345,24 +385,46 @@ The resources information before update:
SecretName: secret-data SecretName: secret-data
Optional: false Optional: false
... ...
$
$ kubectl describe pod volume-test2
Name: volume-test2
Namespace: default
...
Containers:
nginx:
Container ID: docker://74d38aa62097b3a1a80181195ebda3877e3773311d0273fdc3fbb27fa4b9600d
Image: nginx
Image ID: docker-pullable://nginx@sha256:ecc068890de55a75f1a32cc8063e79f90f0b043d70c5fcf28f1713395a4b3d49
...
Volumes:
cm-volume:
Type: ConfigMap (a volume populated by a ConfigMap)
Name: cm-data2
Optional: false
sec-volume:
Type: Secret (a volume populated by a Secret)
SecretName: secret-data2
Optional: false
...
* Deployment * Deployment
.. code-block:: console .. code-block:: console
$ kubectl get deployments.apps -o wide $ kubectl get deployments.apps -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
vdu1 1/1 1 1 4h29m nginx nginx app=webserver deployment1 1/1 1 1 49m nginx nginx app=webserver
deployment2 1/1 1 1 49m nginx nginx app=webserver
$ $
$ kubectl describe pod vdu1-85dd489b89-w72dr $ kubectl describe pod deployment1-85dd489b89-p7m9q
Name: vdu1-85dd489b89-w72dr Name: deployment1-85dd489b89-p7m9q
Namespace: default Namespace: default
... ...
Containers: Containers:
nginx: nginx:
Container ID: docker://5efe65493ac13ff539f9de30db7c624405ff390df8f5f2e23f22fc0f8b6ad68a Container ID: docker://50ffc03736a03c8d4546bb60bb5815b4c8f6cbbfb7b70da4121a06c5c8d6568a
Image: nginx Image: nginx
Image ID: docker-pullable://nginx@sha256:e9712bdfa40c19cc2cee4f06e5b1215138926250165e26fe69822a9ddc525eaf Image ID: docker-pullable://nginx@sha256:ecc068890de55a75f1a32cc8063e79f90f0b043d70c5fcf28f1713395a4b3d49
... ...
Environment Variables from: Environment Variables from:
cm-data ConfigMap with prefix 'CM_' Optional: false cm-data ConfigMap with prefix 'CM_' Optional: false
@ -371,10 +433,79 @@ The resources information before update:
CMENV: <set to the key 'cmKey1.txt' of config map 'cm-data'> Optional: false CMENV: <set to the key 'cmKey1.txt' of config map 'cm-data'> Optional: false
SECENV: <set to the key 'password' in secret 'secret-data'> Optional: false SECENV: <set to the key 'password' in secret 'secret-data'> Optional: false
... ...
$
$ kubectl describe pod deployment2-5c6b485699-mdx9v
Name: deployment2-5c6b485699-mdx9v
Namespace: default
...
Containers:
nginx:
Container ID: docker://6d7a8019984c04ab758b962a228f44fb14bfc0f4e1f525548d87a91d17b49f77
Image: nginx
Image ID: docker-pullable://nginx@sha256:ecc068890de55a75f1a32cc8063e79f90f0b043d70c5fcf28f1713395a4b3d49
...
Environment Variables from:
cm-data2 ConfigMap with prefix 'CM_' Optional: false
secret-data2 Secret with prefix 'SEC_' Optional: false
Environment:
CMENV: <set to the key 'cmKey1.txt' of config map 'cm-data2'> Optional: false
SECENV: <set to the key 'password' in secret 'secret-data2'> Optional: false
...
* DaemonSet
.. code-block:: console
$ kubectl get daemonset.apps -o wide
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
daemonset 1 1 1 1 1 <none> 58m nginx nginx app=nginx
$
$ kubectl describe pod daemonset-nv79l
Name: daemonset-nv79l
Namespace: default
...
Containers:
nginx:
Container ID: docker://3f392217d5f22c417fc9da24f4bd27d41e90a2165d10356a44cd1b98b6b899d9
Image: nginx
Image ID: docker-pullable://nginx@sha256:ecc068890de55a75f1a32cc8063e79f90f0b043d70c5fcf28f1713395a4b3d49
...
Environment Variables from:
cm-data ConfigMap with prefix 'CM_' Optional: false
secret-data Secret with prefix 'SEC_' Optional: false
Environment:
CMENV: <set to the key 'cmKey1.txt' of config map 'cm-data'> Optional: false
SECENV: <set to the key 'password' in secret 'secret-data'> Optional: false
...
* ReplicaSet
.. code-block:: console
$ kubectl get replicaset.apps -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
deployment1-85dd489b89 1 1 1 62m nginx nginx app=webserver,pod-template-hash=85dd489b89
deployment2-5c6b485699 1 1 1 62m nginx nginx app=webserver,pod-template-hash=5c6b485699
replicaset 1 1 1 62m nginx nginx app=webserver
$
$ kubectl describe pod replicaset-bv6cp
Name: replicaset-bv6cp
Namespace: default
...
Containers:
nginx:
Container ID: docker://d8e5ea8404a8cd272b54cefac236fdf0c1963a6b0cf03b283e9f57c70fcd4eab
Image: nginx
Image ID: docker-pullable://nginx@sha256:ecc068890de55a75f1a32cc8063e79f90f0b043d70c5fcf28f1713395a4b3d49
...
Volumes: Volumes:
default-token-ctq4p: cm-volume:
Type: ConfigMap (a volume populated by a ConfigMap)
Name: cm-data
Optional: false
sec-volume:
Type: Secret (a volume populated by a Secret) Type: Secret (a volume populated by a Secret)
SecretName: default-token-ctq4p SecretName: secret-data
Optional: false Optional: false
... ...
@ -410,8 +541,8 @@ Here is an example of updating CNF:
.. code-block:: console .. code-block:: console
$ openstack vnflcm update 9d2bd0d7-4248-445d-a70f-a14cf57d6f96 --I sample_param_file.json $ openstack vnflcm update f21814f0-3e00-4651-a9ac-ec10f3248c19 --I sample_param_file.json
Update vnf:9d2bd0d7-4248-445d-a70f-a14cf57d6f96 Update vnf:f21814f0-3e00-4651-a9ac-ec10f3248c19
The resources information after update: The resources information after update:
@ -433,6 +564,21 @@ The resources information after update:
foo2 foo2
bar2 bar2
Events: <none> Events: <none>
$
$ kubectl describe configmaps cm-data2
Name: cm-data2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
cmKey1.txt:
----
configmap data
foo
bar
Events: <none>
* Secret * Secret
@ -450,26 +596,169 @@ The resources information after update:
==== ====
password: 16 bytes password: 16 bytes
secKey1.txt: 18 bytes secKey1.txt: 18 bytes
$
$ kubectl describe secrets secret-data2
Name: secret-data2
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 15 bytes
secKey1.txt: 15 bytes
* Pod * Pod
.. code-block:: console .. code-block:: console
$ kubectl get pod -o wide $ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
env-test 1/1 Running 1 5h45m 10.233.96.4 node2 <none> <none> daemonset-gl4kf 1/1 Running 0 38m 10.233.96.27 node2 <none> <none>
vdu1-5974f79c95-xs48r 1/1 Running 0 5m17s 10.233.96.7 node2 <none> <none> deployment1-5974f79c95-5d6x4 1/1 Running 0 38m 10.233.96.25 node2 <none> <none>
vdu2-mfn78 1/1 Running 0 5h45m 10.233.96.2 node2 <none> <none> deployment2-5c6b485699-mdx9v 1/1 Running 0 114m 10.233.96.22 node2 <none> <none>
volume-test 1/1 Running 1 5h45m 10.233.96.3 node2 <none> <none> env-test1 1/1 Running 1 114m 10.233.96.21 node2 <none> <none>
$ kubectl describe pod volume-test env-test2 1/1 Running 0 114m 10.233.96.19 node2 <none> <none>
Name: volume-test replicaset-xfgmj 1/1 Running 0 38m 10.233.96.26 node2 <none> <none>
volume-test1 1/1 Running 1 114m 10.233.96.18 node2 <none> <none>
volume-test2 1/1 Running 0 114m 10.233.96.23 node2 <none> <none>
$
$ kubectl describe pod volume-test1
Name: volume-test1
Namespace: default Namespace: default
... ...
Containers: Containers:
nginx: nginx:
Container ID: docker://d3b101bff4863eef62c7a89cb07268d236a72c5b47cc46f167a1dbdf7900220f Container ID: docker://77f1518b617403115163874f1ea65793b92f7c8d22f5364fe5bb299b471decb1
Image: cirros Image: cirros
Image ID: docker-pullable://cirros@sha256:1e695eb2772a2b511ccab70091962d1efb9501fdca804eb1d52d21c0933e7f47 Image ID: docker-pullable://cirros@sha256:be6f5d1ab1e463e7991ecb29f1e71993d633ff1d190188662085ef641bdcf389
...
Volumes:
cm-volume:
Type: ConfigMap (a volume populated by a ConfigMap)
Name: cm-data
Optional: false
sec-volume:
Type: Secret (a volume populated by a Secret)
SecretName: secret-data
Optional: false
...
$
$ kubectl describe pod volume-test2
Name: volume-test2
Namespace: default
...
Containers:
nginx:
Container ID: docker://74d38aa62097b3a1a80181195ebda3877e3773311d0273fdc3fbb27fa4b9600d
Image: nginx
Image ID: docker-pullable://nginx@sha256:ecc068890de55a75f1a32cc8063e79f90f0b043d70c5fcf28f1713395a4b3d49
...
Volumes:
cm-volume:
Type: ConfigMap (a volume populated by a ConfigMap)
Name: cm-data2
Optional: false
sec-volume:
Type: Secret (a volume populated by a Secret)
SecretName: secret-data2
Optional: false
...
* Deployment
.. code-block:: console
$ kubectl get deployments.apps -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment1 1/1 1 1 4h10m nginx cirros app=webserver
deployment2 1/1 1 1 4h10m nginx nginx app=webserver
$
$ kubectl describe pod deployment1-5974f79c95-5d6x4
Name: deployment1-5974f79c95-5d6x4
Namespace: default
...
Containers:
nginx:
Container ID: docker://7b8bd5a7da875fea74a0b0d54ad8a6c1e65bf08a823ae864c6bd7f16b494b990
Image: cirros
Image ID: docker-pullable://cirros@sha256:be6f5d1ab1e463e7991ecb29f1e71993d633ff1d190188662085ef641bdcf389
...
Environment Variables from:
cm-data ConfigMap with prefix 'CM_' Optional: false
secret-data Secret with prefix 'SEC_' Optional: false
Environment:
CMENV: <set to the key 'cmKey1.txt' of config map 'cm-data'> Optional: false
SECENV: <set to the key 'password' in secret 'secret-data'> Optional: false
...
$
$ kubectl describe pod deployment2-5c6b485699-mdx9v
Name: deployment2-5c6b485699-mdx9v
Namespace: default
...
Containers:
nginx:
Container ID: docker://6d7a8019984c04ab758b962a228f44fb14bfc0f4e1f525548d87a91d17b49f77
Image: nginx
Image ID: docker-pullable://nginx@sha256:ecc068890de55a75f1a32cc8063e79f90f0b043d70c5fcf28f1713395a4b3d49
...
Environment Variables from:
cm-data2 ConfigMap with prefix 'CM_' Optional: false
secret-data2 Secret with prefix 'SEC_' Optional: false
Environment:
CMENV: <set to the key 'cmKey1.txt' of config map 'cm-data2'> Optional: false
SECENV: <set to the key 'password' in secret 'secret-data2'> Optional: false
...
* DaemonSet
.. code-block:: console
$ kubectl get daemonset.apps -o wide
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
daemonset 1 1 1 1 1 <none> 4h14m nginx cirros app=nginx
$
$ kubectl describe pod daemonset-gl4kf
Name: daemonset-gl4kf
Namespace: default
...
Containers:
nginx:
Container ID: docker://98712bf43f41fce1983d46cefcfab7ed72f6159f6eb18ab763d9707caf887d8c
Image: cirros
Image ID: docker-pullable://cirros@sha256:be6f5d1ab1e463e7991ecb29f1e71993d633ff1d190188662085ef641bdcf389
...
Environment Variables from:
cm-data ConfigMap with prefix 'CM_' Optional: false
secret-data Secret with prefix 'SEC_' Optional: false
Environment:
CMENV: <set to the key 'cmKey1.txt' of config map 'cm-data'> Optional: false
SECENV: <set to the key 'password' in secret 'secret-data'> Optional: false
...
* ReplicaSet
.. code-block:: console
$ kubectl get replicaset.apps -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
deployment1-5974f79c95 1 1 1 3h5m nginx cirros app=webserver,pod-template-hash=5974f79c95
deployment1-85dd489b89 0 0 0 4h20m nginx nginx app=webserver,pod-template-hash=85dd489b89
deployment2-5c6b485699 1 1 1 4h20m nginx nginx app=webserver,pod-template-hash=5c6b485699
replicaset 1 1 1 4h20m nginx cirros app=webserver
$
$ kubectl describe pod replicaset-xfgmj
Name: replicaset-xfgmj
Namespace: default
...
Containers:
nginx:
Container ID: docker://a9cf17fd465780e5f3e557a1c5d27e0c8ccf5f31a0fd106d9dc891971fed455d
Image: cirros
Image ID: docker-pullable://cirros@sha256:be6f5d1ab1e463e7991ecb29f1e71993d633ff1d190188662085ef641bdcf389
... ...
Volumes: Volumes:
cm-volume: cm-volume:
@ -482,39 +771,10 @@ The resources information after update:
Optional: false Optional: false
... ...
* Deployment You can see that only the Pods are restarted whose ConfigMap/Secret or images
are updated. When it comes to Deployments, DaemonSets and ReplicaSets whose
.. code-block:: console ConfigMap/Secret or images are updated, their pods will be deleted and
recreated.
$ kubectl get deployments.apps -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
vdu1 1/1 1 1 5h50m nginx cirros app=webserver
$ kubectl describe pod vdu1-5974f79c95-xs48r
Name: vdu1-5974f79c95-xs48r
Namespace: default
...
Containers:
nginx:
Container ID: docker://6cad9f692f839d08b53fae58fe2ab06f576271d15aae8744ac0ce57c34510fe0
Image: cirros
Image ID: docker-pullable://cirros@sha256:1e695eb2772a2b511ccab70091962d1efb9501fdca804eb1d52d21c0933e7f47
...
Environment Variables from:
cm-data ConfigMap with prefix 'CM_' Optional: false
secret-data Secret with prefix 'SEC_' Optional: false
Environment:
CMENV: <set to the key 'cmKey1.txt' of config map 'cm-data'> Optional: false
SECENV: <set to the key 'password' in secret 'secret-data'> Optional: false
...
Volumes:
default-token-ctq4p:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-ctq4p
Optional: false
...
You can see that the ConfigMap and Secret are updated, as are the images in
the Pod and Deployment.
.. _NFV-SOL001 v2.6.1 : https://www.etsi.org/deliver/etsi_gs/NFV-SOL/001_099/001/02.06.01_60/gs_NFV-SOL001v020601p.pdf .. _NFV-SOL001 v2.6.1 : https://www.etsi.org/deliver/etsi_gs/NFV-SOL/001_099/001/02.06.01_60/gs_NFV-SOL001v020601p.pdf
.. _Set Tacker Configuration : https://docs.openstack.org/tacker/latest/user/mgmt_driver_deploy_k8s_usage_guide.html#set-tacker-configuration .. _Set Tacker Configuration : https://docs.openstack.org/tacker/latest/user/mgmt_driver_deploy_k8s_usage_guide.html#set-tacker-configuration

View File

@ -0,0 +1,9 @@
---
features:
- |
In the current implementation, when users invoke update operation of
ConfigMaps and Secrets, all Pods are restarted even if they don't use
those updated ConfigMaps and Secrets.
Remove this limitation by filtering out resources that use
Configmaps/Secrets and restarting those resources.

View File

@ -88,13 +88,48 @@ class ContainerUpdateMgmtDriver(vnflcm_abstract_driver.
return k8s_objs return k8s_objs
def _modify_container_img(self, old_containers, new_containers): def _modify_container_img(self, old_containers, new_containers):
flag = False
for old_container in old_containers: for old_container in old_containers:
for new_container in new_containers: for new_container in new_containers:
if (old_container.name == new_container.name and if (old_container.name == new_container.name and
old_container.image != new_container.image): old_container.image != new_container.image):
# Replace the old image with the new image # Replace the old image with the new image
flag = True
old_container.image = new_container.image old_container.image = new_container.image
break break
return flag
def _is_config_updated(self, k8s_resource_info, modify_config_names):
containers = None
volumes = None
k8s_obj_kind = k8s_resource_info.kind
if k8s_obj_kind == 'Pod':
containers = k8s_resource_info.spec.containers
volumes = k8s_resource_info.spec.volumes
elif k8s_obj_kind in ('Deployment', 'ReplicaSet', 'DaemonSet'):
containers = k8s_resource_info.spec.template.spec.containers
volumes = k8s_resource_info.spec.template.spec.volumes
if containers:
for container in containers:
if container.env:
for env in container.env:
if env.value_from.config_map_key_ref and (
env.value_from.config_map_key_ref.name
in modify_config_names):
return True
if env.value_from.secret_key_ref and (
env.value_from.secret_key_ref.name
in modify_config_names):
return True
if volumes:
for volume in volumes:
if volume.config_map and (
volume.config_map.name in modify_config_names):
return True
if volume.secret and (
volume.secret.secret_name in modify_config_names):
return True
return False
def _replace_api(self, k8s_clients, namespace, k8s_obj): def _replace_api(self, k8s_clients, namespace, k8s_obj):
# get api # get api
@ -197,6 +232,9 @@ class ContainerUpdateMgmtDriver(vnflcm_abstract_driver.
vnf_instance.vim_connection_info) vnf_instance.vim_connection_info)
vim_connection_info = objects.VimConnectionInfo.obj_from_primitive( vim_connection_info = objects.VimConnectionInfo.obj_from_primitive(
vim_info, context) vim_info, context)
# the name of updated configmap/secret will be in this set
modify_config_names = set()
for configmap_secret_path in configmap_secret_paths: for configmap_secret_path in configmap_secret_paths:
# Read the contents of the manifest file and get name and kind # Read the contents of the manifest file and get name and kind
configmap_secrets = self._get_kind_and_name(configmap_secret_path, configmap_secrets = self._get_kind_and_name(configmap_secret_path,
@ -215,6 +253,8 @@ class ContainerUpdateMgmtDriver(vnflcm_abstract_driver.
new_inst_vnf_info.additional_params[ new_inst_vnf_info.additional_params[
'lcm-kubernetes-def-files'][ 'lcm-kubernetes-def-files'][
index] = configmap_secret_path index] = configmap_secret_path
for obj in resource:
modify_config_names.add(obj['name'])
break break
raise exceptions.MgmtDriverOtherError( raise exceptions.MgmtDriverOtherError(
error_message='The number of resources in the ' error_message='The number of resources in the '
@ -249,7 +289,10 @@ class ContainerUpdateMgmtDriver(vnflcm_abstract_driver.
for old_k8s_obj in old_k8s_objs: for old_k8s_obj in old_k8s_objs:
old_k8s_obj_kind = old_k8s_obj['object'].kind old_k8s_obj_kind = old_k8s_obj['object'].kind
old_k8s_obj_name = old_k8s_obj['object'].metadata.name old_k8s_obj_name = old_k8s_obj['object'].metadata.name
if old_k8s_obj_kind in ['Pod', 'Deployment']: if old_k8s_obj_kind in ('Pod', 'Deployment',
'ReplicaSet', 'DaemonSet'):
image_modify_flag = False
config_modify_flag = False
for new_k8s_obj in new_k8s_objs: for new_k8s_obj in new_k8s_objs:
# If the old and new k8s_obj have the same kind and name # If the old and new k8s_obj have the same kind and name
new_k8s_obj_kind = new_k8s_obj['object'].kind new_k8s_obj_kind = new_k8s_obj['object'].kind
@ -268,7 +311,12 @@ class ContainerUpdateMgmtDriver(vnflcm_abstract_driver.
# Assign old_k8s_resource_info to old_k8s_obj['object'] # Assign old_k8s_resource_info to old_k8s_obj['object']
old_k8s_obj['object'] = old_k8s_resource_info old_k8s_obj['object'] = old_k8s_resource_info
if old_k8s_obj_kind == 'Deployment': # if config of Pod/Deployment/ReplicaSet/DaemonSet
# is to be updated then set config_modify_flag True
config_modify_flag = self._is_config_updated(
old_k8s_resource_info, modify_config_names)
if old_k8s_obj_kind in ('Deployment', 'ReplicaSet',
'DaemonSet'):
old_containers = (old_k8s_obj['object'].spec old_containers = (old_k8s_obj['object'].spec
.template.spec.containers) .template.spec.containers)
new_containers = (new_k8s_obj['object'].spec new_containers = (new_k8s_obj['object'].spec
@ -279,12 +327,13 @@ class ContainerUpdateMgmtDriver(vnflcm_abstract_driver.
new_containers = (new_k8s_obj['object'] new_containers = (new_k8s_obj['object']
.spec.containers) .spec.containers)
# Replace the old image with the new image # Replace the old image with the new image
self._modify_container_img(old_containers, image_modify_flag = self._modify_container_img(
new_containers) old_containers, new_containers)
break break
# Append only old_k8s_obj whose image or config would
# Append old_k8s_obj to k8s_pod_objs # be updated to k8s_pod_objs
k8s_pod_objs.append(old_k8s_obj) if image_modify_flag or config_modify_flag:
k8s_pod_objs.append(old_k8s_obj)
elif old_k8s_obj_kind in ['ConfigMap', 'Secret']: elif old_k8s_obj_kind in ['ConfigMap', 'Secret']:
for new_k8s_obj in new_k8s_objs: for new_k8s_obj in new_k8s_objs:
# If the old and new k8s_obj have the same kind and name # If the old and new k8s_obj have the same kind and name
@ -292,18 +341,36 @@ class ContainerUpdateMgmtDriver(vnflcm_abstract_driver.
new_k8s_obj_name = new_k8s_obj['object'].metadata.name new_k8s_obj_name = new_k8s_obj['object'].metadata.name
if old_k8s_obj_kind == new_k8s_obj_kind and ( if old_k8s_obj_kind == new_k8s_obj_kind and (
old_k8s_obj_name == new_k8s_obj_name): old_k8s_obj_name == new_k8s_obj_name):
# Append old_k8s_obj to k8s_pod_objs # Append new_k8s_obj to k8s_config_objs
k8s_config_objs.append(new_k8s_obj) k8s_config_objs.append(new_k8s_obj)
break break
for k8s_config_obj in k8s_config_objs: for k8s_config_obj in k8s_config_objs:
# Call the replace API # Call the replace API
self._replace_api(k8s_clients, namespace, k8s_config_obj) self._replace_api(k8s_clients, namespace, k8s_config_obj)
core_v1_api_client = k8s_clients['v1']
pods = core_v1_api_client.list_namespaced_pod(namespace=namespace)
for k8s_pod_obj in k8s_pod_objs: for k8s_pod_obj in k8s_pod_objs:
# Call the replace API # Call the replace API
self._replace_api(k8s_clients, namespace, k8s_pod_obj) self._replace_api(k8s_clients, namespace, k8s_pod_obj)
# delete pod of modified replicaset
# After using the replace_namespaced_replicaset API of k8s,
# the new configuration cannot be applied to the pod created
# by the replicaset, so you need to delete the pod first, and
# then the replicaset will automatically rebuild the pod to make
# the new configuration take effect.
if k8s_pod_obj['object'].kind == 'ReplicaSet':
for pod in pods.items:
match_result = kube_driver.is_match_pod_naming_rule(
'ReplicaSet',
k8s_pod_obj['object'].metadata.name,
pod.metadata.name)
if match_result:
core_v1_api_client.delete_namespaced_pod(
namespace=namespace,
name=pod.metadata.name,
body=pod)
# _replace_wait_k8s # _replace_wait_k8s
core_v1_api_client = k8s_clients['v1']
self._replace_wait_k8s(kube_driver, k8s_pod_objs, core_v1_api_client, self._replace_wait_k8s(kube_driver, k8s_pod_objs, core_v1_api_client,
vnf_instance) vnf_instance)
# Get all pod information under the specified namespace # Get all pod information under the specified namespace

View File

@ -87,6 +87,43 @@ topology_template:
vdu_profile: vdu_profile:
min_number_of_instances: 1 min_number_of_instances: 1
max_number_of_instances: 1 max_number_of_instances: 1
VDU5:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: daemonset-vdu5
description: kubernetes resource as VDU5
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 1
VDU6:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: deployment2-vdu6
description: kubernetes resource as VDU6
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 1
VDU7:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: env-test2
description: kubernetes resource as VDU7
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 1
VDU8:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: volume-test2
description: kubernetes resource as VDU8
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 1
policies: policies:
- scaling_aspects: - scaling_aspects:
type: tosca.policies.nfv.ScalingAspects type: tosca.policies.nfv.ScalingAspects

View File

@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-data3
data:
cmKey1.txt: |
configmap data
foo
bar

View File

@ -0,0 +1,38 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: daemonset-vdu5
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: cirros
name: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
env:
- name: CMENV
valueFrom:
configMapKeyRef:
name: cm-data
key: cmKey1.txt
- name: SECENV
valueFrom:
secretKeyRef:
name: secret-data
key: password
envFrom:
- prefix: CM_
configMapRef:
name: cm-data
- prefix: SEC_
secretRef:
name: secret-data

View File

@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment2-vdu6
spec:
replicas: 1
selector:
matchLabels:
app: webserver
template:
metadata:
labels:
app: webserver
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
env:
- name: CMENV
valueFrom:
configMapKeyRef:
name: cm-data3
key: cmKey1.txt
- name: SECENV
valueFrom:
secretKeyRef:
name: secret-data3
key: password
envFrom:
- prefix: CM_
configMapRef:
name: cm-data3
- prefix: SEC_
secretRef:
name: secret-data3

View File

@ -0,0 +1,26 @@
apiVersion: v1
kind: Pod
metadata:
name: env-test2
spec:
containers:
- image: nginx
name: nginx
env:
- name: CMENV
valueFrom:
configMapKeyRef:
name: cm-data3
key: cmKey1.txt
- name: SECENV
valueFrom:
secretKeyRef:
name: secret-data3
key: password
envFrom:
- prefix: CM_
configMapRef:
name: cm-data3
- prefix: SEC_
secretRef:
name: secret-data3

View File

@ -6,3 +6,23 @@ spec:
containers: containers:
- image: cirros - image: cirros
name: nginx name: nginx
volumeMounts:
- name: cm-volume
mountPath: /config
- name: sec-volume
mountPath: /etc/secrets
volumes:
- name: cm-volume
configMap:
name: cm-data
defaultMode: 0666
items:
- key: cmKey1.txt
path: cm/config.txt
- name: sec-volume
secret:
secretName: secret-data
defaultMode: 0600
items:
- key: secKey1.txt
path: creds/secret.txt

View File

@ -0,0 +1,28 @@
apiVersion: v1
kind: Pod
metadata:
name: volume-test2
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: cm-volume
mountPath: /config
- name: sec-volume
mountPath: /etc/secrets
volumes:
- name: cm-volume
configMap:
name: cm-data3
defaultMode: 0666
items:
- key: cmKey1.txt
path: cm/config.txt
- name: sec-volume
secret:
secretName: secret-data3
defaultMode: 0600
items:
- key: secKey1.txt
path: creds/secret.txt

View File

@ -0,0 +1,9 @@
apiVersion: v1
kind: Secret
metadata:
name: secret-data3
stringData:
password: 1mbb1G968fb1CUg
secKey1.txt: |
secret data
baz

View File

@ -8,20 +8,45 @@ Content-Type: application/yaml
Algorithm: SHA-256 Algorithm: SHA-256
Hash: 6f34907da12cb5ad82b25d8e7dd6a7dd4219bd0cbad65e678b58b8466be220e0 Hash: 6f34907da12cb5ad82b25d8e7dd6a7dd4219bd0cbad65e678b58b8466be220e0
Name: Files/kubernetes/configmap_3.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 77561abb949dbc3e71cc7cc5311556f37e69e14743fb6dfe44617ad9929ce615
Name: Files/kubernetes/daemonset.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 5431163fcba979bcad5f77ef956a5a1cc2069ff0f3e13131ef8826fb7e8f039b
Name: Files/kubernetes/deployment.yaml Name: Files/kubernetes/deployment.yaml
Content-Type: application/yaml Content-Type: application/yaml
Algorithm: SHA-256 Algorithm: SHA-256
Hash: 290debe315bb5b098f73d63049ba850cc5df3723447637bddc1cabe3d0e151d7 Hash: 290debe315bb5b098f73d63049ba850cc5df3723447637bddc1cabe3d0e151d7
Name: Files/kubernetes/deployment_2.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 3c89ba20b8e49a4d24297e0392e2f8774319cbe131bd28dfe80a263c0f0ce6e0
Name: Files/kubernetes/pod_env.yaml Name: Files/kubernetes/pod_env.yaml
Content-Type: application/yaml Content-Type: application/yaml
Algorithm: SHA-256 Algorithm: SHA-256
Hash: b8674c55cd387fd2ab3d550bc622b314bed151d0afffe4f6bc44a553280d400c Hash: b8674c55cd387fd2ab3d550bc622b314bed151d0afffe4f6bc44a553280d400c
Name: Files/kubernetes/pod_env_2.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 2193e9633c750886ad6d19013887ffe550c94c1da0985fbe60ce8663022c67a5
Name: Files/kubernetes/pod_volume.yaml Name: Files/kubernetes/pod_volume.yaml
Content-Type: application/yaml Content-Type: application/yaml
Algorithm: SHA-256 Algorithm: SHA-256
Hash: e74cd59b3e91ca1a8fb103b13ef15965581639883cc6d8a531f959b4ae89e688 Hash: 87507e140db298662b6cf3bc905be42b6697a6724d86ca661bbf28e18ae19397
Name: Files/kubernetes/pod_volume_2.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 5e29e35c849b2b8677efe8d6ec8554d638481bd41b4705856382698d96bcb040
Name: Files/kubernetes/replicaset.yaml Name: Files/kubernetes/replicaset.yaml
Content-Type: application/yaml Content-Type: application/yaml
@ -33,7 +58,12 @@ Content-Type: application/yaml
Algorithm: SHA-256 Algorithm: SHA-256
Hash: f57cbb1822c57e523e5c6d48feea37ee1b1bbd976d720baf8491d47331249e11 Hash: f57cbb1822c57e523e5c6d48feea37ee1b1bbd976d720baf8491d47331249e11
Name: Files/kubernetes/secret_3.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 2a1b16ab7e9ee34a23a67a3aa0535311c927f4194b639bcb0a70905578940695
Name: Scripts/container_update_mgmt.py Name: Scripts/container_update_mgmt.py
Content-Type: text/x-python Content-Type: text/x-python
Algorithm: SHA-256 Algorithm: SHA-256
Hash: 9e272402dd0f6f6b39ffc750590eedef028ce22506eb7436a1a1fcfa76c66423 Hash: 334316e69326a0aaad58dc339bc3541786f96bbf1345e9770759d9cab60382f9

View File

@ -87,6 +87,43 @@ topology_template:
vdu_profile: vdu_profile:
min_number_of_instances: 1 min_number_of_instances: 1
max_number_of_instances: 1 max_number_of_instances: 1
VDU5:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: daemonset-vdu5
description: kubernetes resource as VDU5
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 1
VDU6:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: deployment2-vdu6
description: kubernetes resource as VDU6
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 1
VDU7:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: env-test2
description: kubernetes resource as VDU7
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 1
VDU8:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: volume-test2
description: kubernetes resource as VDU8
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 1
policies: policies:
- scaling_aspects: - scaling_aspects:
type: tosca.policies.nfv.ScalingAspects type: tosca.policies.nfv.ScalingAspects

View File

@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-data3
data:
cmKey1.txt: |
configmap data
foo
bar

View File

@ -0,0 +1,38 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: daemonset-vdu5
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
env:
- name: CMENV
valueFrom:
configMapKeyRef:
name: cm-data
key: cmKey1.txt
- name: SECENV
valueFrom:
secretKeyRef:
name: secret-data
key: password
envFrom:
- prefix: CM_
configMapRef:
name: cm-data
- prefix: SEC_
secretRef:
name: secret-data

View File

@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment2-vdu6
spec:
replicas: 1
selector:
matchLabels:
app: webserver
template:
metadata:
labels:
app: webserver
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
env:
- name: CMENV
valueFrom:
configMapKeyRef:
name: cm-data3
key: cmKey1.txt
- name: SECENV
valueFrom:
secretKeyRef:
name: secret-data3
key: password
envFrom:
- prefix: CM_
configMapRef:
name: cm-data3
- prefix: SEC_
secretRef:
name: secret-data3

View File

@ -0,0 +1,26 @@
apiVersion: v1
kind: Pod
metadata:
name: env-test2
spec:
containers:
- image: nginx
name: nginx
env:
- name: CMENV
valueFrom:
configMapKeyRef:
name: cm-data3
key: cmKey1.txt
- name: SECENV
valueFrom:
secretKeyRef:
name: secret-data3
key: password
envFrom:
- prefix: CM_
configMapRef:
name: cm-data3
- prefix: SEC_
secretRef:
name: secret-data3

View File

@ -0,0 +1,28 @@
apiVersion: v1
kind: Pod
metadata:
name: volume-test2
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: cm-volume
mountPath: /config
- name: sec-volume
mountPath: /etc/secrets
volumes:
- name: cm-volume
configMap:
name: cm-data3
defaultMode: 0666
items:
- key: cmKey1.txt
path: cm/config.txt
- name: sec-volume
secret:
secretName: secret-data3
defaultMode: 0600
items:
- key: secKey1.txt
path: creds/secret.txt

View File

@ -0,0 +1,9 @@
apiVersion: v1
kind: Secret
metadata:
name: secret-data3
stringData:
password: 1mbb1G968fb1CUg
secKey1.txt: |
secret data
baz

View File

@ -8,21 +8,46 @@ Content-Type: application/yaml
Algorithm: SHA-256 Algorithm: SHA-256
Hash: b914022a12c7a0f3a6a7d14013020f1271645ab44b17942a014fdc8ad96f42fe Hash: b914022a12c7a0f3a6a7d14013020f1271645ab44b17942a014fdc8ad96f42fe
Name: Files/kubernetes/configmap_3.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 77561abb949dbc3e71cc7cc5311556f37e69e14743fb6dfe44617ad9929ce615
Name: Files/kubernetes/daemonset.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 289386c71936b758022646248bfd3af90e87e42e6bbf203a6e32cd70905806e6
Name: Files/kubernetes/deployment.yaml Name: Files/kubernetes/deployment.yaml
Content-Type: application/yaml Content-Type: application/yaml
Algorithm: SHA-256 Algorithm: SHA-256
Hash: 03b61e9646925ddf414489212736b7d799710b26dc70f96641c50e699f0a1d5f Hash: 03b61e9646925ddf414489212736b7d799710b26dc70f96641c50e699f0a1d5f
Name: Files/kubernetes/deployment_2.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 3c89ba20b8e49a4d24297e0392e2f8774319cbe131bd28dfe80a263c0f0ce6e0
Name: Files/kubernetes/pod_env.yaml Name: Files/kubernetes/pod_env.yaml
Content-Type: application/yaml Content-Type: application/yaml
Algorithm: SHA-256 Algorithm: SHA-256
Hash: 2e69400cf742fd88cb9ba5abd0b83ba9dd12f46f36fa615d5b93e07af47a2b5d Hash: 2e69400cf742fd88cb9ba5abd0b83ba9dd12f46f36fa615d5b93e07af47a2b5d
Name: Files/kubernetes/pod_env_2.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 2193e9633c750886ad6d19013887ffe550c94c1da0985fbe60ce8663022c67a5
Name: Files/kubernetes/pod_volume.yaml Name: Files/kubernetes/pod_volume.yaml
Content-Type: application/yaml Content-Type: application/yaml
Algorithm: SHA-256 Algorithm: SHA-256
Hash: 93bd20b9c2111115131a96769b710e09001248ba9c3d3f33e1d616d0b9546728 Hash: 93bd20b9c2111115131a96769b710e09001248ba9c3d3f33e1d616d0b9546728
Name: Files/kubernetes/pod_volume_2.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 5e29e35c849b2b8677efe8d6ec8554d638481bd41b4705856382698d96bcb040
Name: Files/kubernetes/replicaset.yaml Name: Files/kubernetes/replicaset.yaml
Content-Type: application/yaml Content-Type: application/yaml
Algorithm: SHA-256 Algorithm: SHA-256
@ -33,7 +58,12 @@ Content-Type: application/yaml
Algorithm: SHA-256 Algorithm: SHA-256
Hash: 8c170000410e72c1b81784061928cde26d1f9ea027fbece4da34ced08da8c4b4 Hash: 8c170000410e72c1b81784061928cde26d1f9ea027fbece4da34ced08da8c4b4
Name: Files/kubernetes/secret_3.yaml
Content-Type: application/yaml
Algorithm: SHA-256
Hash: 2a1b16ab7e9ee34a23a67a3aa0535311c927f4194b639bcb0a70905578940695
Name: Scripts/container_update_mgmt.py Name: Scripts/container_update_mgmt.py
Content-Type: text/x-python Content-Type: text/x-python
Algorithm: SHA-256 Algorithm: SHA-256
Hash: 9e272402dd0f6f6b39ffc750590eedef028ce22506eb7436a1a1fcfa76c66423 Hash: 334316e69326a0aaad58dc339bc3541786f96bbf1345e9770759d9cab60382f9

View File

@ -48,7 +48,14 @@ class VnfLcmKubernetesContainerUpdate(vnflcm_base.BaseVnfLcmKubernetesTest):
"Files/kubernetes/pod_env.yaml", "Files/kubernetes/pod_env.yaml",
"Files/kubernetes/pod_volume.yaml", "Files/kubernetes/pod_volume.yaml",
"Files/kubernetes/replicaset.yaml", "Files/kubernetes/replicaset.yaml",
"Files/kubernetes/secret_1.yaml"] "Files/kubernetes/secret_1.yaml",
"Files/kubernetes/configmap_3.yaml",
"Files/kubernetes/pod_env_2.yaml",
"Files/kubernetes/pod_volume_2.yaml",
"Files/kubernetes/daemonset.yaml",
"Files/kubernetes/deployment_2.yaml",
"Files/kubernetes/secret_3.yaml",
]
additional_param = { additional_param = {
"lcm-kubernetes-def-files": files, "lcm-kubernetes-def-files": files,
"namespace": "default"} "namespace": "default"}
@ -59,7 +66,7 @@ class VnfLcmKubernetesContainerUpdate(vnflcm_base.BaseVnfLcmKubernetesTest):
vnf_instance_description, additional_param) vnf_instance_description, additional_param)
before_vnfc_rscs = self._get_vnfc_resource_info(vnf_instance) before_vnfc_rscs = self._get_vnfc_resource_info(vnf_instance)
self.assertEqual(4, len(before_vnfc_rscs)) self.assertEqual(8, len(before_vnfc_rscs))
# modify # modify
vnf_instance_name = "modify_vnf_after" vnf_instance_name = "modify_vnf_after"
@ -76,14 +83,17 @@ class VnfLcmKubernetesContainerUpdate(vnflcm_base.BaseVnfLcmKubernetesTest):
vnf_instance_after, after_vnfc_rscs = self._modify_vnf_instance( vnf_instance_after, after_vnfc_rscs = self._modify_vnf_instance(
vnf_instance['id'], modify_request_body) vnf_instance['id'], modify_request_body)
self.assertEqual(4, len(after_vnfc_rscs)) self.assertEqual(8, len(after_vnfc_rscs))
for after_vnfc_rsc in after_vnfc_rscs: for after_vnfc_rsc in after_vnfc_rscs:
for before_vnfc_rsc in before_vnfc_rscs: for before_vnfc_rsc in before_vnfc_rscs:
after_resource = after_vnfc_rsc['computeResource'] after_resource = after_vnfc_rsc['computeResource']
before_resource = before_vnfc_rsc['computeResource'] before_resource = before_vnfc_rsc['computeResource']
if after_vnfc_rsc['id'] == before_vnfc_rsc['id']: if after_vnfc_rsc['id'] == before_vnfc_rsc['id']:
if after_resource['vimLevelResourceType'] == 'Deployment': if (after_resource['vimLevelResourceType'] in
('Deployment', 'ReplicaSet', 'DaemonSet')
and after_vnfc_rsc['vduId'] in
('VDU1', 'VDU2', 'VDU5')):
# check stored pod name is changed (Deployment) # check stored pod name is changed (Deployment)
self.assertNotEqual(before_resource['resourceId'], self.assertNotEqual(before_resource['resourceId'],
after_resource['resourceId']) after_resource['resourceId'])

View File

@ -24,7 +24,6 @@ from tacker.tests import uuidsentinel
def get_vnf_instance_object( def get_vnf_instance_object(
instantiation_state=fields.VnfInstanceState.NOT_INSTANTIATED): instantiation_state=fields.VnfInstanceState.NOT_INSTANTIATED):
inst_vnf_info = get_vnf_instantiated_info() inst_vnf_info = get_vnf_instantiated_info()
vnf_instance = objects.VnfInstance( vnf_instance = objects.VnfInstance(
@ -93,6 +92,313 @@ def fake_pod():
) )
def fake_pod_container_config_changed():
return client.V1Pod(
api_version='v1',
kind='Pod',
metadata=client.V1ObjectMeta(
name='volume-test',
namespace='default'
),
spec=client.V1PodSpec(
containers=[
client.V1Container(
image="cirros",
name="nginx",
env=[
client.V1EnvVar(
name='param0',
value_from=client.V1EnvVarSource(
config_map_key_ref=client.
V1ConfigMapKeySelector(
key='param0',
name='cm-data'
)
)
),
client.V1EnvVar(
name='param1',
value_from=client.V1EnvVarSource(
secret_key_ref=client.
V1SecretKeySelector(
key='password',
name='secret-data'
)
)
)
],
)
]
),
status=client.V1PodStatus(
phase='Running',
)
)
def fake_pod_volume_config_changed():
return client.V1Pod(
api_version='v1',
kind='Pod',
metadata=client.V1ObjectMeta(
name='volume-test',
namespace='default'
),
spec=client.V1PodSpec(
containers=[
client.V1Container(
image="cirros",
name="nginx",
volume_mounts=[
client.V1VolumeMount(
name='cm-volume',
mount_path='/config'
),
client.V1VolumeMount(
name='sec-volume',
mount_path='/etc/secrets'
),
]
)
],
volumes=[
client.V1Volume(
name='cm-volume',
config_map=client.V1ConfigMapVolumeSource(
name='cm-data'
),
),
client.V1Volume(
name='sec-volume',
secret=client.V1SecretVolumeSource(
secret_name='secret-data'
)
)
]
),
status=client.V1PodStatus(
phase='Running',
)
)
def fake_pod_image_changed():
return client.V1Pod(
api_version='v1',
kind='Pod',
metadata=client.V1ObjectMeta(
name='volume-test',
namespace='default'
),
spec=client.V1PodSpec(
containers=[
client.V1Container(
image="nginx-old",
name="nginx",
)
]
),
status=client.V1PodStatus(
phase='Running',
)
)
def fake_replicaset_container_config_changed():
return client.V1ReplicaSet(
api_version='apps/v1',
kind='ReplicaSet',
metadata=client.V1ObjectMeta(
name='vdu2',
namespace='default'
),
spec=client.V1ReplicaSetSpec(
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='cm-data'
)
)
),
client.V1EnvVar(
name='param1',
value_from=client.V1EnvVarSource(
secret_key_ref=client.
V1SecretKeySelector(
key='password',
name='secret-data'
)
)
)
],
image='celebdor/kuryr-demo',
image_pull_policy='IfNotPresent',
name='nginx',
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'
)
]
)
],
termination_grace_period_seconds=0
)
)
),
status=client.V1PodStatus(
phase='Running',
)
)
def fake_replicaset_volume_config_changed():
return client.V1ReplicaSet(
api_version='apps/v1',
kind='ReplicaSet',
metadata=client.V1ObjectMeta(
name='vdu2',
namespace='default'
),
spec=client.V1ReplicaSetSpec(
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(
image='celebdor/kuryr-demo',
image_pull_policy='IfNotPresent',
name='nginx',
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'
),
config_map=client.V1ConfigMapVolumeSource(
default_mode=438,
name='cm-data'
),
secret=client.V1SecretVolumeSource(
secret_name='secret-data'
)
)
],
termination_grace_period_seconds=0
)
)
),
status=client.V1PodStatus(
phase='Running',
)
)
def fake_replicaset_image_changed():
return client.V1ReplicaSet(
api_version='apps/v1',
kind='ReplicaSet',
metadata=client.V1ObjectMeta(
name='vdu2',
namespace='default'
),
spec=client.V1ReplicaSetSpec(
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(
image='celebdor/kuryr-demo-old',
image_pull_policy='IfNotPresent',
name='nginx',
ports=[
client.V1ContainerPort(
container_port=8080
)
],
resources=client.V1ResourceRequirements(
limits={
'cpu': '500m', 'memory': '512M'
},
requests={
'cpu': '500m', 'memory': '512M'
}
),
)
],
termination_grace_period_seconds=0
)
)
),
status=client.V1PodStatus(
phase='Running',
)
)
def fake_list_pod(): def fake_list_pod():
return client.V1PodList( return client.V1PodList(
items=[ items=[

View File

@ -15,6 +15,8 @@
import os import os
from oslo_config import cfg
from kubernetes import client from kubernetes import client
from samples.mgmt_driver.kubernetes.container_update import ( from samples.mgmt_driver.kubernetes.container_update import (
container_update_mgmt as mgmt_driver) container_update_mgmt as mgmt_driver)
@ -39,6 +41,7 @@ class TestContainerUpdate(base.TestCase):
self.context = context.get_admin_context() self.context = context.get_admin_context()
self.cntr_update_mgmt = mgmt_driver.ContainerUpdateMgmtDriver() self.cntr_update_mgmt = mgmt_driver.ContainerUpdateMgmtDriver()
self.vnf_instance = mgmt_fakes.get_vnf_instance_object() self.vnf_instance = mgmt_fakes.get_vnf_instance_object()
cfg.CONF.kubernetes_vim.stack_retry_wait = 0
self.modify_vnf_request = None self.modify_vnf_request = None
self._mock_vim_client() self._mock_vim_client()
self._stub_get_vim() self._stub_get_vim()
@ -108,8 +111,6 @@ class TestContainerUpdate(base.TestCase):
{'namespace': 'default', 'object': mgmt_fakes.fake_pod()} {'namespace': 'default', 'object': mgmt_fakes.fake_pod()}
] ]
kube_driver = Kubernetes() kube_driver = Kubernetes()
kube_driver.STACK_RETRIES = 1
kube_driver.STACK_RETRY_WAIT = 5
mock_list_pod.return_value = mgmt_fakes.fake_list_pod() mock_list_pod.return_value = mgmt_fakes.fake_list_pod()
self.assertRaises( self.assertRaises(
exceptions.MgmtDriverOtherError, exceptions.MgmtDriverOtherError,
@ -137,8 +138,10 @@ class TestContainerUpdate(base.TestCase):
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_config_map') @mock.patch.object(client.CoreV1Api, 'replace_namespaced_config_map')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_pod') @mock.patch.object(client.CoreV1Api, 'replace_namespaced_pod')
@mock.patch.object(client.CoreV1Api, 'read_namespaced_pod') @mock.patch.object(client.CoreV1Api, 'read_namespaced_pod')
@mock.patch.object(client.AppsV1Api, 'read_namespaced_replica_set')
def test_container_update_modify_information_end( def test_container_update_modify_information_end(
self, mock_read_pod, mock_replace_pod, mock_replace_config_map, self, mock_read_replica_set,
mock_read_pod, mock_replace_pod, mock_replace_config_map,
mock_replace_secret, mock_list_pod, mock_vnfd_dict, mock_save): mock_replace_secret, mock_list_pod, mock_vnfd_dict, mock_save):
mock_read_pod.return_value = mgmt_fakes.fake_pod() mock_read_pod.return_value = mgmt_fakes.fake_pod()
mock_list_pod.return_value = client.V1PodList(items=[ mock_list_pod.return_value = client.V1PodList(items=[
@ -154,3 +157,132 @@ class TestContainerUpdate(base.TestCase):
self.cntr_update_mgmt.modify_information_end( self.cntr_update_mgmt.modify_information_end(
self.context, self.vnf_instance, self.modify_vnf_request, **kwargs) self.context, self.vnf_instance, self.modify_vnf_request, **kwargs)
self.assertEqual(1, mock_save.call_count) self.assertEqual(1, mock_save.call_count)
@mock.patch('tacker.objects.vnf_instance.VnfInstance.save')
@mock.patch('tacker.vnflcm.utils._get_vnfd_dict')
@mock.patch.object(client.CoreV1Api, 'list_namespaced_pod')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_secret')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_config_map')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_pod')
@mock.patch.object(client.CoreV1Api, 'read_namespaced_pod')
@mock.patch.object(client.AppsV1Api, 'read_namespaced_replica_set')
@mock.patch.object(client.AppsV1Api, 'replace_namespaced_replica_set')
def test_container_update_modify_information_end_container_config_changed(
self, mock_replace_replica_set, mock_read_replicaset,
mock_read_pod, mock_replace_pod, mock_replace_config_map,
mock_replace_secret, mock_list_pod, mock_vnfd_dict, mock_save,
):
mock_read_replicaset.return_value = (mgmt_fakes.
fake_replicaset_container_config_changed())
mock_read_pod.return_value = (mgmt_fakes.
fake_pod_container_config_changed())
mock_list_pod.return_value = client.V1PodList(items=[
mgmt_fakes.get_fake_pod_info(kind='Pod', name='vdu1')])
mock_vnfd_dict.return_value = fakes.vnfd_dict_cnf()
kwargs = {
'old_vnf_package_path': self.yaml_path_before,
'configmap_secret_paths': [
"Files/kubernetes/configmap_2.yaml",
"Files/kubernetes/secret_2.yaml"
]
}
self.cntr_update_mgmt.modify_information_end(
self.context, self.vnf_instance, self.modify_vnf_request, **kwargs)
self.assertEqual(1, mock_save.call_count)
@mock.patch('tacker.objects.vnf_instance.VnfInstance.save')
@mock.patch('tacker.vnflcm.utils._get_vnfd_dict')
@mock.patch.object(client.CoreV1Api, 'list_namespaced_pod')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_secret')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_config_map')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_pod')
@mock.patch.object(client.CoreV1Api, 'read_namespaced_pod')
@mock.patch.object(client.AppsV1Api, 'read_namespaced_replica_set')
@mock.patch.object(client.AppsV1Api, 'replace_namespaced_replica_set')
def test_container_update_modify_information_end_volume_config_changed(
self, mock_replace_replica_set, mock_read_replicaset,
mock_read_pod, mock_replace_pod, mock_replace_config_map,
mock_replace_secret, mock_list_pod, mock_vnfd_dict, mock_save,
):
mock_read_replicaset.return_value = (mgmt_fakes.
fake_replicaset_volume_config_changed())
mock_read_pod.return_value = (mgmt_fakes.
fake_pod_volume_config_changed())
mock_list_pod.return_value = client.V1PodList(items=[
mgmt_fakes.get_fake_pod_info(kind='Pod', name='vdu1')])
mock_vnfd_dict.return_value = fakes.vnfd_dict_cnf()
kwargs = {
'old_vnf_package_path': self.yaml_path_before,
'configmap_secret_paths': [
"Files/kubernetes/configmap_2.yaml",
"Files/kubernetes/secret_2.yaml"
]
}
self.cntr_update_mgmt.modify_information_end(
self.context, self.vnf_instance, self.modify_vnf_request, **kwargs)
self.assertEqual(1, mock_save.call_count)
@mock.patch('tacker.objects.vnf_instance.VnfInstance.save')
@mock.patch('tacker.vnflcm.utils._get_vnfd_dict')
@mock.patch.object(client.CoreV1Api, 'list_namespaced_pod')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_secret')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_config_map')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_pod')
@mock.patch.object(client.CoreV1Api, 'read_namespaced_pod')
@mock.patch.object(client.AppsV1Api, 'read_namespaced_replica_set')
@mock.patch.object(client.AppsV1Api, 'replace_namespaced_replica_set')
def test_container_update_modify_information_end_image_changed(
self, mock_replace_replica_set, mock_read_replicaset,
mock_read_pod, mock_replace_pod, mock_replace_config_map,
mock_replace_secret, mock_list_pod, mock_vnfd_dict, mock_save,
):
mock_read_replicaset.return_value = (mgmt_fakes.
fake_replicaset_image_changed())
mock_read_pod.return_value = mgmt_fakes.fake_pod_image_changed()
mock_list_pod.return_value = client.V1PodList(items=[
mgmt_fakes.get_fake_pod_info(kind='Pod', name='vdu1')])
mock_vnfd_dict.return_value = fakes.vnfd_dict_cnf()
kwargs = {
'old_vnf_package_path': self.yaml_path_before,
'configmap_secret_paths': [
"Files/kubernetes/configmap_2.yaml",
"Files/kubernetes/secret_2.yaml"
]
}
self.cntr_update_mgmt.modify_information_end(
self.context, self.vnf_instance, self.modify_vnf_request, **kwargs)
self.assertEqual(1, mock_save.call_count)
@mock.patch('tacker.objects.vnf_instance.VnfInstance.save')
@mock.patch('tacker.vnflcm.utils._get_vnfd_dict')
@mock.patch.object(client.CoreV1Api, 'list_namespaced_pod')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_secret')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_config_map')
@mock.patch.object(client.CoreV1Api, 'replace_namespaced_pod')
@mock.patch.object(client.CoreV1Api, 'read_namespaced_pod')
@mock.patch.object(client.AppsV1Api, 'read_namespaced_replica_set')
@mock.patch.object(client.AppsV1Api, 'replace_namespaced_replica_set')
@mock.patch.object(client.CoreV1Api, 'delete_namespaced_pod')
def test_container_update_modify_information_end_replicasetpod_deleted(
self, mock_delete_namespaced_pod,
mock_replace_replica_set, mock_read_replicaset,
mock_read_pod, mock_replace_pod, mock_replace_config_map,
mock_replace_secret, mock_list_pod, mock_vnfd_dict, mock_save,
):
mock_read_replicaset.return_value = (mgmt_fakes.
fake_replicaset_image_changed())
mock_read_pod.return_value = mgmt_fakes.fake_pod()
mock_list_pod.return_value = client.V1PodList(items=[
mgmt_fakes.get_fake_pod_info(kind='Pod',
name='vdu2-rldmg')])
mock_vnfd_dict.return_value = fakes.vnfd_dict_cnf()
kwargs = {
'old_vnf_package_path': self.yaml_path_before,
'configmap_secret_paths': [
"Files/kubernetes/configmap_2.yaml",
"Files/kubernetes/secret_2.yaml"
]
}
self.cntr_update_mgmt.modify_information_end(
self.context, self.vnf_instance, self.modify_vnf_request, **kwargs)
self.assertEqual(1, mock_save.call_count)