3 # Copyright 2016 RIFT.IO Inc
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
25 gi
.require_version('RwDts', '1.0')
26 gi
.require_version('RwVnfrYang', '1.0')
27 from gi
.repository
import (
32 import rift
.openmano
.rift2openmano
as rift2openmano
33 import rift
.openmano
.openmano_client
as openmano_client
34 from . import rwnsmplugin
40 if sys
.version_info
< (3, 4, 4):
41 asyncio
.ensure_future
= asyncio
.async
44 DUMP_OPENMANO_DIR
= os
.path
.join(
45 os
.environ
["RIFT_ARTIFACTS"],
46 "openmano_descriptors"
50 def dump_openmano_descriptor(name
, descriptor_str
):
51 filename
= "{}_{}.yaml".format(
52 time
.strftime("%Y%m%d-%H%M%S"),
56 filepath
= os
.path
.join(
62 if not os
.path
.exists(DUMP_OPENMANO_DIR
):
63 os
.makedirs(DUMP_OPENMANO_DIR
)
65 with
open(filepath
, 'w') as hdl
:
66 hdl
.write(descriptor_str
)
69 print("Failed to dump openmano descriptor: %s" % str(e
))
73 class VNFExistError(Exception):
76 class VnfrConsoleOperdataDtsHandler(object):
77 """ registers 'D,/vnfr:vnfr-console/vnfr:vnfr[id]/vdur[id]' and handles CRUD from DTS"""
79 def vnfr_vdu_console_xpath(self
):
80 """ path for resource-mgr"""
81 return ("D,/rw-vnfr:vnfr-console/rw-vnfr:vnfr[rw-vnfr:id='{}']/rw-vnfr:vdur[vnfr:id='{}']".format(self
._vnfr
_id
,self
._vdur
_id
))
83 def __init__(self
, dts
, log
, loop
, nsr
, vnfr_id
, vdur_id
, vdu_id
):
90 self
._vnfr
_id
= vnfr_id
91 self
._vdur
_id
= vdur_id
96 """ Register for VNFR VDU Operational Data read from dts """
99 def on_prepare(xact_info
, action
, ks_path
, msg
):
100 """ prepare callback from dts """
101 xpath
= ks_path
.to_xpath(RwVnfrYang
.get_schema())
103 "Got VNFR VDU Opdata xact_info: %s, action: %s): %s:%s",
104 xact_info
, action
, xpath
, msg
107 if action
== rwdts
.QueryAction
.READ
:
108 schema
= RwVnfrYang
.YangData_RwVnfr_VnfrConsole_Vnfr_Vdur
.schema()
109 path_entry
= schema
.keyspec_to_entry(ks_path
)
112 console_url
= yield from self
._loop
.run_in_executor(
114 self
._nsr
._http
_api
.get_instance_vm_console_url
,
119 self
._log
.debug("Got console response: %s for NSR ID %s vdur ID %s",
124 vdur_console
= RwVnfrYang
.YangData_RwVnfr_VnfrConsole_Vnfr_Vdur()
125 vdur_console
.id = self
._vdur
_id
127 vdur_console
.console_url
= console_url
129 vdur_console
.console_url
= 'none'
130 self
._log
.debug("Recevied console URL for vdu {} is {}".format(self
._vdu
_id
,vdur_console
))
131 except openmano_client
.InstanceStatusError
as e
:
132 self
._log
.error("Could not get NS instance console URL: %s",
134 vdur_console
= RwVnfrYang
.YangData_RwVnfr_VnfrConsole_Vnfr_Vdur()
135 vdur_console
.id = self
._vdur
_id
136 vdur_console
.console_url
= 'none'
138 xact_info
.respond_xpath(rsp_code
=rwdts
.XactRspCode
.ACK
,
139 xpath
=self
.vnfr_vdu_console_xpath
,
142 #raise VnfRecordError("Not supported operation %s" % action)
143 self
._log
.error("Not supported operation %s" % action
)
144 xact_info
.respond_xpath(rsp_code
=rwdts
.XactRspCode
.ACK
)
147 self
._log
.debug("Registering for VNFR VDU using xpath: %s",
148 self
.vnfr_vdu_console_xpath
)
149 hdl
= rift
.tasklets
.DTS
.RegistrationHandler(on_prepare
=on_prepare
,)
150 with self
._dts
.group_create() as group
:
151 self
._regh
= group
.register(xpath
=self
.vnfr_vdu_console_xpath
,
153 flags
=rwdts
.Flag
.PUBLISHER
,
158 class OpenmanoVnfr(object):
159 def __init__(self
, log
, loop
, cli_api
, vnfr
, nsd
):
162 self
._cli
_api
= cli_api
164 self
._vnfd
_id
= vnfr
.vnfd
.id
168 self
._created
= False
174 return rift2openmano
.RiftVNFD(self
._vnfr
.vnfd
)
181 def rift_vnfd_id(self
):
185 def openmano_vnfd_id(self
):
189 def openmano_vnfd(self
):
190 self
._log
.debug("Converting vnfd %s from rift to openmano", self
.vnfd
.id)
191 openmano_vnfd
= rift2openmano
.rift2openmano_vnfd(self
.vnfd
, self
.nsd
)
195 def openmano_vnfd_yaml(self
):
196 return yaml
.safe_dump(self
.openmano_vnfd
, default_flow_style
=False)
200 self
._log
.debug("Creating openmano vnfd")
201 openmano_vnfd
= self
.openmano_vnfd
202 name
= openmano_vnfd
["vnf"]["name"]
204 # If the name already exists, get the openmano vnfd id
205 name_uuid_map
= yield from self
._loop
.run_in_executor(
207 self
._cli
_api
.vnf_list
,
210 if name
in name_uuid_map
:
211 vnf_id
= name_uuid_map
[name
]
212 self
._log
.debug("Vnf already created. Got existing openmano vnfd id: %s", vnf_id
)
213 self
._vnf
_id
= vnf_id
216 self
._vnf
_id
, _
= yield from self
._loop
.run_in_executor(
218 self
._cli
_api
.vnf_create
,
219 self
.openmano_vnfd_yaml
,
222 fpath
= dump_openmano_descriptor(
223 "{}_vnf".format(name
),
224 self
.openmano_vnfd_yaml
227 self
._log
.debug("Dumped Openmano VNF descriptor to: %s", fpath
)
232 if not self
._created
:
235 self
._log
.debug("Deleting openmano vnfd")
236 if self
._vnf
_id
is None:
237 self
._log
.warning("Openmano vnf id not set. Cannot delete.")
240 self
._cli
_api
.vnf_delete(self
._vnf
_id
)
243 class OpenmanoNSRecordState(Enum
):
244 """ Network Service Record State """
245 # Make sure the values match with NetworkServiceRecordState
247 INSTANTIATION_PENDING
= 102
259 class OpenmanoNsr(object):
261 INSTANCE_TERMINATE_TIMEOUT
= 60
263 def __init__(self
, dts
, log
, loop
, publisher
, cli_api
, http_api
, nsd_msg
, nsr_config_msg
,key_pairs
,rift_vnfd_id
=None ):
267 self
._publisher
= publisher
268 self
._cli
_api
= cli_api
269 self
._http
_api
= http_api
271 self
._nsd
_msg
= nsd_msg
272 self
._nsr
_config
_msg
= nsr_config_msg
276 self
._vdur
_console
_handler
= {}
277 self
._key
_pairs
= key_pairs
279 self
._nsd
_uuid
= None
280 self
._nsr
_uuid
= None
281 self
._nsd
_msg
= nsd_msg
285 self
._created
= False
287 self
._monitor
_task
= None
288 self
._rift
_vnfd
_id
= rift_vnfd_id
289 self
._state
= OpenmanoNSRecordState
.INIT
293 return rift2openmano
.RiftNSD(self
._nsd
_msg
)
296 def rift_vnfd_id(self
):
297 return self
._rift
_vnfd
_id
304 def nsr_config_msg(self
):
305 return self
._nsr
_config
_msg
310 return {v
.rift_vnfd_id
: v
.vnfd
for v
in self
._vnfrs
}
314 return {v
.rift_vnfd_id
: v
.openmano_vnfd_id
for v
in self
._vnfrs
}
322 return self
._key
_pairs
333 def openmano_nsd_yaml(self
):
334 self
._log
.debug("Converting nsd %s from rift to openmano", self
.nsd
.id)
335 openmano_nsd
= rift2openmano
.rift2openmano_nsd(self
.nsd
, self
.vnfds
,self
.vnfr_ids
)
336 return yaml
.safe_dump(openmano_nsd
, default_flow_style
=False)
339 def openmano_scaling_yaml(self
):
340 self
._log
.debug("Creating Openmano Scaling Descriptor %s")
342 openmano_vnfd_nsd
= rift2openmano
.rift2openmano_vnfd_nsd(self
.nsd
, self
.vnfds
, self
.vnfr_ids
, self
._rift
_vnfd
_id
)
343 return yaml
.safe_dump(openmano_vnfd_nsd
, default_flow_style
=False)
344 except Exception as e
:
345 self
._log
.exception("Scaling Descriptor Exception: %s", str(e
))
347 def get_ssh_key_pairs(self
):
350 for authorized_key
in self
._nsr
_config
_msg
.ssh_authorized_key
:
351 self
._log
.debug("Key pair ref present is %s",authorized_key
.key_pair_ref
)
352 if authorized_key
.key_pair_ref
in self
._key
_pairs
:
353 key_pairs
.append(self
._key
_pairs
[authorized_key
.key_pair_ref
].key
)
355 for authorized_key
in self
._nsd
_msg
.key_pair
:
356 self
._log
.debug("Key pair NSD is %s",authorized_key
)
357 key_pairs
.append(authorized_key
.key
)
360 cloud_config
["key-pairs"] = key_pairs
363 for user_entry
in self
._nsr
_config
_msg
.user
:
364 self
._log
.debug("User present is %s",user_entry
)
366 user
["name"] = user_entry
.name
367 user
["key-pairs"] = list()
368 for ssh_key
in user_entry
.ssh_authorized_key
:
369 if ssh_key
.key_pair_ref
in self
._key
_pairs
:
370 user
["key-pairs"].append(self
._key
_pairs
[ssh_key
.key_pair_ref
].key
)
373 for user_entry
in self
._nsd
_msg
.user
:
374 self
._log
.debug("User present in NSD is %s",user_entry
)
376 user
["name"] = user_entry
.name
377 user
["key-pairs"] = list()
378 for ssh_key
in user_entry
.key_pair
:
379 user
["key-pairs"].append(ssh_key
.key
)
383 cloud_config
["users"] = users
385 self
._log
.debug("Cloud config formed is %s",cloud_config
)
390 def openmano_instance_create_yaml(self
):
391 self
._log
.debug("Creating instance-scenario-create input file for nsd %s with name %s", self
.nsd
.id, self
._nsr
_config
_msg
.name
)
392 openmano_instance_create
= {}
393 openmano_instance_create
["name"] = self
._nsr
_config
_msg
.name
394 openmano_instance_create
["description"] = self
._nsr
_config
_msg
.description
395 openmano_instance_create
["scenario"] = self
._nsd
_uuid
397 cloud_config
= self
.get_ssh_key_pairs()
399 openmano_instance_create
["cloud-config"] = cloud_config
400 if self
._nsr
_config
_msg
.has_field("om_datacenter"):
401 openmano_instance_create
["datacenter"] = self
._nsr
_config
_msg
.om_datacenter
402 openmano_instance_create
["vnfs"] = {}
403 for vnfr
in self
._vnfrs
:
404 if "om_datacenter" in vnfr
.vnfr
.vnfr_msg
:
405 vnfr_name
= vnfr
.vnfr
.vnfd
.name
+ "__" + str(vnfr
.vnfr
.vnfr_msg
.member_vnf_index_ref
)
406 openmano_instance_create
["vnfs"][vnfr_name
] = {"datacenter": vnfr
.vnfr
.vnfr_msg
.om_datacenter
}
407 openmano_instance_create
["networks"] = {}
408 for vld_msg
in self
._nsd
_msg
.vld
:
409 openmano_instance_create
["networks"][vld_msg
.name
] = {}
410 openmano_instance_create
["networks"][vld_msg
.name
]["sites"] = list()
411 for vlr
in self
._vlrs
:
412 if vlr
.vld_msg
.name
== vld_msg
.name
:
413 self
._log
.debug("Received VLR name %s, VLR DC: %s for VLD: %s",vlr
.vld_msg
.name
,
414 vlr
.om_datacenter_name
,vld_msg
.name
)
415 #network["vim-network-name"] = vld_msg.name
418 if vld_msg
.vim_network_name
:
419 network
["netmap-use"] = vld_msg
.vim_network_name
420 elif vlr
._ip
_profile
and vlr
._ip
_profile
.has_field("ip_profile_params"):
421 ip_profile_params
= vlr
._ip
_profile
.ip_profile_params
422 if ip_profile_params
.ip_version
== "ipv6":
423 ip_profile
['ip-version'] = "IPv6"
425 ip_profile
['ip-version'] = "IPv4"
426 if ip_profile_params
.has_field('subnet_address'):
427 ip_profile
['subnet-address'] = ip_profile_params
.subnet_address
428 if ip_profile_params
.has_field('gateway_address'):
429 ip_profile
['gateway-address'] = ip_profile_params
.gateway_address
430 if ip_profile_params
.has_field('dns_server') and len(ip_profile_params
.dns_server
) > 0:
431 ip_profile
['dns-address'] = ip_profile_params
.dns_server
[0].address
432 if ip_profile_params
.has_field('dhcp_params'):
433 ip_profile
['dhcp'] = {}
434 ip_profile
['dhcp']['enabled'] = ip_profile_params
.dhcp_params
.enabled
435 ip_profile
['dhcp']['start-address'] = ip_profile_params
.dhcp_params
.start_address
436 ip_profile
['dhcp']['count'] = ip_profile_params
.dhcp_params
.count
438 network
["netmap-create"] = vlr
.name
439 if vlr
.om_datacenter_name
:
440 network
["datacenter"] = vlr
.om_datacenter_name
441 elif vld_msg
.has_field("om_datacenter"):
442 network
["datacenter"] = vld_msg
.om_datacenter
443 elif "datacenter" in openmano_instance_create
:
444 network
["datacenter"] = openmano_instance_create
["datacenter"]
446 openmano_instance_create
["networks"][vld_msg
.name
]["sites"].append(network
)
448 openmano_instance_create
["networks"][vld_msg
.name
]['ip-profile'] = ip_profile
450 return yaml
.safe_dump(openmano_instance_create
, default_flow_style
=False,width
=1000)
453 def scaling_instance_create_yaml(self
, scaleout
=False):
454 self
._log
.debug("Creating instance-scenario-create input file for nsd %s with name %s", self
.nsd
.id, self
._nsr
_config
_msg
.name
+"scal1")
455 scaling_instance_create
= {}
456 for group_list
in self
._nsd
_msg
.scaling_group_descriptor
:
457 scaling_instance_create
["name"] = self
._nsr
_config
_msg
.name
+ "__"+group_list
.name
459 scaling_instance_create
["scenario"] = self
._nsd
_uuid
+ "__" +group_list
.name
461 scaling_instance_create
["scenario"] = self
._nsd
_uuid
462 scaling_instance_create
["description"] = self
._nsr
_config
_msg
.description
465 if self
._nsr
_config
_msg
.has_field("om_datacenter"):
466 scaling_instance_create
["datacenter"] = self
._nsr
_config
_msg
.om_datacenter
467 scaling_instance_create
["vnfs"] = {}
468 for vnfr
in self
._vnfrs
:
469 if "om_datacenter" in vnfr
.vnfr
.vnfr_msg
:
470 vnfr_name
= vnfr
.vnfr
.vnfd
.name
+ "__" + str(vnfr
.vnfr
.vnfr_msg
.member_vnf_index_ref
)
471 scaling_instance_create
["vnfs"][vnfr_name
] = {"datacenter": vnfr
.vnfr
.vnfr_msg
.om_datacenter
}
472 scaling_instance_create
["networks"] = {}
473 for vld_msg
in self
._nsd
_msg
.vld
:
474 scaling_instance_create
["networks"][vld_msg
.name
] = {}
475 scaling_instance_create
["networks"][vld_msg
.name
]["sites"] = list()
476 for vlr
in self
._vlrs
:
477 if vlr
.vld_msg
.name
== vld_msg
.name
:
478 self
._log
.debug("Received VLR name %s, VLR DC: %s for VLD: %s",vlr
.vld_msg
.name
,
479 vlr
.om_datacenter_name
,vld_msg
.name
)
480 #network["vim-network-name"] = vld_msg.name
483 if vld_msg
.vim_network_name
:
484 network
["netmap-use"] = vld_msg
.vim_network_name
486 # network["netmap-create"] = vlr.name
487 if vlr
.om_datacenter_name
:
488 network
["datacenter"] = vlr
.om_datacenter_name
489 elif vld_msg
.has_field("om_datacenter"):
490 network
["datacenter"] = vld_msg
.om_datacenter
491 elif "datacenter" in scaling_instance_create
:
492 network
["datacenter"] = scaling_instance_create
["datacenter"]
494 scaling_instance_create
["networks"][vld_msg
.name
]["sites"].append(network
)
496 return yaml
.safe_dump(scaling_instance_create
, default_flow_style
=False, width
=1000)
499 def add_vlr(self
, vlr
):
500 self
._vlrs
.append(vlr
)
501 yield from self
._publisher
.publish_vlr(None, vlr
.vlr_msg
)
502 yield from asyncio
.sleep(1, loop
=self
._loop
)
505 def remove_vlr(self
, vlr
):
506 if vlr
in self
._vlrs
:
507 self
._vlrs
.remove(vlr
)
508 yield from self
._publisher
.unpublish_vlr(None, vlr
.vlr_msg
)
509 yield from asyncio
.sleep(1, loop
=self
._loop
)
512 def remove_vnf(self
,vnf
):
513 if vnf
in self
._vnfrs
:
514 self
._vnfrs
.remove(vnf
)
515 yield from self
._publisher
.unpublish_vnfr(
519 yield from asyncio
.sleep(1, loop
=self
._loop
)
522 def delete_vlr(self
, vlr
):
523 if vlr
in self
._vlrs
:
524 self
._vlrs
.remove(vlr
)
525 if not vlr
.vld_msg
.vim_network_name
:
526 yield from self
._loop
.run_in_executor(
528 self
._cli
_api
.ns_vim_network_delete
,
530 vlr
.om_datacenter_name
)
531 yield from self
._publisher
.unpublish_vlr(None, vlr
.vlr_msg
)
532 yield from asyncio
.sleep(1, loop
=self
._loop
)
535 def add_vnfr(self
, vnfr
):
536 vnfr
= OpenmanoVnfr(self
._log
, self
._loop
, self
._cli
_api
, vnfr
, nsd
=self
.nsd
)
537 yield from vnfr
.create()
538 self
._vnfrs
.append(vnfr
)
541 def add_nsr(self
, nsr
, vnfr
):
542 self
._nsrs
[vnfr
.id] = nsr
545 if not self
._created
:
546 self
._log
.debug("NSD wasn't created. Skipping delete.")
549 self
._log
.debug("Deleting openmano nsr")
550 self
._cli
_api
.ns_delete(self
._nsd
_uuid
)
552 self
._log
.debug("Deleting openmano vnfrs")
553 deleted_vnf_id_list
= []
554 for vnfr
in self
._vnfrs
:
555 if vnfr
.vnfr
.vnfd
.id not in deleted_vnf_id_list
:
557 deleted_vnf_id_list
.append(vnfr
.vnfr
.vnfd
.id)
562 self
._log
.debug("Creating openmano scenario")
563 name_uuid_map
= yield from self
._loop
.run_in_executor(
565 self
._cli
_api
.ns_list
,
568 if self
._nsd
_msg
.name
in name_uuid_map
:
569 self
._log
.debug("Found existing openmano scenario")
570 self
._nsd
_uuid
= name_uuid_map
[self
._nsd
_msg
.name
]
574 # Use the nsd uuid as the scenario name to rebind to existing
575 # scenario on reload or to support muliple instances of the name
577 self
._nsd
_uuid
, _
= yield from self
._loop
.run_in_executor(
579 self
._cli
_api
.ns_create
,
580 self
.openmano_nsd_yaml
,
583 fpath
= dump_openmano_descriptor(
584 "{}_nsd".format(self
._nsd
_msg
.name
),
585 self
.openmano_nsd_yaml
,
588 self
._log
.debug("Dumped Openmano NS descriptor to: %s", fpath
)
593 def scaling_scenario_create(self
):
594 self
._log
.debug("Creating scaling openmano scenario")
595 self
._nsd
_uuid
, _
= yield from self
._loop
.run_in_executor(
597 self
._cli
_api
.ns_create
,
598 self
.openmano_scaling_yaml
,
601 fpath
= dump_openmano_descriptor(
602 "{}_sgd".format(self
._nsd
_msg
.name
),
603 self
.scaling_instance_create_yaml
,
607 def instance_monitor_task(self
):
608 self
._log
.debug("Starting Instance monitoring task")
610 start_time
= time
.time()
614 yield from asyncio
.sleep(1, loop
=self
._loop
)
617 instance_resp_json
= yield from self
._loop
.run_in_executor(
619 self
._http
_api
.get_instance
,
623 self
._log
.debug("Got instance response: %s for NSR ID %s",
627 except openmano_client
.InstanceStatusError
as e
:
628 self
._log
.error("Could not get NS instance status: %s", str(e
))
631 def all_vms_active(vnf
):
632 for vm
in vnf
["vms"]:
633 vm_status
= vm
["status"]
635 if vm_status
!= "ACTIVE":
636 self
._log
.debug("VM is not yet active: %s (status: %s)", vm_uuid
, vm_status
)
641 def any_vm_active_nomgmtip(vnf
):
642 for vm
in vnf
["vms"]:
643 vm_status
= vm
["status"]
645 if vm_status
!= "ACTIVE":
646 self
._log
.debug("VM is not yet active: %s (status: %s)", vm_uuid
, vm_status
)
651 def any_vms_error(vnf
):
652 for vm
in vnf
["vms"]:
653 vm_status
= vm
["status"]
654 vm_vim_info
= vm
["vim_info"]
656 if vm_status
== "ERROR":
657 self
._log
.error("VM Error: %s (vim_info: %s)", vm_uuid
, vm_vim_info
)
662 def get_vnf_ip_address(vnf
):
663 if "ip_address" in vnf
:
664 return vnf
["ip_address"].strip()
667 def get_vnf_mac_address(vnf
):
668 if "mac_address" in vnf
:
669 return vnf
["mac_address"].strip()
672 def get_ext_cp_info(vnf
):
674 for vm
in vnf
["vms"]:
675 if "interfaces" not in vm
:
678 for intf
in vm
["interfaces"]:
679 if "external_name" not in intf
:
682 if not intf
["external_name"]:
685 ip_address
= intf
["ip_address"]
686 if ip_address
is None:
687 ip_address
= "0.0.0.0"
689 mac_address
= intf
["mac_address"]
690 if mac_address
is None:
691 mac_address
="00:00:00:00:00:00"
693 cp_info_list
.append((intf
["external_name"], ip_address
, mac_address
))
697 def get_vnf_status(vnfr
):
698 # When we create an openmano descriptor we use <name>__<idx>
699 # to come up with openmano constituent VNF name. Use this
700 # knowledge to map the vnfr back.
701 openmano_vnfr_suffix
= "__{}".format(
702 vnfr
.vnfr
.vnfr_msg
.member_vnf_index_ref
705 for vnf
in instance_resp_json
["vnfs"]:
706 if vnf
["vnf_name"].endswith(openmano_vnfr_suffix
):
709 self
._log
.warning("Could not find vnf status with name that ends with: %s",
710 openmano_vnfr_suffix
)
713 for vnfr
in self
._vnfrs
:
714 if vnfr
in active_vnfs
:
715 # Skipping, so we don't re-publish the same VNF message.
718 vnfr_msg
= vnfr
.vnfr
.vnfr_msg
.deep_copy()
719 vnfr_msg
.operational_status
= "init"
722 vnf_status
= get_vnf_status(vnfr
)
723 self
._log
.debug("Found VNF status: %s", vnf_status
)
724 if vnf_status
is None:
725 self
._log
.error("Could not find VNF status from openmano")
726 self
._state
= OpenmanoNSRecordState
.FAILED
727 vnfr_msg
.operational_status
= "failed"
728 yield from self
._publisher
.publish_vnfr(None, vnfr_msg
)
731 # If there was a VNF that has a errored VM, then just fail the VNF and stop monitoring.
732 if any_vms_error(vnf_status
):
733 self
._log
.debug("VM was found to be in error state. Marking as failed.")
734 self
._state
= OpenmanoNSRecordState
.FAILED
735 vnfr_msg
.operational_status
= "failed"
736 yield from self
._publisher
.publish_vnfr(None, vnfr_msg
)
739 if (time
.time() - start_time
) > OpenmanoNsr
.TIMEOUT_SECS
:
740 self
._log
.error("NSR timed out before reaching running state")
741 self
._state
= OpenmanoNSRecordState
.FAILED
742 vnfr_msg
.operational_status
= "failed"
743 yield from self
._publisher
.publish_vnfr(None, vnfr_msg
)
746 if all_vms_active(vnf_status
):
747 vnf_ip_address
= get_vnf_ip_address(vnf_status
)
748 vnf_mac_address
= get_vnf_mac_address(vnf_status
)
750 if vnf_ip_address
is None:
751 self
._log
.warning("No IP address obtained "
752 "for VNF: {}, will retry.".format(
753 vnf_status
['vnf_name']))
756 self
._log
.debug("All VMs in VNF are active. Marking as running.")
757 vnfr_msg
.operational_status
= "running"
759 self
._log
.debug("Got VNF ip address: %s, mac-address: %s", vnf_ip_address
, vnf_mac_address
)
760 vnfr_msg
.mgmt_interface
.ip_address
= vnf_ip_address
761 vnfr_msg
.vnf_configuration
.config_access
.mgmt_ip_address
= vnf_ip_address
764 for vm
in vnf_status
["vms"]:
765 if vm
["uuid"] not in self
._vdur
_console
_handler
:
766 vdur_console_handler
= VnfrConsoleOperdataDtsHandler(self
._dts
, self
._log
, self
._loop
,
767 self
, vnfr_msg
.id,vm
["uuid"],vm
["name"])
768 yield from vdur_console_handler
.register()
769 self
._vdur
_console
_handler
[vm
["uuid"]] = vdur_console_handler
771 vdur_msg
= vnfr_msg
.vdur
.add()
772 vdur_msg
.vim_id
= vm
["vim_vm_id"]
773 vdur_msg
.id = vm
["uuid"]
775 # Add connection point information for the config manager
776 cp_info_list
= get_ext_cp_info(vnf_status
)
777 for (cp_name
, cp_ip
, cp_mac_addr
) in cp_info_list
:
778 cp
= vnfr_msg
.connection_point
.add()
780 cp
.short_name
= cp_name
781 cp
.ip_address
= cp_ip
782 cp
.mac_address
= cp_mac_addr
784 yield from self
._publisher
.publish_vnfr(None, vnfr_msg
)
785 active_vnfs
.append(vnfr
)
787 except Exception as e
:
788 vnfr_msg
.operational_status
= "failed"
789 self
._state
= OpenmanoNSRecordState
.FAILED
790 yield from self
._publisher
.publish_vnfr(None, vnfr_msg
)
791 self
._log
.exception("Caught exception publishing vnfr info: %s", str(e
))
794 if len(active_vnfs
) == len(self
._vnfrs
):
795 self
._state
= OpenmanoNSRecordState
.RUNNING
796 self
._log
.info("All VNF's are active. Exiting NSR monitoring task")
800 def deploy(self
,nsr_msg
):
801 if self
._nsd
_uuid
is None:
802 raise ValueError("Cannot deploy an uncreated nsd")
804 self
._log
.debug("Deploying openmano instance scenario")
806 name_uuid_map
= yield from self
._loop
.run_in_executor(
808 self
._cli
_api
.ns_instance_list
,
811 if self
._nsr
_config
_msg
.name
in name_uuid_map
:
812 self
._log
.debug("Found existing instance with nsr name: %s", self
._nsr
_config
_msg
.name
)
813 self
._nsr
_uuid
= name_uuid_map
[self
._nsr
_config
_msg
.name
]
815 self
._nsr
_msg
= nsr_msg
816 fpath
= dump_openmano_descriptor(
817 "{}_instance_sce_create".format(self
._nsr
_config
_msg
.name
),
818 self
.openmano_instance_create_yaml
,
820 self
._log
.debug("Dumped Openmano instance Scenario Cretae to: %s", fpath
)
822 self
._nsr
_uuid
= yield from self
._loop
.run_in_executor(
824 self
._cli
_api
.ns_instance_scenario_create
,
825 self
.openmano_instance_create_yaml
)
827 self
._state
= OpenmanoNSRecordState
.INSTANTIATION_PENDING
829 self
._monitor
_task
= asyncio
.ensure_future(
830 self
.instance_monitor_task(), loop
=self
._loop
834 def deploy_scaling(self
, nsr_msg
, rift_vnfd_id
):
835 self
._log
.debug("Deploying Scaling instance scenario")
836 self
._nsr
_msg
= nsr_msg
837 self
._rift
_vnfd
_id
= rift_vnfd_id
838 fpath
= dump_openmano_descriptor(
839 "{}_scale_instance".format(self
._nsr
_config
_msg
.name
),
840 self
.scaling_instance_create_yaml
842 self
._nsr
_uuid
= yield from self
._loop
.run_in_executor(
844 self
._cli
_api
.ns_instance_scenario_create
,
845 self
.scaling_instance_create_yaml
)
847 self
._state
= OpenmanoNSRecordState
.INSTANTIATION_PENDING
849 self
._monitor
_task
= asyncio
.ensure_future(
850 self
.instance_monitor_task(), loop
=self
._loop
853 self
._state
= OpenmanoNSRecordState
.INIT
857 if self
._nsr
_uuid
is None:
858 start_time
= time
.time()
859 while ((time
.time() - start_time
) < OpenmanoNsr
.INSTANCE_TERMINATE_TIMEOUT
) and (self
._nsr
_uuid
is None):
861 self
._log
.warning("Waiting for nsr to get instatiated")
862 if self
._nsr
_uuid
is None:
863 self
._log
.warning("Cannot terminate an un-instantiated nsr")
866 if self
._monitor
_task
is not None:
867 self
._monitor
_task
.cancel()
868 self
._monitor
_task
= None
870 self
._log
.debug("Terminating openmano nsr")
871 self
._cli
_api
.ns_terminate(self
._nsr
_uuid
)
874 def create_vlr(self
,vlr
):
875 self
._log
.debug("Creating openmano vim network VLR name %s, VLR DC: %s",vlr
.vld_msg
.name
,
876 vlr
.om_datacenter_name
)
879 net
['name'] = vlr
.name
881 net
['type'] = 'bridge'
882 self
._log
.debug("Received ip profile is %s",vlr
._ip
_profile
)
883 if vlr
._ip
_profile
and vlr
._ip
_profile
.has_field("ip_profile_params"):
884 ip_profile_params
= vlr
._ip
_profile
.ip_profile_params
886 if ip_profile_params
.ip_version
== "ipv6":
887 ip_profile
['ip_version'] = "IPv6"
889 ip_profile
['ip_version'] = "IPv4"
890 if ip_profile_params
.has_field('subnet_address'):
891 ip_profile
['subnet_address'] = ip_profile_params
.subnet_address
892 if ip_profile_params
.has_field('gateway_address'):
893 ip_profile
['gateway_address'] = ip_profile_params
.gateway_address
894 if ip_profile_params
.has_field('dns_server') and len(ip_profile_params
.dns_server
) > 0:
895 ip_profile
['dns_address'] = ip_profile_params
.dns_server
[0].address
896 if ip_profile_params
.has_field('dhcp_params'):
897 ip_profile
['dhcp_enabled'] = ip_profile_params
.dhcp_params
.enabled
898 ip_profile
['dhcp_start_address'] = ip_profile_params
.dhcp_params
.start_address
899 ip_profile
['dhcp_count'] = ip_profile_params
.dhcp_params
.count
900 net
['ip_profile'] = ip_profile
901 net_create
["network"]= net
903 net_create_msg
= yaml
.safe_dump(net_create
,default_flow_style
=False)
904 fpath
= dump_openmano_descriptor(
905 "{}_vim_net_create_{}".format(self
._nsr
_config
_msg
.name
,vlr
.name
),
907 self
._log
.debug("Dumped Openmano VIM Net create to: %s", fpath
)
909 vim_network_uuid
= yield from self
._loop
.run_in_executor(
911 self
._cli
_api
.ns_vim_network_create
,
913 vlr
.om_datacenter_name
)
914 self
._vlrs
.append(vlr
)
918 class OpenmanoNsPlugin(rwnsmplugin
.NsmPluginBase
):
920 RW Implentation of the NsmPluginBase
922 def __init__(self
, dts
, log
, loop
, publisher
, ro_account
):
926 self
._publisher
= publisher
929 self
._http
_api
= None
930 self
._openmano
_nsrs
= {}
931 self
._vnfr
_uptime
_tasks
= {}
932 self
._openmano
_nsr
_by
_vnfr
_id
= {}
933 #self._nsr_uuid = None
935 self
._set
_ro
_account
(ro_account
)
937 def _set_ro_account(self
, ro_account
):
938 self
._log
.debug("Setting openmano plugin cloud account: %s", ro_account
)
939 self
._cli
_api
= openmano_client
.OpenmanoCliAPI(
941 ro_account
.openmano
.host
,
942 ro_account
.openmano
.port
,
943 ro_account
.openmano
.tenant_id
,
946 self
._http
_api
= openmano_client
.OpenmanoHttpAPI(
948 ro_account
.openmano
.host
,
949 ro_account
.openmano
.port
,
950 ro_account
.openmano
.tenant_id
,
953 def set_state(self
, nsr_id
, state
):
954 # Currently we update only during terminate to
955 # decide how to handle VL terminate
956 if state
.value
== OpenmanoNSRecordState
.TERMINATE
.value
:
957 self
._openmano
_nsrs
[nsr_id
]._state
= \
958 [member
.value
for name
, member
in \
959 OpenmanoNSRecordState
.__members
__.items() \
960 if member
.value
== state
.value
]
962 def create_nsr(self
, nsr_config_msg
, nsd_msg
, key_pairs
=None):
964 Create Network service record
966 openmano_nsr
= OpenmanoNsr(
977 self
._openmano
_nsrs
[nsr_config_msg
.id] = openmano_nsr
980 def deploy(self
, nsr_msg
):
981 self
._log
.debug("Received NSR Deploy msg : %s", nsr_msg
)
982 openmano_nsr
= self
._openmano
_nsrs
[nsr_msg
.ns_instance_config_ref
]
983 yield from openmano_nsr
.create()
984 yield from openmano_nsr
.deploy(nsr_msg
)
987 def instantiate_ns(self
, nsr
, xact
):
989 Instantiate NSR with the passed nsr id
991 yield from nsr
.instantiate(xact
)
994 def instantiate_vnf(self
, nsr
, vnfr
, scaleout
=False):
996 Instantiate NSR with the passed nsr id
998 openmano_nsr
= self
._openmano
_nsrs
[nsr
.id]
1000 openmano_vnf_nsr
= OpenmanoNsr(
1007 openmano_nsr
.nsd_msg
,
1008 openmano_nsr
.nsr_config_msg
,
1009 openmano_nsr
.key_pairs
,
1012 self
._openmano
_nsr
_by
_vnfr
_id
[nsr
.id] = openmano_nsr
1013 if vnfr
.id in self
._openmano
_nsr
_by
_vnfr
_id
:
1014 raise VNFExistError("VNF %s already exist", vnfr
.id)
1015 self
._openmano
_nsr
_by
_vnfr
_id
[vnfr
.id] = openmano_vnf_nsr
1016 self
._log
.debug("VNFRID %s %s %s", type(self
._openmano
_nsr
_by
_vnfr
_id
), type(openmano_vnf_nsr
), type(self
._openmano
_nsr
_by
_vnfr
_id
[vnfr
.id]))
1018 for vlr
in openmano_nsr
.vlrs
:
1019 yield from openmano_vnf_nsr
.add_vlr(vlr
)
1021 yield from openmano_nsr
.add_nsr(openmano_vnf_nsr
, vnfr
)
1022 except Exception as e
:
1023 self
.log
.exception(str(e
))
1025 yield from openmano_vnf_nsr
.add_vnfr(vnfr
)
1026 except Exception as e
:
1027 self
.log
.exception(str(e
))
1029 yield from openmano_vnf_nsr
.scaling_scenario_create()
1030 except Exception as e
:
1031 self
.log
.exception(str(e
))
1033 yield from openmano_vnf_nsr
.deploy_scaling(openmano_vnf_nsr
.nsr_msg
, vnfr
.id)
1034 except Exception as e
:
1035 self
.log
.exception(str(e
))
1037 yield from openmano_nsr
.add_vnfr(vnfr
)
1039 # Mark the VNFR as running
1040 # TODO: Create a task to monitor nsr/vnfr status
1041 vnfr_msg
= vnfr
.vnfr_msg
.deep_copy()
1042 vnfr_msg
.operational_status
= "init"
1044 self
._log
.debug("Attempting to publish openmano vnf: %s", vnfr_msg
)
1045 with self
._dts
.transaction() as xact
:
1046 yield from self
._publisher
.publish_vnfr(xact
, vnfr_msg
)
1047 self
._log
.debug("Creating a task to update uptime for vnfr: %s", vnfr
.id)
1048 self
._vnfr
_uptime
_tasks
[vnfr
.id] = self
._loop
.create_task(self
.vnfr_uptime_update(vnfr
))
1050 def vnfr_uptime_update(self
, vnfr
):
1052 vnfr_
= RwVnfrYang
.YangData_Vnfr_VnfrCatalog_Vnfr
.from_dict({'id': vnfr
.id})
1054 vnfr_
.uptime
= int(time
.time()) - vnfr
._create
_time
1055 yield from self
._publisher
.publish_vnfr(None, vnfr_
)
1056 yield from asyncio
.sleep(2, loop
=self
._loop
)
1057 except asyncio
.CancelledError
:
1058 self
._log
.debug("Received cancellation request for vnfr_uptime_update task")
1061 def instantiate_vl(self
, nsr
, vlr
):
1063 Instantiate NSR with the passed nsr id
1065 self
._log
.debug("Received instantiate VL for NSR {}; VLR {}".format(nsr
.id,vlr
))
1066 openmano_nsr
= self
._openmano
_nsrs
[nsr
.id]
1067 if openmano_nsr
._state
== OpenmanoNSRecordState
.RUNNING
:
1068 yield from openmano_nsr
.create_vlr(vlr
)
1069 yield from self
._publisher
.publish_vlr(None, vlr
.vlr_msg
)
1071 yield from openmano_nsr
.add_vlr(vlr
)
1074 def terminate_ns(self
, nsr
):
1076 Terminate the network service
1079 openmano_nsr
= self
._openmano
_nsrs
[nsr_id
]
1081 for _
,handler
in openmano_nsr
._vdur
_console
_handler
.items():
1082 handler
._regh
.deregister()
1084 yield from self
._loop
.run_in_executor(
1090 with self
._dts
.transaction() as xact
:
1091 for vnfr
in openmano_nsr
.vnfrs
:
1092 self
._log
.debug("Unpublishing VNFR: %s", vnfr
.vnfr
.vnfr_msg
)
1093 yield from self
._publisher
.unpublish_vnfr(xact
, vnfr
.vnfr
.vnfr_msg
)
1095 del self
._openmano
_nsrs
[nsr_id
]
1097 def terminate(self
, openmano_nsr
):
1098 openmano_nsr
.terminate()
1099 openmano_nsr
.delete()
1102 def terminate_vnf(self
, nsr
, vnfr
, scalein
=False):
1104 Terminate the network service
1107 openmano_vnf_nsr
= self
._openmano
_nsr
_by
_vnfr
_id
[vnfr
.id]
1108 openmano_vnf_nsr
.terminate()
1109 openmano_vnf_nsr
.delete()
1110 yield from openmano_vnf_nsr
.remove_vnf(vnfr
)
1111 if vnfr
.id in self
._vnfr
_uptime
_tasks
:
1112 self
._vnfr
_uptime
_tasks
[vnfr
.id].cancel()
1115 def terminate_vl(self
, vlr
):
1117 Terminate the virtual link
1119 self
._log
.debug("Received terminate VL for VLR {}".format(vlr
))
1120 openmano_nsr
= self
._openmano
_nsrs
[vlr
._nsr
_id
]
1121 if openmano_nsr
._state
== OpenmanoNSRecordState
.RUNNING
:
1122 yield from openmano_nsr
.delete_vlr(vlr
)
1124 yield from openmano_nsr
.remove_vlr(vlr
)