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