[vFW_CNF_CDS] Update of python-sdk for vFW_CNF use case
[demo.git] / heat / vFW_CNF_CDS / automation / instantiate.py
1 # ============LICENSE_START=======================================================
2 # Copyright (C) 2021 Orange
3 # Copyright (C) 2022 Deutsche Telekom AG
4 # ================================================================================
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #      http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 #
17 # ============LICENSE_END=========================================================
18
19 import logging
20 import zipfile
21 from io import BytesIO
22 from time import sleep
23 import os
24
25 import oyaml as yaml
26
27 from config import Config
28 from onapsdk.aai.cloud_infrastructure import (
29     CloudRegion
30 )
31 from onapsdk.aai.business import (
32     Customer,
33     OwningEntity as AaiOwningEntity
34 )
35 from onapsdk.exceptions import ResourceNotFound, APIError
36 from onapsdk.msb.k8s import Definition
37
38 from onapsdk.so.instantiation import (
39     ServiceInstantiation,
40     InstantiationParameter, VnfParameters, VfmoduleParameters)
41 from onapsdk.sdc.service import Service
42 from onapsdk.so.so_element import OrchestrationRequest
43 from onapsdk.aai.service_design_and_creation import Service as AaiService
44
45 logger = logging.getLogger("")
46 logger.setLevel(logging.DEBUG)
47 fh = logging.StreamHandler()
48 fh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s')
49 fh.setFormatter(fh_formatter)
50 logger.addHandler(fh)
51
52
53 def get_customer(global_customer_id):
54     try:
55         customer = Customer.get_by_global_customer_id(global_customer_id)
56         logger.info(f"Customer {customer.subscriber_name} found")
57         return customer
58     except ResourceNotFound:
59         logger.error("Customer not exists. Check if region creation was successfully finished")
60         exit(1)
61
62
63 def get_service_model(service_type):
64     try:
65         service_model = next(model for model in Service.get_all() if model.name == service_type)
66         logger.info(
67             f"Found Service {service_model.name} in SDC, distribution status: {service_model.distribution_status}")
68         return service_model
69     except StopIteration:
70         logger.error(f"Service model {service_type} not found in SDC")
71         exit(1)
72
73
74 def check_service_customer_subscription(customer, service):
75     try:
76         customer.get_service_subscription_by_service_type(
77             service_type=service.name)
78     except ResourceNotFound:
79         return False
80
81     logger.info(f"Customer {customer.subscriber_name} subscribed for {service.name}")
82     return True
83
84
85 def subscribe_service_customer(customer, service):
86     if not check_service_customer_subscription(customer, service):
87         logger.info("******** Subscribe Service *******")
88         customer.subscribe_service(service.name)
89
90
91 def get_cloud_region(cloud_owner, cloud_region):
92     return CloudRegion(cloud_owner=cloud_owner, cloud_region_id=cloud_region,
93                        orchestration_disabled=True, in_maint=False)
94
95
96 def get_tenant(cloud_region, tenant_name):
97     try:
98         tenant = next(tenant for tenant in cloud_region.tenants if tenant.name == tenant_name)
99         return tenant
100     except StopIteration:
101         logger.error(f"Tenant {tenant_name} not found")
102         exit(1)
103
104
105 def add_owning_entity(owning_entity):
106     logger.info("******** Add Owning Entity to AAI *******")
107     try:
108         aai_owning_entity = AaiOwningEntity.get_by_owning_entity_name(owning_entity)
109     except ResourceNotFound:
110         logger.info("******** Owning Entity not existing: create *******")
111         aai_owning_entity = AaiOwningEntity.create(owning_entity)
112
113     return aai_owning_entity
114
115
116 def delete_old_profiles(service):
117     for vnf in service.vnfs:
118         for vf_module in vnf.vf_modules:
119             vf_module_label = next(vfm_prop.value for vfm_prop in vf_module.properties if
120                                    vfm_prop.name == "vf_module_label")
121             if vf_module_label == "base_template_dummy_ignore":
122                 continue
123             if "k8s-rb-profile-name" not in Config.VF_MODULE_PARAM_LIST[vf_module_label]["instantiation_parameters"]:
124                 continue
125             try:
126                 definition = Definition.get_definition_by_name_version(
127                     rb_name=vf_module.model_invariant_uuid,
128                     rb_version=vf_module.model_customization_id)
129             except APIError:
130                 definition = Definition.get_definition_by_name_version(
131                     rb_name=vf_module.model_invariant_uuid,
132                     rb_version=vf_module.model_version_id)
133             profile_name = Config.VF_MODULE_PARAM_LIST[vf_module_label]["instantiation_parameters"][
134                 "k8s-rb-profile-name"]
135             try:
136                 profile = definition.get_profile_by_name(profile_name)
137                 namespace = None
138                 if "k8s-rb-profile-namespace" in Config.VNF_PARAM_LIST:
139                     namespace = Config.VNF_PARAM_LIST["k8s-rb-profile-namespace"]
140                 if "k8s-rb-profile-namespace" in Config.VF_MODULE_PARAM_LIST[vf_module_label]["instantiation_parameters"]:
141                     namespace = Config.VF_MODULE_PARAM_LIST[vf_module_label]["instantiation_parameters"]["k8s-rb-profile-namespace"]
142                 if namespace != None and profile.namespace != namespace:
143                     profile.delete()
144                     logger.info("Profile: " + profile_name + " for " + vf_module.name + " deleted")
145                 else:
146                     logger.info("No need to delete Profile " + profile_name +
147                                 " for " + vf_module.name + ". Namespace is fine")
148             except ResourceNotFound:
149                 logger.info("Profile: " + profile_name + " for " + vf_module.name + " not found")
150
151
152 def read_sdnc_model_details(file):
153     mypath = os.path.dirname(os.path.realpath(__file__))
154     file_path = os.path.join(mypath, file)
155     with zipfile.ZipFile(file_path, 'r') as package:
156         cba_io = BytesIO(package.read("CBA.zip"))
157         with zipfile.ZipFile(cba_io) as cba:
158             with cba.open('TOSCA-Metadata/TOSCA.meta') as meta_file:
159                 tosca_meta = yaml.load(meta_file, Loader=yaml.FullLoader)
160                 sdnc_model_name = tosca_meta.get("Template-Name")
161                 sdnc_model_version = tosca_meta.get("Template-Version")
162     return sdnc_model_name, sdnc_model_version
163
164
165 def check_service_instance_exists(service_subscription, service_instance_name):
166     try:
167         service_instance = next((instance for instance in service_subscription.service_instances
168                                  if instance.instance_name == service_instance_name), None)
169         return service_instance
170     except ResourceNotFound:
171         return None
172
173
174 def get_vfmodule_parameters(vf_module, vf_module_instantiation_parameters, sdnc_model_name, sdnc_model_version):
175     base_parameters = [
176         InstantiationParameter(name="sdnc_model_name", value=sdnc_model_name),
177         InstantiationParameter(name="sdnc_model_version", value=sdnc_model_version),
178         InstantiationParameter(name="vf_module_label", value=vf_module)]
179
180     for instantiation_parameter_key, instantiation_parameter_value in vf_module_instantiation_parameters:
181         base_parameters.append(InstantiationParameter(name=instantiation_parameter_key,
182                                                       value=instantiation_parameter_value))
183
184     return VfmoduleParameters(vf_module, base_parameters)
185
186
187 def get_vnf_parameters(sdnc_model_name, sdnc_model_version, sdnc_artifact_name, vnf_param_list):
188     vnf_parameters = [
189         InstantiationParameter(name="sdnc_model_name", value=sdnc_model_name),
190         InstantiationParameter(name="sdnc_model_version", value=sdnc_model_version),
191         InstantiationParameter(name="sdnc_artifact_name", value=sdnc_artifact_name)]
192
193     for vnf_param_name, vnf_param_value in vnf_param_list.items():
194         vnf_parameters.append(
195             InstantiationParameter(name=vnf_param_name, value=vnf_param_value)
196         )
197
198     return vnf_parameters
199
200
201 def check_orchestration_status(instantiation):
202     status = None
203     while not (status == OrchestrationRequest.StatusEnum.COMPLETED
204                or status == OrchestrationRequest.StatusEnum.FAILED):
205         sleep(10)
206         status = instantiation.status
207         logger.info(f"Orchestration status is: {status.value}")
208
209     if status == OrchestrationRequest.StatusEnum.FAILED:
210         logger.error("Orchestration was failed!")
211         exit(1)
212     else:
213         logger.info("Orchestration was succeed")
214         return
215
216
217 def get_aai_service(service_type):
218     logging.info("******** Retrieve product family for service *******")
219     try:
220         aai_service = next(service for service in AaiService.get_all() if service.service_id == service_type)
221     except (ResourceNotFound, StopIteration):
222         logging.info("******** Service design and creation in AAI not existing: create *******")
223         AaiService.create(service_id=service_type, service_description=service_type)
224         aai_service = next(service for service in AaiService.get_all() if service.service_id == service_type)
225
226     return aai_service
227
228
229 def instantiate_service_macro(service_instance_name,
230                               sdnc_model_name, sdnc_model_version, sdnc_artifact_name, vf_name, vnf_param_list,
231                               vf_module_list, service, cloud_region, tenant, customer, owning_entity,
232                               vid_project, vid_line_of_business, vid_platform, service_subscription):
233     # TODO: support for multiple vnf should be added BEGINING of the loop
234     vnf_parameters = get_vnf_parameters(sdnc_model_name, sdnc_model_version, sdnc_artifact_name, vnf_param_list)
235
236     vfmodule_parameters = []
237     for vfmodule in vf_module_list:
238         vf_module_instantiation_parameters = vf_module_list[vfmodule]["instantiation_parameters"].items()
239         vfmodule_parameters.append(get_vfmodule_parameters(vfmodule, vf_module_instantiation_parameters,
240                                                            sdnc_model_name, sdnc_model_version))
241
242     vnf_instantiation_parameters = VnfParameters(name=vf_name,
243                                                  vnf_parameters=vnf_parameters,
244                                                  vfmodule_parameters=vfmodule_parameters)
245     # END of the loop
246     aai_service = get_aai_service(service.name)
247     service_instantiation = ServiceInstantiation.instantiate_macro(
248         sdc_service=service,
249         cloud_region=cloud_region,
250         tenant=tenant,
251         customer=customer,
252         owning_entity=owning_entity,
253         project=vid_project,
254         line_of_business=vid_line_of_business,
255         platform=vid_platform,
256         service_instance_name=service_instance_name,
257         vnf_parameters=[vnf_instantiation_parameters],
258         aai_service=aai_service,
259         service_subscription=service_subscription
260     )
261     check_orchestration_status(service_instantiation)
262
263
264 def get_base_vf_module(vf_modules):
265     base_vf_module = next(vf_module for vf_module in vf_modules if vf_module.properties["isBase"])
266     return base_vf_module
267
268
269 def is_base(vf_module):
270     if vf_module.properties["isBase"]:
271         return True
272     return False
273
274
275 def instantiate_vf_module(vf_module, vf_module_param_list, vnf_instance, sdnc_model_name, sdnc_model_version):
276     vf_module_label = vf_module.properties["vf_module_label"]
277     region_id = vf_module_param_list[vf_module_label]["cloud_configuration"]
278     cloud_region = get_cloud_region(
279         Config.CLOUD_REGIONS[region_id]["cloud_owner"],
280         region_id)
281     tenant = get_tenant(cloud_region, Config.CLOUD_REGIONS[region_id]["tenant"]["name"])
282
283     vfmodule_instantiation_parameters = vf_module_param_list[vf_module_label]["instantiation_parameters"].items()
284
285     base_parameters = [
286         InstantiationParameter(name="sdnc_model_name", value=sdnc_model_name),
287         InstantiationParameter(name="sdnc_model_version", value=sdnc_model_version),
288         InstantiationParameter(name="vf_module_label", value=vf_module_label)]
289
290     for instantiation_parameter_key, instantiation_parameter_value in vfmodule_instantiation_parameters:
291         base_parameters.append(InstantiationParameter(name=instantiation_parameter_key,
292                                                       value=instantiation_parameter_value))
293
294     vf_module_instantiation = vnf_instance.add_vf_module(
295         vf_module=vf_module,
296         cloud_region=cloud_region,
297         tenant=tenant,
298         vnf_parameters=base_parameters,
299         use_preload=False
300     )
301     check_orchestration_status(vf_module_instantiation)
302
303
304 def check_vf_module_list_correct(vf_modules, vf_module_param_list):
305     labels = set()
306     for vf_module in vf_modules:
307         labels.add(vf_module.properties["vf_module_label"])
308     if vf_module_param_list.keys() == labels:
309         return True
310     else:
311         return False
312
313
314 def instantiate_service_alacarte(service_subscription, service_instance_name,
315                                  sdnc_model_name, sdnc_model_version, sdnc_artifact_name, vnf_param_list,
316                                  vf_module_param_list, service, cloud_region, tenant, customer, owning_entity,
317                                  vid_project, vid_line_of_business, vid_platform):
318     # Tworzenie Serwisu
319     service_instantiation = ServiceInstantiation.instantiate_ala_carte(
320         sdc_service=service,
321         cloud_region=cloud_region,
322         tenant=tenant,
323         customer=customer,
324         owning_entity=owning_entity,
325         project=vid_project,
326         service_instance_name=service_instance_name
327     )
328     check_orchestration_status(service_instantiation)
329     # Koniec tworzenia Serwisu
330
331     service_instance = service_subscription.get_service_instance_by_name(service_instance_name)
332     # Dodawanie VNFs (VF) do Serwisu
333     for vnf in service.vnfs:
334         vnf_parameters = get_vnf_parameters(sdnc_model_name, sdnc_model_version, sdnc_artifact_name, vnf_param_list)
335         vnf_instantiation = service_instance.add_vnf(
336             # vnf_instance_name=vf_name, TODO: support for multiple vnf in config file
337             vnf=vnf,
338             line_of_business=vid_line_of_business,
339             platform=vid_platform,
340             vnf_parameters=vnf_parameters
341         )
342         check_orchestration_status(vnf_instantiation)
343
344         # Dodawanie VF Modulow
345         vnf_type = service.name + "/" + vnf.name
346         vnf_instance = next((vnf for vnf in service_instance.vnf_instances if vnf.vnf_type == vnf_type), None)
347
348         if check_vf_module_list_correct(vnf.vf_modules, vf_module_param_list):
349             for vf_module_label in vf_module_param_list:
350                 vf_module = next(
351                     vf_module for vf_module in vnf.vf_modules if
352                     vf_module.properties["vf_module_label"] == vf_module_label)
353                 instantiate_vf_module(vf_module, vf_module_param_list, vnf_instance, sdnc_model_name,
354                                       sdnc_model_version)
355         else:
356             logger.error("VF_MODULE_PARAM_LIST error. ")
357         # Koniec dodawania VF Modulow
358     # Koniec dodawania VNFs
359
360     # # Dodanie base
361     # base_vf_module = get_base_vf_module(vnf.vf_modules)
362     # instantiate_vf_module(base_vf_module, vf_module_param_list, vnf_instance, sdnc_model_name, sdnc_model_version)
363     # # Dodanie reszty
364     # for vf_module in vnf.vf_modules:
365     #     if not is_base(vf_module):
366     #         instantiate_vf_module(vf_module, vf_module_param_list, vnf_instance, sdnc_model_name,
367     #                               sdnc_model_version)
368
369
370 def main():
371     logger.info("*******************************")
372     logger.info("**** SERVICE INSTANTIATION ****")
373     logger.info("*******************************")
374
375     logger.info("******** GET Customer *******")
376     customer = get_customer(Config.GLOBAL_CUSTOMER_ID)
377
378     logger.info("******** GET Service Model from SDC *******")
379     service = get_service_model(Config.SERVICENAME)
380
381     logger.info("******** Subscribe Customer for Service *******")
382     subscribe_service_customer(customer, service)
383
384     logger.info("******** Get Tenant *******")
385     basic_cloud_region_name = next(iter(Config.CLOUD_REGIONS.keys()))
386     cloud_region = get_cloud_region(Config.CLOUD_REGIONS[basic_cloud_region_name]["cloud_owner"],
387                                     basic_cloud_region_name)
388     tenant = get_tenant(cloud_region,
389                         Config.CLOUD_REGIONS[basic_cloud_region_name]["tenant"]["name"])
390
391     ######
392     logger.info("******** Connect Service to Tenant *******")
393     service_subscription = None
394     for service_sub in customer.service_subscriptions:
395         logger.debug("Service subscription %s is found", service_sub.service_type)
396         if service_sub.service_type == Config.SERVICENAME:
397             logger.info("Service %s subscribed", Config.SERVICENAME)
398             service_subscription = service_sub
399             break
400
401     if not service_subscription:
402         logger.error("Service subscription %s is not found", Config.SERVICENAME)
403         exit(1)
404
405     service_subscription.link_to_cloud_region_and_tenant(cloud_region, tenant)
406     ####
407
408     logger.info("******** Business Objects (OE, P, Pl, LoB) *******")
409     project = Config.PROJECT
410     platform = Config.PLATFORM
411     line_of_business = Config.LINE_OF_BUSINESS
412     owning_entity = add_owning_entity(Config.OWNING_ENTITY)
413
414     logger.info("******** Delete old profiles ********")
415     delete_old_profiles(service)
416
417     logger.info("******** Read SDNC MODEL NAME and VERSION from CBA.zip ********")
418     sdnc_model_name, sdnc_model_version = read_sdnc_model_details(Config.VSPFILE)
419
420     logger.info("******** Instantiate Service *******")
421     service_instance = check_service_instance_exists(service_subscription, Config.SERVICE_INSTANCE_NAME)
422     if service_instance:
423         logger.info("******** Service Instance exists, do not instantiate *******")
424     else:
425         logger.info("******** Service Instance not existing: Instantiate *******")
426         if Config.MACRO_INSTANTIATION:
427             instantiate_service_macro(Config.SERVICE_INSTANCE_NAME, sdnc_model_name,
428                                       sdnc_model_version, Config.SDNC_ARTIFACT_NAME, Config.VFNAME,
429                                       Config.VNF_PARAM_LIST,
430                                       Config.VF_MODULE_PARAM_LIST,
431                                       service, cloud_region, tenant, customer, owning_entity, project,
432                                       line_of_business, platform, service_subscription)
433         else:
434             instantiate_service_alacarte(service_subscription, Config.SERVICE_INSTANCE_NAME, sdnc_model_name,
435                                          sdnc_model_version, Config.SDNC_ARTIFACT_NAME, Config.VNF_PARAM_LIST,
436                                          Config.VF_MODULE_PARAM_LIST,
437                                          service, cloud_region, tenant, customer, owning_entity, project,
438                                          line_of_business, platform)
439
440
441 if __name__ == "__main__":
442     main()