4a7fb3039d90180b29e5d4d8a6732ca7644238cf
[vfc/nfvo/lcm.git] / lcm / packages / ns_package.py
1 # Copyright 2016 ZTE Corporation.
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
18 import traceback
19 import sys
20
21 from lcm.pub.database.models import NSDModel, NSInstModel, NfPackageModel
22 from lcm.pub.utils.values import ignore_case_get
23 from lcm.pub.msapi.catalog import STATUS_ONBOARDED, P_STATUS_ENABLED
24 from lcm.pub.msapi.catalog import query_csar_from_catalog, set_csar_state
25 from lcm.pub.msapi.catalog import query_rawdata_from_catalog, delete_csar_from_catalog
26 from lcm.pub.exceptions import NSLCMException
27 from lcm.pub.utils import toscautil
28
29 logger = logging.getLogger(__name__)
30
31 STATUS_SUCCESS, STATUS_FAILED = "success", "failed"
32
33
34 def fmt_ns_pkg_rsp(status, desc, error_code="500"):
35     return [0, {"status": status, "statusDescription": desc, "errorCode": error_code}]
36
37
38 def ns_common_call(fun, csar_id, operation=""):
39     ret = None
40     try:
41         if operation == "":
42             ret = fun(csar_id)
43         else:
44             ret = fun(csar_id, operation)
45
46         if ret[0] != 0:
47             return fmt_ns_pkg_rsp(STATUS_FAILED, ret[1])
48     except NSLCMException as e:
49         return fmt_ns_pkg_rsp(STATUS_FAILED, e.message)
50     except:
51         logger.error(traceback.format_exc())
52         return fmt_ns_pkg_rsp(STATUS_FAILED, str(sys.exc_info()))
53     return fmt_ns_pkg_rsp(STATUS_SUCCESS, ret[1], "")
54
55 def ns_on_boarding(csar_id):
56     return ns_common_call(NsPackage().on_boarding, csar_id)
57
58
59 def ns_delete_csar(csar_id):
60     return ns_common_call(NsPackage().delete_csar, csar_id)
61
62
63 def ns_delete_pending_csar(csar_id):
64     return ns_common_call(NsPackage().delete_pending_csar, csar_id)
65
66
67 def ns_set_state_csar(csar_id, operation):
68     return ns_common_call(NsPackage().set_state_csar, csar_id, operation)
69
70
71 def ns_get_csar(csar_id):
72     ret = None
73     try:
74         ret = NsPackage().get_csar(csar_id)
75     except NSLCMException as e:
76         return [1, e.message]
77     except:
78         logger.error(traceback.format_exc())
79         return [1, str(sys.exc_info())]
80     return ret
81
82
83 ###############################################################################################################
84
85
86 class NsPackage(object):
87     """
88     Actions for ns package.
89     """
90
91     def __init__(self):
92         pass
93
94     def on_boarding(self, csar_id):
95         csar = query_csar_from_catalog(csar_id)
96         if ignore_case_get(csar, "onBoardState") == STATUS_ONBOARDED:
97             raise NSLCMException("CSAR(%s) already onBoarded." % csar_id)
98
99         raw_data = query_rawdata_from_catalog(csar_id)
100         nsd = toscautil.convert_nsd_model(raw_data["rawData"]) # convert to inner json
101         nsd = json.JSONDecoder().decode(nsd)
102         nsd_id = nsd["metadata"]["id"]
103         if NSDModel.objects.filter(nsd_id=nsd_id):
104             raise NSLCMException("NSD(%s) already exists." % nsd_id)
105
106         for vnf in nsd["vnfs"]:
107             vnfd_id = vnf["properties"]["id"]
108             pkg = NfPackageModel.objects.filter(vnfdid=vnfd_id)
109             if not pkg:
110                 raise NSLCMException("VNF package(%s) is not onBoarded." % vnfd_id)
111             pkg_id = pkg[0].nfpackageid
112             if query_csar_from_catalog(pkg_id, "onBoardState") != STATUS_ONBOARDED:
113                 raise NSLCMException("VNF package(%s) is not onBoarded on catalog." % pkg_id)
114
115         NSDModel(
116             id=csar_id,
117             nsd_id=nsd_id,
118             name=nsd["metadata"].get("name", nsd_id),
119             vendor=nsd["metadata"].get("vendor", "undefined"),
120             description=nsd["metadata"].get("description", ""),
121             version=nsd["metadata"].get("version", "undefined"),
122             nsd_model=json.JSONEncoder().encode(nsd)).save()
123
124         set_csar_state(csar_id, "onBoardState", STATUS_ONBOARDED)
125         set_csar_state(csar_id, "operationalState", P_STATUS_ENABLED)
126
127         return [0, "CSAR(%s) onBoarded successfully." % csar_id]
128
129     def delete_csar(self, csar_id):
130         if not NSDModel.objects.filter(id=csar_id):
131             return delete_csar_from_catalog(csar_id)
132
133         if NSInstModel.objects.filter(nspackage_id=csar_id):
134             return set_csar_state(csar_id, "deletionPending", True)
135
136         ret = delete_csar_from_catalog(csar_id)
137         if ret[0] == 0:
138             NSDModel.objects.filter(id=csar_id).delete()
139         return ret
140
141     def delete_pending_csar(self, csar_id):
142         if not NSDModel.objects.filter(id=csar_id):
143             return [0, "Delete pending CSAR(%s) successfully." % csar_id]
144
145         pending = query_csar_from_catalog(csar_id, "deletionPending")
146
147         if pending.lower() == "false":
148             return [1, "CSAR(%s) need not to be deleted." % csar_id]
149
150         if NSInstModel.objects.filter(nspackage_id=csar_id):
151             return [1, "CSAR(%s) is in using, cannot be deleted." % csar_id]
152
153         ret = delete_csar_from_catalog(csar_id)
154         if ret[0] == 0:
155             NSDModel.objects.filter(id=csar_id).delete()
156         return ret
157
158     def get_csar(self, csar_id):
159         package_info = {}
160
161         csar_in_catalog = query_csar_from_catalog(csar_id)
162         props_of_catalog = [
163             "name", "provider", "version", "operationalState", "usageState",
164             "onBoardState", "processState", "deletionPending", "downloadUri",
165             "createTime", "modifyTime", "format", "size"]
166         for prop in props_of_catalog:
167             package_info[prop] = ignore_case_get(csar_in_catalog, prop)
168
169         csars = NSDModel.objects.filter(id=csar_id)
170         if csars:
171             package_info["nsdId"] = csars[0].nsd_id
172             package_info["nsdProvider"] = csars[0].vendor
173             package_info["nsdVersion"] = csars[0].version
174
175         nss = NSInstModel.objects.filter(nspackage_id=csar_id)
176         ns_instance_info = [{"nsInstanceId": ns.id, "nsInstanceName": ns.name} for ns in nss]
177
178         return [0, {"csarId": csar_id, "packageInfo": package_info, "nsInstanceInfo": ns_instance_info}]
179
180
181     def set_state_csar(self, csar_id, operation):
182         if not NSDModel.objects.filter(id=csar_id):
183             raise NSLCMException("CSAR(%s) does not exist." % csar_id)
184
185         csar = query_csar_from_catalog(csar_id)
186         if ignore_case_get(csar, "operationalState") == operation.capitalize():
187             raise NSLCMException("CSAR(%s) already %s." % (csar_id, operation))
188         return set_csar_state(csar_id, 'operationState', operation.capitalize())