0d9dc5ef40edf4f41b06cc064138a31fd711ff69
[demo.git] / tutorials / ApacheCNF / 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 from time import sleep
20
21 from config import Config, VariablesDict
22 from onapsdk.aai.cloud_infrastructure import (
23     CloudRegion
24 )
25 from onapsdk.aai.business import (
26     Customer,
27     OwningEntity as AaiOwningEntity
28 )
29 from onapsdk.exceptions import ResourceNotFound, APIError
30 from onapsdk.msb.k8s import Definition
31 from onapsdk.so.instantiation import (
32     ServiceInstantiation,
33     InstantiationParameter, SoService, SoServiceVnf)
34 from onapsdk.sdc.service import Service
35 # from onapsdk.vid import LineOfBusiness, OwningEntity, Platform, Project
36 from onapsdk.so.so_element import OrchestrationRequest
37 from onapsdk.aai.service_design_and_creation import Service as AaiService
38
39 logger = logging.getLogger()
40 logger.setLevel(logging.DEBUG)
41
42
43 def get_customer(global_customer_id: str = "customer_cnf"):
44     logger.info("******** Customer *******")
45     try:
46         customer = Customer.get_by_global_customer_id(global_customer_id)
47         logger.info("Customer exists")
48     except ResourceNotFound:
49         logger.info("Customer does not exist")
50         customer = Customer.create(global_customer_id, global_customer_id, "INFRA")
51         logger.info("Customer created")
52     return customer
53
54
55 def get_service_model(model_name):
56     try:
57         service_model = next(model for model in Service.get_all() if model.name == model_name)
58         logger.info(
59             f"Found Service {service_model.name} in SDC, distribution status: {service_model.distribution_status}")
60         return service_model
61     except StopIteration:
62         logger.error(f"Service model {model_name} not found in SDC")
63         exit(1)
64
65
66 def check_service_customer_subscription(customer, service):
67     try:
68         customer.get_service_subscription_by_service_type(
69             service_type=service.name)
70     except ResourceNotFound:
71         return False
72
73     logger.info(f"Customer {customer.subscriber_name} subscribed for {service.name}")
74     return True
75
76
77 def subscribe_service_customer(customer, service):
78     if not check_service_customer_subscription(customer, service):
79         logger.info("******** Subscribe Service *******")
80         customer.subscribe_service(service.name)
81
82
83 def get_cloud_region(cloud_owner, cloud_region):
84     try:
85         cloud_region_object = next(cr for cr in CloudRegion.get_all() if
86                                    cr.cloud_region_id == cloud_region and cr.cloud_owner == cloud_owner)
87         return cloud_region_object
88     except (StopIteration, ResourceNotFound):
89         logging.error("Cloud region not found!!!")
90         exit(1)
91
92
93 def get_tenant(cloud_region, tenant_name):
94     try:
95         tenant = next(tenant for tenant in cloud_region.tenants if tenant.name == tenant_name)
96         return tenant
97     except (StopIteration, ResourceNotFound):
98         logger.error(f"Tenant {tenant_name} not found")
99         exit(1)
100
101
102 def add_owning_entity(owning_entity):
103     logger.info("******** Add Owning Entity to AAI *******")
104     try:
105         aai_owning_entity = AaiOwningEntity.get_by_owning_entity_name(owning_entity)
106     except ResourceNotFound:
107         logger.info("******** Owning Entity not existing: create *******")
108         aai_owning_entity = AaiOwningEntity.create(owning_entity)
109
110     return aai_owning_entity
111
112
113 def delete_old_profiles(service, service_config):
114     for vnf in service.vnfs:
115         vnf_config_details = next(
116             (_vnf for _vnf in service_config["vnfs"] if _vnf["model_name"] == vnf.model_name), None)
117         if not vnf_config_details:
118             continue
119         for vf_module in vnf.vf_modules:
120             vf_module_label = next(vfm_prop.value for vfm_prop in vf_module.properties if
121                                    vfm_prop.name == "vf_module_label")
122             if vf_module_label == "base_template_dummy_ignore":
123                 continue
124             vf_module_config_details = next((_vf_module for _vf_module in vnf_config_details["vf_modules"] if
125                                             _vf_module["model_name"] == vf_module_label), None)
126             if not vf_module_config_details:
127                 continue
128             if "k8s-rb-profile-name" not in vf_module_config_details["parameters"]:
129                 continue
130             try:
131                 definition = Definition.get_definition_by_name_version(
132                     rb_name=vf_module.model_invariant_uuid,
133                     rb_version=vf_module.model_customization_id)
134             except APIError:
135                 definition = Definition.get_definition_by_name_version(
136                     rb_name=vf_module.model_invariant_uuid,
137                     rb_version=vf_module.model_version_id)
138             profile_name = vf_module_config_details["parameters"]["k8s-rb-profile-name"]
139             try:
140                 profile = definition.get_profile_by_name(profile_name)
141                 namespace = None
142                 if "k8s-rb-profile-namespace" in vnf_config_details["parameters"]:
143                     namespace = vnf_config_details["parameters"]["k8s-rb-profile-namespace"]
144                 if "k8s-rb-profile-namespace" in vf_module_config_details["parameters"]:
145                     namespace = vf_module_config_details["parameters"]["k8s-rb-profile-namespace"]
146                 if namespace is not None and profile.namespace != namespace:
147                     profile.delete()
148                     logger.info("Profile: " + profile_name + " for " + vf_module.name + " deleted")
149                 else:
150                     logger.info("No need to delete Profile " + profile_name +
151                                 " for " + vf_module.name + ". Namespace is fine")
152             except ResourceNotFound:
153                 logger.info("Profile: " + profile_name + " for " + vf_module.name + " not found")
154
155
156 def check_service_instance_exists(service_subscription, service_instance_name):
157     try:
158         service_instance = next((instance for instance in service_subscription.service_instances
159                                  if instance.instance_name == service_instance_name), None)
160         return service_instance
161     except ResourceNotFound:
162         return None
163
164
165 def get_instantiation_parameters(properties, vnf_vf_module_config):
166     instantiation_parameters = []
167     for property_name, property_value in properties:
168         instantiation_parameters.append(InstantiationParameter(name=property_name, value=property_value))
169
170     for instantiation_parameter_key, instantiation_parameter_value in vnf_vf_module_config["parameters"]:
171         instantiation_parameters.append(InstantiationParameter(name=instantiation_parameter_key,
172                                                                value=instantiation_parameter_value))
173
174     return instantiation_parameters
175
176
177 def check_orchestration_status(instantiation):
178     status = None
179     while not (status == OrchestrationRequest.StatusEnum.COMPLETED
180                or status == OrchestrationRequest.StatusEnum.FAILED):
181         sleep(10)
182         status = instantiation.status
183         logger.info(f"Orchestration status is: {status.value}")
184
185     if status == OrchestrationRequest.StatusEnum.FAILED:
186         logger.error("Orchestration was failed!")
187         exit(1)
188     else:
189         logger.info("Orchestration was succeed")
190         return
191
192
193 def get_aai_service(service_type):
194     logging.info("******** Retrieve product family for service *******")
195     try:
196         aai_service = next(service for service in AaiService.get_all() if service.service_id == service_type)
197     except (ResourceNotFound, StopIteration):
198         logging.info("******** Service design and creation in AAI not existing: create *******")
199         AaiService.create(service_id=service_type, service_description=service_type)
200         aai_service = next(service for service in AaiService.get_all() if service.service_id == service_type)
201
202     return aai_service
203
204
205 def instantiate_service_macro(config, service, cloud_region, tenant, customer, owning_entity,
206                               vid_project, vid_line_of_business, vid_platform):
207     service_instance_name = config.service_instance["instance_name"]
208     so_input = config.so_input
209     for vnf in so_input["vnfs"]:
210         _vnf = next(nf for nf in service.vnfs if nf.model_name == vnf["model_name"])
211         sdnc_model_name = next(prop.value for prop in _vnf.properties if prop.name == "sdnc_model_name")
212         sdnc_model_version = next(prop.value for prop in _vnf.properties if prop.name == "sdnc_model_version")
213         sdnc_artifact_name = next(prop.value for prop in _vnf.properties if prop.name == "sdnc_artifact_name")
214
215         vnf["parameters"]["sdnc_model_name"] = sdnc_model_name
216         vnf["parameters"]["sdnc_model_version"] = sdnc_model_version
217         vnf["parameters"]["sdnc_artifact_name"] = sdnc_artifact_name
218         for vf_module in vnf["vf_modules"]:
219             vf_module_label = vf_module["model_name"]
220             vf_module["parameters"]["sdnc_model_name"] = sdnc_model_name
221             vf_module["parameters"]["sdnc_model_version"] = sdnc_model_version
222             vf_module["parameters"]["vf_module_label"] = vf_module_label
223
224     # TODO: PNF support in so_input -> first ONAPSDK
225
226     so_service = SoService.load(so_input)
227
228     aai_service = get_aai_service(service.name)
229     service_instantiation = ServiceInstantiation.instantiate_macro(
230         sdc_service=service,
231         cloud_region=cloud_region,
232         tenant=tenant,
233         customer=customer,
234         owning_entity=owning_entity,
235         project=vid_project,
236         line_of_business=vid_line_of_business,
237         platform=vid_platform,
238         service_instance_name=service_instance_name,
239         aai_service=aai_service,
240         so_service=so_service
241     )
242     check_orchestration_status(service_instantiation)
243
244
245 def instantiate_vnfs_macro(config, service_subscription, line_of_business, platform):
246
247     service_instance = check_service_instance_exists(service_subscription, config.service_instance["instance_name"])
248
249     so_input_vnfs_locations = config.create_so_input(other_cluster=True)
250
251     if not so_input_vnfs_locations["vnfs"]:
252         return
253
254     so_input_vnfs_by_priority = sorted(so_input_vnfs_locations["vnfs"],
255                                        key=lambda _vnf: _vnf.get("processing_priority", 100))
256
257     for vnf in so_input_vnfs_by_priority:
258
259         cloud_owner_name = next(
260             region["cloud_owner"] for region in config.cloud_regions if region["name"] == vnf["cloud_region"])
261         cloud_region = get_cloud_region(cloud_owner=cloud_owner_name, cloud_region=vnf["cloud_region"])
262
263         vnf_model = next(nf for nf in service_instance.sdc_service.vnfs
264                          if nf.model_name == vnf["model_name"])
265
266         sdnc_model_name = next(prop.value for prop in vnf_model.properties if prop.name == "sdnc_model_name")
267         sdnc_model_version = next(prop.value for prop in vnf_model.properties if prop.name == "sdnc_model_version")
268         sdnc_artifact_name = next(prop.value for prop in vnf_model.properties if prop.name == "sdnc_artifact_name")
269
270         vnf["parameters"]["sdnc_model_name"] = sdnc_model_name
271         vnf["parameters"]["sdnc_model_version"] = sdnc_model_version
272         vnf["parameters"]["sdnc_artifact_name"] = sdnc_artifact_name
273         for vf_module in vnf["vf_modules"]:
274             vf_module_label = vf_module["model_name"]
275             vf_module["parameters"]["sdnc_model_name"] = sdnc_model_name
276             vf_module["parameters"]["sdnc_model_version"] = sdnc_model_version
277             vf_module["parameters"]["vf_module_label"] = vf_module_label
278
279         so_vnf = SoServiceVnf.load(vnf)
280
281         vnf_instantiation = service_instance.add_vnf(
282             vnf=vnf_model,
283             line_of_business=line_of_business,
284             platform=platform,
285             cloud_region=cloud_region,
286             tenant=get_tenant(cloud_region=cloud_region, tenant_name=vnf["tenant_name"]),
287             vnf_instance_name=vnf["instance_name"],
288             so_vnf=so_vnf,
289             a_la_carte=False
290         )
291
292         check_orchestration_status(vnf_instantiation)
293
294
295 def instantiate_vf_module(vf_module, vf_module_param_list, vnf_instance, sdnc_model_name, sdnc_model_version):
296     vf_module_label = next(vfm_prop.value for vfm_prop in vf_module.properties if vfm_prop.name == "vf_module_label")
297     region_id = vf_module_param_list[vf_module_label]["cloud_configuration"]
298     cloud_region = get_cloud_region(
299         Config.CLOUD_REGIONS[region_id]["cloud_owner"],
300         region_id)
301     tenant = get_tenant(cloud_region, Config.CLOUD_REGIONS[region_id]["tenant"]["name"])
302
303     vfmodule_instantiation_parameters = vf_module_param_list[vf_module_label]["instantiation_parameters"].items()
304
305     base_parameters = [
306         InstantiationParameter(name="sdnc_model_name", value=sdnc_model_name),
307         InstantiationParameter(name="sdnc_model_version", value=sdnc_model_version),
308         InstantiationParameter(name="vf_module_label", value=vf_module_label)]
309
310     for instantiation_parameter_key, instantiation_parameter_value in vfmodule_instantiation_parameters:
311         base_parameters.append(InstantiationParameter(name=instantiation_parameter_key,
312                                                       value=instantiation_parameter_value))
313
314     vf_module_instantiation = vnf_instance.add_vf_module(
315         vf_module=vf_module,
316         cloud_region=cloud_region,
317         tenant=tenant,
318         vnf_parameters=base_parameters,
319         use_preload=False
320     )
321     check_orchestration_status(vf_module_instantiation)
322
323
324 def check_vf_module_list_correct(vf_modules, vf_modules_config_list):
325     model_labels = set()
326     config_labels = set()
327     for vf_module in vf_modules:
328         _model_label = next(_prop.value for _prop in vf_module.properties if _prop.name == "vf_module_label")
329         model_labels.add(_model_label)
330     for vf_module in vf_modules_config_list:
331         config_labels.add(vf_module.model_name)
332     if model_labels == config_labels:
333         return True
334     else:
335         return False
336
337
338 def get_properties(vnf):
339     properties = dict()
340
341     properties["sdnc_model_name"] = next(prop.value for prop in vnf.properties if prop.name == "sdnc_model_name")
342     properties["sdnc_model_version"] = next(prop.value for prop in vnf.properties if prop.name == "sdnc_model_version")
343     properties["sdnc_artifact_name"] = next(prop.value for prop in vnf.properties if prop.name == "sdnc_artifact_name")
344
345     return properties
346
347
348 def instantiate_service_alacarte(config, service_subscription, service_model, cloud_region, tenant, customer,
349                                  owning_entity,
350                                  vid_project, vid_line_of_business, vid_platform):
351     raise NotImplementedError("Not supported since 2022")
352
353     service_instance_name = config.service_instance["instance_name"]
354     # Service creation
355     service_instantiation = ServiceInstantiation.instantiate_ala_carte(
356         sdc_service=service_model,
357         cloud_region=cloud_region,
358         tenant=tenant,
359         customer=customer,
360         owning_entity=owning_entity,
361         project=vid_project,
362         service_instance_name=service_instance_name
363     )
364     check_orchestration_status(service_instantiation)
365     # End of service creation
366
367     service_instance = service_subscription.get_service_instance_by_name(service_instance_name)
368     # Add VNFs
369     for vnf in service_model.vnfs:
370         # TODO: priority
371         properties = get_properties(vnf)
372         vnf_config = next(_vnf for _vnf in config.service_instance["vnfs"]
373                           if config.service_instance["vnfs"]["model_name"] == vnf.name)
374         vnf_parameters = get_instantiation_parameters(properties, vnf_config)
375         #  TODO: instance name
376         vnf_instantiation = service_instance.add_vnf(
377             vnf=vnf,
378             line_of_business=vid_line_of_business,
379             platform=vid_platform,
380             vnf_parameters=vnf_parameters
381         )
382         check_orchestration_status(vnf_instantiation)
383
384         # Add vf_modules
385         vnf_type = service_model.name + "/" + vnf.name
386         vnf_instance = next((vnf for vnf in service_instance.vnf_instances if vnf.vnf_type == vnf_type), None)
387
388         if check_vf_module_list_correct(vnf.vf_modules, vnf_config["vf_modules"]):
389             for vf_module in vnf.vf_modules:
390                 vf_module_config = next(_vf for _vf in vnf_config["vf_modules"]
391                                         if _vf["model_name"] == vf_module.properties["vf_module_label"])
392                 vf_module_parameters = get_instantiation_parameters(properties, vf_module_config)
393                 vf_module_instantiation = vnf_instance.add_vf_module(
394                     vf_module=vf_module,
395                     cloud_region=cloud_region,
396                     tenant=tenant,
397                     vnf_parameters=vf_module_parameters,
398                     use_preload=False
399                 )
400                 check_orchestration_status(vf_module_instantiation)
401         else:
402             logger.error("VF_MODULE_PARAM_LIST error. ")
403         # End of vf_modules
404     # End of VNFs
405
406
407 def main():
408     logger.info("*******************************")
409     logger.info("**** SERVICE INSTANTIATION ****")
410     logger.info("*******************************")
411
412     config = Config(env_dict=VariablesDict.env_variable)
413
414     logger.info("******** GET Customer *******")
415     customer = get_customer(config.service_instance["customer_id"])
416
417     logger.info("******** GET Service Model from SDC *******")
418     service = get_service_model(config.service_instance["model_name"])
419
420     logger.info("******** Subscribe Customer for Service *******")
421     subscribe_service_customer(customer, service)
422
423     logger.info("******** Get Tenant *******")
424     region_details = next(
425         region for region in config.cloud_regions if region["name"] == config.service_instance["cloud_region"])
426     cloud_region = get_cloud_region(region_details["cloud_owner"], region_details["name"])
427     tenant = get_tenant(cloud_region,
428                         config.service_instance["tenant_name"])
429
430     ######
431     logger.info("******** Connect Service to Tenant *******")
432     service_subscription = None
433     try:
434         service_subscription = customer.get_service_subscription_by_service_type(
435             service_type=config.service_instance["model_name"])
436     except ResourceNotFound:
437         logger.error("Service subscription %s is not found", config.service_instance["model_name"])
438         exit(1)
439
440     service_subscription.link_to_cloud_region_and_tenant(cloud_region, tenant)
441     ####
442
443     logger.info("******** Business Objects (OE, P, Pl, LoB) *******")
444     project = "Project-Demonstration"
445     platform = "Platform-test"
446     line_of_business = "Orange-LOB"
447     owning_entity = add_owning_entity("Orange")
448
449     logger.info("******** Delete old profiles ********")
450     delete_old_profiles(service, config.service_instance)
451
452     logger.info("******** Instantiate Service *******")
453     service_instance = check_service_instance_exists(service_subscription, config.service_instance["instance_name"])
454     if service_instance:
455         logger.info("******** Service Instance exists, do not instantiate *******")
456     else:
457         logger.info("******** Service Instance not existing: Instantiate *******")
458         if config.service_model["macro_orchestration"]:
459             instantiate_service_macro(config, service, cloud_region, tenant, customer, owning_entity,
460                                       project, line_of_business, platform)
461             instantiate_vnfs_macro(config=config, service_subscription=service_subscription,
462                                    line_of_business=line_of_business, platform=platform)
463         else:
464             instantiate_service_alacarte(config, service_subscription, service, cloud_region, tenant, customer,
465                                          owning_entity, project, line_of_business, platform)
466
467
468 if __name__ == "__main__":
469     sh = logging.StreamHandler()
470     sh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s')
471     sh.setFormatter(sh_formatter)
472     logger.addHandler(sh)
473
474     main()