summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortianxing <15210838572@139.com>2018-09-21 11:36:45 +0800
committerTian Xing <15210838572@139.com>2018-10-08 03:22:47 +0000
commitbd77d972c666cf7a57b610bea5b29ba99444de78 (patch)
treeab05193d5716cbcdcd026ae57f04c6491e7c3b00
parent6594edc6160fb2a43685e383f0dd8727f2df667f (diff)
add function of update
Change-Id: I7d6107d1f7210ed460c82b8f9a76a4d6bf8566d8 Issue-ID: VFC-1139 Signed-off-by: tianxing <15210838572@139.com>
-rw-r--r--lcm/ns/biz/ns_update.py150
-rw-r--r--lcm/ns/serializers/update_serializers.py2
-rw-r--r--lcm/ns/urls.py5
-rw-r--r--lcm/ns/views/update_ns_view.py57
4 files changed, 211 insertions, 3 deletions
diff --git a/lcm/ns/biz/ns_update.py b/lcm/ns/biz/ns_update.py
new file mode 100644
index 00000000..cb00ced8
--- /dev/null
+++ b/lcm/ns/biz/ns_update.py
@@ -0,0 +1,150 @@
+# Copyright (c) 2018, CMCC Technologies Co., Ltd.
+
+# 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 logging
+import threading
+import traceback
+import datetime
+import time
+
+from lcm.ns.const import NS_INST_STATUS
+from lcm.pub.database.models import JobModel, NSInstModel
+from lcm.ns_vnfs.biz.update_vnfs import NFOperateService
+from lcm.pub.exceptions import NSLCMException
+from lcm.pub.utils.jobutil import JobUtil, JOB_MODEL_STATUS
+from lcm.pub.utils.values import ignore_case_get
+from lcm.pub.utils.enumutil import enum
+
+JOB_ERROR = 255
+logger = logging.getLogger(__name__)
+OPERATIONAL_STATES = enum(STOPPED='STOPPED', STARTED='STARTED')
+STOP_TYPE = enum(GRACEFUL='GRACEFUL', FORCEFUL='FORCEFUL')
+
+
+class NSUpdateService(threading.Thread):
+ def __init__(self, ns_instance_id, request_data, job_id):
+ super(NSUpdateService, self).__init__()
+ self.ns_instance_id = ns_instance_id
+ self.request_data = request_data
+ self.job_id = job_id
+
+ self.update_type = ''
+ self.operate_vnf_data = ''
+
+ def run(self):
+ try:
+ self.do_biz()
+ except NSLCMException as e:
+ logger.error(traceback.format_exc())
+ JobUtil.add_job_status(self.job_id, JOB_ERROR, e.message)
+ except:
+ logger.error(traceback.format_exc())
+ JobUtil.add_job_status(self.job_id, JOB_ERROR, 'ns update fail')
+
+ def do_biz(self):
+ self.update_job(1, desc='ns update start')
+ self.get_and_check_params()
+ self.update_ns_status(NS_INST_STATUS.UPDATING)
+ self.do_update()
+ self.update_ns_status(NS_INST_STATUS.ACTIVE)
+ self.update_job(100, desc='ns update success')
+
+ def get_and_check_params(self):
+ ns_info = NSInstModel.objects.filter(id=self.ns_instance_id)
+ if not ns_info:
+ raise NSLCMException(
+ 'NS [id=%s] does not exist' % self.ns_instance_id)
+
+ self.update_type = ignore_case_get(self.request_data, "updateType")
+ if not self.update_type:
+ raise NSLCMException(
+ 'UpdateType parameter does not exist or value incorrect.')
+
+ def do_update(self):
+ if self.update_type == "OPERATE_VNF":
+ self.operate_vnf_data = ignore_case_get(
+ self.request_data, "operateVnfData")
+ if not self.operate_vnf_data:
+ raise NSLCMException(
+ 'OperateVnfData does not exist or value is incorrect.')
+ for vnf_update_data in self.operate_vnf_data:
+ vnf_update_params = self.prepare_update_params(vnf_update_data)
+ status = self.do_vnf_update(vnf_update_params, 15)
+ if status is JOB_MODEL_STATUS.FINISHED:
+ logger.info(
+ 'nf[%s] update handle end' % vnf_update_params.get('vnfInstanceId'))
+ self.update_job(90,
+ desc='nf[%s] update handle end'
+ % vnf_update_params.get('vnfInstanceId'))
+ else:
+ raise NSLCMException('nf update failed')
+ else:
+ raise NSLCMException('Method update.')
+
+ def do_vnf_update(self, vnf_update_params, progress):
+ vnf_instance_id = vnf_update_params.get('vnfInstanceId')
+ nf_service = NFOperateService(vnf_instance_id, vnf_update_params)
+ nf_service.start()
+ self.update_job(progress, desc='nf[%s] update handle start' % vnf_instance_id)
+ status = self.wait_job_finish(nf_service.job_id)
+ return status
+
+ @staticmethod
+ def prepare_update_params(vnf_data):
+ vnf_instance_id = ignore_case_get(vnf_data, 'vnfInstanceId')
+ if not vnf_instance_id:
+ raise NSLCMException(
+ 'VnfInstanceId does not exist or value is incorrect.')
+
+ change_state_to = ignore_case_get(vnf_data, 'changeStateTo')
+ if not change_state_to:
+ raise NSLCMException(
+ 'ChangeStateTo does not exist or value is incorrect.')
+ Stop_Type = ''
+ graceful_stop_timeout = ''
+ operational_states = ignore_case_get(change_state_to, 'OperationalStates')
+ if operational_states == OPERATIONAL_STATES.STOPPED:
+ stop_type = ignore_case_get(vnf_data, 'stopType')
+ Stop_Type = ignore_case_get(stop_type, 'StopType')
+ if Stop_Type == STOP_TYPE.GRACEFUL:
+ graceful_stop_timeout = ignore_case_get(vnf_data, 'gracefulStopTimeout')
+
+ result = {
+ "vnfInstanceId": vnf_instance_id,
+ "changeStateTo": operational_states,
+ "stopType": Stop_Type,
+ "gracefulStopTimeout": graceful_stop_timeout
+ }
+ return result
+
+ @staticmethod
+ def wait_job_finish(sub_job_id, timeout=3600):
+ query_interval = 2
+ start_time = end_time = datetime.datetime.now()
+ while (end_time - start_time).seconds < timeout:
+ job_result = JobModel.objects.get(jobid=sub_job_id)
+ time.sleep(query_interval)
+ end_time = datetime.datetime.now()
+ if job_result.progress == 100:
+ return JOB_MODEL_STATUS.FINISHED
+ elif job_result.progress > 100:
+ return JOB_MODEL_STATUS.ERROR
+ else:
+ continue
+ return JOB_MODEL_STATUS.TIMEOUT
+
+ def update_job(self, progress, desc=''):
+ JobUtil.add_job_status(self.job_id, progress, desc)
+
+ def update_ns_status(self, status):
+ NSInstModel.objects.filter(id=self.ns_instance_id).update(status=status)
diff --git a/lcm/ns/serializers/update_serializers.py b/lcm/ns/serializers/update_serializers.py
index 80d506ed..fc3b6fb3 100644
--- a/lcm/ns/serializers/update_serializers.py
+++ b/lcm/ns/serializers/update_serializers.py
@@ -147,7 +147,7 @@ class OperationalStatesSerializer(serializers.Serializer):
class StopTypeSerializer(serializers.Serializer):
- StopType = serializers.CharField(help_text="Type of stop", choices=["FORCEFUL", "GRACEFUL"])
+ StopType = serializers.ChoiceField(help_text="Type of stop", choices=["FORCEFUL", "GRACEFUL"])
class OperateVnfDataSerializer(serializers.Serializer):
diff --git a/lcm/ns/urls.py b/lcm/ns/urls.py
index 4322d763..53c42498 100644
--- a/lcm/ns/urls.py
+++ b/lcm/ns/urls.py
@@ -18,6 +18,7 @@ from lcm.ns.views.create_ns_view import CreateNSView
from lcm.ns.views.inst_ns_view import NSInstView
from lcm.ns.views.term_ns_view import TerminateNSView
from lcm.ns.views.heal_ns_view import NSHealView
+from lcm.ns.views.update_ns_view import NSUpdateView
from lcm.ns.views.get_del_ns_view import NSDetailView
from lcm.ns.views.inst_ns_post_deal_view import NSInstPostDealView
from lcm.ns.views.scale_ns_views import NSManualScaleView
@@ -31,10 +32,10 @@ urlpatterns = [
url(r'^api/nslcm/v1/ns/(?P<ns_instance_id>[0-9a-zA-Z_-]+)$', NSDetailView.as_view()),
url(r'^api/nslcm/v1/ns/(?P<ns_instance_id>[0-9a-zA-Z_-]+)/postdeal$', NSInstPostDealView.as_view()),
url(r'^api/nslcm/v1/ns/(?P<ns_instance_id>[0-9a-zA-Z_-]+)/scale$', NSManualScaleView.as_view()),
- url(r'^api/nslcm/v1/ns/(?P<ns_instance_id>[0-9a-zA-Z_-]+)/heal$', NSHealView.as_view())
+ url(r'^api/nslcm/v1/ns/(?P<ns_instance_id>[0-9a-zA-Z_-]+)/heal$', NSHealView.as_view()),
# SOL005 URL API definition TODO
-
+ url(r'^api/nslcm/v1/ns/(?P<ns_instance_id>[0-9a-zA-Z_-]+)/update$', NSUpdateView.as_view())
]
urlpatterns = format_suffix_patterns(urlpatterns)
diff --git a/lcm/ns/views/update_ns_view.py b/lcm/ns/views/update_ns_view.py
new file mode 100644
index 00000000..45aa2735
--- /dev/null
+++ b/lcm/ns/views/update_ns_view.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2018, CMCC Technologies Co., Ltd.
+
+# 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 logging
+
+from rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+from drf_yasg.utils import swagger_auto_schema
+
+from lcm.ns.biz.ns_update import NSUpdateService
+from lcm.ns.serializers.ns_serializers import NsOperateJobSerializer
+from lcm.ns.serializers.update_serializers import UpdateNsReqSerializer
+from lcm.pub.exceptions import NSLCMException
+from lcm.pub.utils.jobutil import JobUtil, JOB_TYPE
+
+logger = logging.getLogger(__name__)
+
+
+class NSUpdateView(APIView):
+ @swagger_auto_schema(
+ request_body=UpdateNsReqSerializer(),
+ responses={
+ status.HTTP_202_ACCEPTED: NsOperateJobSerializer(),
+ status.HTTP_500_INTERNAL_SERVER_ERROR: "Inner error"
+ }
+ )
+ def post(self, request, ns_instance_id):
+ try:
+ logger.debug("Enter UpdateNSView::post %s, %s", request.data, ns_instance_id)
+ req_serializer = UpdateNsReqSerializer(data=request.data)
+ if not req_serializer.is_valid():
+ raise NSLCMException(req_serializer.errors)
+
+ job_id = JobUtil.create_job("VNF", JOB_TYPE.HEAL_VNF, ns_instance_id)
+ NSUpdateService(ns_instance_id, request.data, job_id).start()
+
+ resp_serializer = NsOperateJobSerializer(data={'jobId': job_id})
+ if not resp_serializer.is_valid():
+ raise NSLCMException(resp_serializer.errors)
+
+ logger.debug("Leave UpdateNSView::post ret=%s", resp_serializer.data)
+ return Response(data=resp_serializer.data, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ logger.error("Exception in UpdateNSView: %s", e.message)
+ return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)