1 # Copyright 2017 ZTE Corporation.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 from threading import Thread
20 from lcm.pub.utils.syscomm import fun_name
21 from lcm.pub.utils.values import ignore_case_get
22 from lcm.pub.utils import restcall
23 from lcm.pub.exceptions import NSLCMException
25 logger = logging.getLogger(__name__)
27 RESULT_OK, RESULT_NG = "0", "1"
36 "nsInstanceId": id of ns instance,
37 "object_context": json format of nsd,
38 "object_additionalParamForNs": json format of additional parameters for ns,
39 "object_additionalParamForVnf": json format of additional parameters for vnf,
40 "vlCount": int type of VL count,
41 "vnfCount: int type of VNF count,
42 "sfcCount": int type of SFC count,
43 "sdnControllerId": uuid of SDN controller
48 def run_ns_instantiate(input_data):
49 logger.debug("Enter %s, input_data is %s", fun_name(), input_data)
50 ns_instantiate_ok = False
51 job_id = ignore_case_get(input_data, "jobId")
52 ns_inst_id = ignore_case_get(input_data, "nsInstanceId")
53 nsd_json = ignore_case_get(input_data, "object_context")
54 ns_param_json = ignore_case_get(input_data, "object_additionalParamForNs")
55 vnf_param_json = ignore_case_get(input_data, "object_additionalParamForVnf")
56 pnf_param_json = ignore_case_get(input_data, "object_additionalParamForPnf")
57 vl_count = int(ignore_case_get(input_data, "vlCount", 0))
58 vnf_count = int(ignore_case_get(input_data, "vnfCount", 0))
59 sfc_count = int(ignore_case_get(input_data, "sfcCount", 0))
60 sdnc_id = ignore_case_get(input_data, "sdnControllerId")
61 g_jobs_status[job_id] = [1 for i in range(vnf_count)]
63 update_job(job_id, 10, "true", "Start to create VL")
64 for i in range(vl_count):
65 create_vl(ns_inst_id, i + 1, nsd_json, ns_param_json)
67 update_job(job_id, 30, "true", "Start to create VNF")
68 jobs = [create_vnf(ns_inst_id, i + 1, vnf_param_json) for i in range(vnf_count)]
69 wait_until_jobs_done(job_id, jobs)
71 [confirm_vnf_status(inst_id) for inst_id, _, _ in jobs]
73 update_job(job_id, 50, "true", "Start to create PNF")
74 create_pnf(pnf_param_json)
76 update_job(job_id, 70, "true", "Start to create SFC")
77 g_jobs_status[job_id] = [1 for i in range(sfc_count)]
78 jobs = [create_sfc(ns_inst_id, i + 1, nsd_json, sdnc_id) for i in range(sfc_count)]
79 wait_until_jobs_done(job_id, jobs)
81 [confirm_sfc_status(inst_id) for inst_id, _, _ in jobs]
83 update_job(job_id, 90, "true", "Start to post deal")
84 post_deal(ns_inst_id, "true")
86 update_job(job_id, 100, "true", "Create NS successfully.")
87 ns_instantiate_ok = True
88 except NSLCMException as e:
89 logger.error("Failded to Create NS: %s", e.message)
90 update_job(job_id, JOB_ERROR, "255", "Failded to Create NS.")
91 post_deal(ns_inst_id, "false")
93 logger.error(traceback.format_exc())
94 update_job(job_id, JOB_ERROR, "255", "Failded to Create NS.")
95 post_deal(ns_inst_id, "false")
97 g_jobs_status.pop(job_id)
98 return ns_instantiate_ok
101 def create_vl(ns_inst_id, vl_index, nsd, ns_param):
102 uri = "api/nslcm/v1/ns/vls"
103 data = json.JSONEncoder().encode({
104 "nsInstanceId": ns_inst_id,
107 "additionalParamForNs": ns_param
110 ret = restcall.req_by_msb(uri, "POST", data)
112 logger.error("Failed to call create_vl(%s): %s", vl_index, ret[1])
113 raise NSLCMException("Failed to call create_vl(index is %s)" % vl_index)
114 ret[1] = json.JSONDecoder().decode(ret[1])
116 result = str(ret[1]["result"])
117 detail = ret[1]["detail"]
118 vl_id = ret[1]["vlId"]
119 if result != RESULT_OK:
120 logger.error("Failed to create VL(%s): %s", vl_id, detail)
121 raise NSLCMException("Failed to create VL(%s)" % vl_id)
123 logger.debug("Create VL(%s) successfully.", vl_id)
126 def create_vnf(ns_inst_id, vnf_index, nf_param):
127 uri = "api/nslcm/v1/ns/vnfs"
128 data = json.JSONEncoder().encode({
129 "nsInstanceId": ns_inst_id,
130 "vnfIndex": vnf_index,
131 "additionalParamForVnf": json.JSONDecoder().decode(nf_param)
134 ret = restcall.req_by_msb(uri, "POST", data)
136 logger.error("Failed to call create_vnf(%s): %s", vnf_index, ret[1])
137 raise NSLCMException("Failed to call create_vnf(index is %s)" % vnf_index)
138 ret[1] = json.JSONDecoder().decode(ret[1])
140 vnf_inst_id = ret[1]["vnfInstId"]
141 job_id = ret[1]["jobId"]
142 logger.debug("Create VNF(%s) started.", vnf_inst_id)
143 return vnf_inst_id, job_id, vnf_index - 1
146 def create_sfc(ns_inst_id, fp_index, nsd_json, sdnc_id):
147 uri = "api/nslcm/v1/ns/sfcs"
148 data = json.JSONEncoder().encode({
149 "nsInstanceId": ns_inst_id,
152 "sdnControllerId": sdnc_id
155 ret = restcall.req_by_msb(uri, "POST", data)
157 logger.error("Failed to call create_sfc(%s): %s", fp_index, ret[1])
158 raise NSLCMException("Failed to call create_sfc(index is %s)" % fp_index)
159 ret[1] = json.JSONDecoder().decode(ret[1])
161 sfc_inst_id = ret[1]["sfcInstId"]
162 job_id = ret[1]["jobId"]
163 logger.debug("Create SFC(%s) started.", sfc_inst_id)
164 return sfc_inst_id, job_id, fp_index - 1
167 def post_deal(ns_inst_id, status):
168 uri = "api/nslcm/v1/ns/{nsInstanceId}/postdeal".format(nsInstanceId=ns_inst_id)
169 data = json.JSONEncoder().encode({
173 ret = restcall.req_by_msb(uri, "POST", data)
175 logger.error("Failed to call post_deal(%s): %s", ns_inst_id, ret[1])
176 logger.debug("Call post_deal(%s, %s) successfully.", ns_inst_id, status)
179 def update_job(job_id, progress, errcode, desc):
180 uri = "api/nslcm/v1/jobs/{jobId}".format(jobId=job_id)
181 data = json.JSONEncoder().encode({
182 "progress": progress,
186 restcall.req_by_msb(uri, "POST", data)
189 class JobWaitThread(Thread):
194 def __init__(self, inst_id, job_id, ns_job_id, index):
195 Thread.__init__(self)
196 self.inst_id = inst_id
198 self.ns_job_id = ns_job_id
200 self.retry_count = 600
201 self.interval_second = 3
205 response_id, new_response_id = 0, 0
206 job_end_normal, job_timeout = False, True
207 while count < self.retry_count:
209 time.sleep(self.interval_second)
210 uri = "/api/nslcm/v1/jobs/%s?responseId=%s" % (self.job_id, response_id)
211 ret = restcall.req_by_msb(uri, "GET")
213 logger.error("Failed to query job: %s:%s", ret[2], ret[1])
215 job_result = json.JSONDecoder().decode(ret[1])
216 if "responseDescriptor" not in job_result:
217 logger.error("Job(%s) does not exist.", self.job_id)
219 progress = job_result["responseDescriptor"]["progress"]
220 new_response_id = job_result["responseDescriptor"]["responseId"]
221 job_desc = job_result["responseDescriptor"]["statusDescription"]
222 if new_response_id != response_id:
223 logger.debug("%s:%s:%s", progress, new_response_id, job_desc)
224 response_id = new_response_id
226 if progress == JOB_ERROR:
228 logger.error("Job(%s) failed: %s", self.job_id, job_desc)
230 elif progress == 100:
231 job_end_normal, job_timeout = True, False
232 logger.info("Job(%s) ended normally", self.job_id)
235 logger.error("Job(%s) timeout", self.job_id)
236 if self.ns_job_id in g_jobs_status:
238 g_jobs_status[self.ns_job_id][self.index] = 0
241 def wait_until_jobs_done(g_job_id, jobs):
243 for inst_id, job_id, index in jobs:
244 job_threads.append(JobWaitThread(inst_id, job_id, g_job_id, index))
245 for t in job_threads:
247 for t in job_threads:
249 if g_job_id in g_jobs_status:
250 if sum(g_jobs_status[g_job_id]) > 0:
251 logger.error("g_jobs_status[%s]: %s", g_job_id, g_jobs_status[g_job_id])
252 raise NSLCMException("Some jobs failed!")
255 def confirm_vnf_status(vnf_inst_id):
256 uri = "api/nslcm/v1/ns/vnfs/{vnfInstId}".format(vnfInstId=vnf_inst_id)
257 ret = restcall.req_by_msb(uri, "GET")
259 raise NSLCMException("Failed to call get_vnf(%s)" % vnf_inst_id)
260 ret[1] = json.JSONDecoder().decode(ret[1])
262 vnf_status = ret[1]["vnfStatus"]
263 if vnf_status != "active":
264 raise NSLCMException("Status of VNF(%s) is not active" % vnf_inst_id)
267 def confirm_sfc_status(sfc_inst_id):
268 uri = "api/nslcm/v1/ns/sfcs/{sfcInstId}".format(sfcInstId=sfc_inst_id)
269 ret = restcall.req_by_msb(uri, "GET")
271 raise NSLCMException("Failed to call get_sfc(%s)" % sfc_inst_id)
272 ret[1] = json.JSONDecoder().decode(ret[1])
274 sfc_status = ret[1]["sfcStatus"]
275 if sfc_status != "active":
276 raise NSLCMException("Status of SFC(%s) is not active" % sfc_inst_id)
279 def create_pnf(pnf_param_json):
280 if pnf_param_json and len(pnf_param_json) > 0:
281 pnfs = json.JSONDecoder().decode(pnf_param_json)
283 uri = "/api/nslcm/v1/pnfs"
285 content = json.JSONEncoder().encode(pnf["input"]["content"])
286 ret = restcall.req_by_msb(uri, method, content)
288 logger.error("Failed to call create_pnf(%s) result %s", content, ret)
289 raise NSLCMException("Failed to call create_pnf(%s)" % content)