d4381de5a883964774c7efdf3e2e5131de61f067
[vfc/gvnfm/vnflcm.git] / lcm / lcm / nf / biz / operate_vnf.py
1 # Copyright (C) 2018 Verizon. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #       http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # import json
16 import logging
17 import traceback
18 from threading import Thread
19
20 from lcm.pub.database.models import NfInstModel, VmInstModel, VNFCInstModel
21 from lcm.pub.exceptions import NFLCMException
22 from lcm.pub.utils.jobutil import JobUtil
23 from lcm.pub.utils.timeutil import now_time
24 from lcm.pub.utils.notificationsutil import NotificationsUtil
25 from lcm.pub.utils.values import ignore_case_get
26 from lcm.pub.vimapi import adaptor
27 from lcm.nf.biz.grant_vnf import grant_resource
28 from lcm.nf.const import VNF_STATUS, RESOURCE_MAP, GRANT_TYPE, OPERATION_STATE_TYPE, LCM_NOTIFICATION_STATUS, CHANGE_TYPE, OPERATION_TYPE
29 import uuid
30
31 logger = logging.getLogger(__name__)
32
33
34 class OperateVnf(Thread):
35     def __init__(self, data, nf_inst_id, job_id):
36         super(OperateVnf, self).__init__()
37         self.data = data
38         self.nf_inst_id = nf_inst_id
39         self.job_id = job_id
40         self.grant_type = GRANT_TYPE.OPERATE
41         self.changeStateTo = ignore_case_get(self.data, "changeStateTo")
42         self.stopType = ignore_case_get(self.data, "stopType")
43         self.gracefulStopTimeout = ignore_case_get(self.data, "gracefulStopTimeout")
44         self.inst_resource = {'vm': []}
45
46     def run(self):
47         try:
48             self.lcm_notify(LCM_NOTIFICATION_STATUS.START, OPERATION_STATE_TYPE.STARTING)
49             self.apply_grant()
50             self.query_inst_resource()
51             self.lcm_notify(LCM_NOTIFICATION_STATUS.RESULT, OPERATION_STATE_TYPE.PROCESSING)
52             self.operate_resource()
53             JobUtil.add_job_status(self.job_id, 100, "Operate Vnf success.")
54             NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(status='INSTANTIATED', lastuptime=now_time())
55             self.lcm_notify(LCM_NOTIFICATION_STATUS.RESULT, OPERATION_STATE_TYPE.COMPLETED)
56         except NFLCMException as e:
57             self.lcm_notify(LCM_NOTIFICATION_STATUS.RESULT, OPERATION_STATE_TYPE.FAILED, str(e))
58             self.vnf_operate_failed_handle(e.message)
59         except Exception as e:
60             logger.error(e.message)
61             self.lcm_notify(LCM_NOTIFICATION_STATUS.RESULT, OPERATION_STATE_TYPE.FAILED, str(e))
62             self.vnf_operate_failed_handle(traceback.format_exc())
63
64     def apply_grant(self):
65         vdus = VmInstModel.objects.filter(instid=self.nf_inst_id)
66         apply_result = grant_resource(data=self.data, nf_inst_id=self.nf_inst_id, job_id=self.job_id,
67                                       grant_type=self.grant_type, vdus=vdus)
68         logger.info("Grant resource, response: %s" % apply_result)
69         JobUtil.add_job_status(self.job_id, 20, 'Nf Operate grant_resource finish')
70
71     def query_inst_resource(self):
72         logger.info('Query resource begin')
73         # Querying only vm resources now
74         resource_type = "Vm"
75         resource_table = globals().get(resource_type + 'InstModel')
76         resource_insts = resource_table.objects.filter(instid=self.nf_inst_id)
77         for resource_inst in resource_insts:
78             if not resource_inst.resourceid:
79                 continue
80             self.inst_resource[RESOURCE_MAP.get(resource_type)].append(self.get_resource(resource_inst))
81         logger.info('Query resource end, resource=%s' % self.inst_resource)
82
83     def get_resource(self, resource):
84         return {
85             "vim_id": resource.vimid,
86             "tenant_id": resource.tenant,
87             "id": resource.resourceid
88         }
89
90     def operate_resource(self):
91         logger.info('Operate resource begin')
92         adaptor.operate_vim_res(self.inst_resource, self.changeStateTo, self.stopType, self.gracefulStopTimeout, self.do_notify_op)
93         logger.info('Operate resource complete')
94
95     def lcm_notify(self, status, opState, err=None):
96         notification_content = self.prepareNotificationData(status, opState, err)
97         logger.info('Notify data = %s' % notification_content)
98         NotificationsUtil().send_notification(notification_content)
99         logger.info('Notify end')
100
101     def vnf_operate_failed_handle(self, error_msg):
102         logger.error('VNF Operation failed, detail message: %s' % error_msg)
103         NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(status=VNF_STATUS.FAILED, lastuptime=now_time())
104         JobUtil.add_job_status(self.job_id, 255, error_msg)
105
106     def do_notify_op(self, status, resid):
107         logger.error('VNF resource %s updated to: %s' % (resid, status))
108
109     def prepareNotificationData(self, status, opState, err=None):
110         affected_vnfcs = []
111         if status == LCM_NOTIFICATION_STATUS.RESULT and opState == OPERATION_STATE_TYPE.COMPLETED:
112             vnfcs = VNFCInstModel.objects.filter(instid=self.nf_inst_id)
113             for vnfc in vnfcs:
114                 vm_resource = {}
115                 if vnfc.vmid:
116                     vm = VmInstModel.objects.filter(vmid=vnfc.vmid)
117                     if vm:
118                         vm_resource = {
119                             'vimConnectionId': vm[0].vimid,
120                             'resourceId': vm[0].resourceid,
121                             'vimLevelResourceType': 'vm'
122                         }
123                 affected_vnfcs.append({
124                     'id': vnfc.vnfcinstanceid,
125                     'vduId': vnfc.vduid,
126                     'changeType': CHANGE_TYPE.MODIFIED,
127                     'computeResource': vm_resource
128                 })
129         notification_content = {
130             "id": str(uuid.uuid4()),
131             "notificationType": "VnfLcmOperationOccurrenceNotification",
132             "subscriptionId": "",
133             "timeStamp": now_time(),
134             "notificationStatus": status,
135             "operationState": opState,
136             "vnfInstanceId": self.nf_inst_id,
137             "operation": OPERATION_TYPE.OPERATE,
138             "isAutomaticInvocation": "false",
139             "vnfLcmOpOccId": self.job_id,
140             "affectedVnfcs": affected_vnfcs,
141             "affectedVirtualLinks": [],
142             "affectedVirtualStorages": [],
143             "changedInfo": {},
144             "changedExtConnectivity": [],
145             "_links": {"vnfInstance": {"href": ""},
146                        "subscription": {"href": ""},
147                        "vnfLcmOpOcc": {"href": ""}}
148         }
149         if opState in (OPERATION_STATE_TYPE.FAILED, OPERATION_STATE_TYPE.FAILED_TEMP):
150             notification_content["error"] = {"status": 500, "detail": err}
151         notification_content["_links"]["vnfInstance"]["href"] = "/vnf_instances/%s" % self.nf_inst_id
152         notification_content["_links"]["vnfLcmOpOcc"]["href"] = "/vnf_lc_ops/%s" % self.job_id
153         return notification_content