From d0d7b8a40207d7c67e72c65879226c441e443d05 Mon Sep 17 00:00:00 2001 From: Suresh Balakrishnan Date: Thu, 22 Sep 2016 07:29:57 -0400 Subject: [PATCH] Bug 50 Cloud-init support in SO for ssh key injection Signed-off-by: Suresh Balakrishnan --- models/plugins/yang/nsd.yang | 49 ++++++++++++++++- models/plugins/yang/nsr.yang | 25 ++++++--- .../rwnsm/rift/tasklets/rwnsmtasklet/cloud.py | 2 +- .../tasklets/rwnsmtasklet/openmano_nsm.py | 53 +++++++++++++++++-- .../tasklets/rwnsmtasklet/rwnsmtasklet.py | 35 +++++++++--- 5 files changed, 145 insertions(+), 19 deletions(-) diff --git a/models/plugins/yang/nsd.yang b/models/plugins/yang/nsd.yang index 5fffa457..ac0987c9 100644 --- a/models/plugins/yang/nsd.yang +++ b/models/plugins/yang/nsd.yang @@ -902,15 +902,62 @@ module nsd uses ns-initial-config-primitive; } + + list key-pair { + key "name"; + description "Used to configure the list of public keys to be injected as part + of ns instantiation"; + + leaf name { + description "Name of this key pair"; + type string; + } + + leaf key { + description "Key associated with this key pair"; + type string; + } + } + + list user { + key "name"; + description "List of users to be added through cloud-config"; + + leaf name { + description "Name of the user "; + type string; + } + + leaf user-info { + description "The user name's real name"; + type string; + } + + list key-pair { + key "name"; + description "Used to configure the list of public keys to be injected as part + of ns instantiation"; + + leaf name { + description "Name of this key pair"; + type string; + } + + leaf key { + description "Key associated with this key pair"; + type string; + } + } + } } + container nsd-catalog { list nsd { key "id"; uses nsd-descriptor; - } } diff --git a/models/plugins/yang/nsr.yang b/models/plugins/yang/nsr.yang index 78c86ad3..c6bb4ec9 100644 --- a/models/plugins/yang/nsr.yang +++ b/models/plugins/yang/nsr.yang @@ -98,9 +98,7 @@ module nsr leaf key-pair-ref { description "A reference to the key pair entry in the global key pair table"; - type leafref { - path "/nsr:key-pair/nsr:name"; - } + type string; } } list user { @@ -111,13 +109,24 @@ module nsr description "Name of the user "; type string; } - leaf gecos { + leaf user-info { description "The user name's real name"; type string; } - leaf passwd { - description "The user password"; - type string; + list key-pair { + key "name"; + description "Used to configure the list of public keys to be injected as part + of ns instantiation"; + + leaf name { + description "Name of this key pair"; + type string; + } + + leaf key { + description "Key associated with this key pair"; + type string; + } } } } @@ -161,6 +170,8 @@ module nsr } } + + container ns-instance-config { list nsr { diff --git a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/cloud.py b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/cloud.py index 5d73680b..6be37611 100644 --- a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/cloud.py +++ b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/cloud.py @@ -40,7 +40,7 @@ class RwNsPlugin(rwnsmplugin.NsmPluginBase): self._log = log self._loop = loop - def create_nsr(self, nsr_msg, nsd): + def create_nsr(self, nsr_msg, nsd,key_pairs=None): """ Create Network service record """ diff --git a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/openmano_nsm.py b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/openmano_nsm.py index 17a13a39..5bf86dec 100644 --- a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/openmano_nsm.py +++ b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/openmano_nsm.py @@ -241,7 +241,7 @@ class OpenmanoVnfr(object): class OpenmanoNsr(object): TIMEOUT_SECS = 120 - def __init__(self, dts, log, loop, publisher, cli_api, http_api, nsd_msg, nsr_config_msg): + def __init__(self, dts, log, loop, publisher, cli_api, http_api, nsd_msg, nsr_config_msg,key_pairs): self._dts = dts self._log = log self._loop = loop @@ -255,6 +255,7 @@ class OpenmanoNsr(object): self._vlrs = [] self._vnfrs = [] self._vdur_console_handler = {} + self._key_pairs = key_pairs self._nsd_uuid = None self._nsr_uuid = None @@ -287,6 +288,46 @@ class OpenmanoNsr(object): openmano_nsd = rift2openmano.rift2openmano_nsd(self.nsd, self.vnfds,self.vnfr_ids) return yaml.safe_dump(openmano_nsd, default_flow_style=False) + def get_ssh_key_pairs(self): + cloud_config = {} + key_pairs = list() + for authorized_key in self._nsr_config_msg.ssh_authorized_key: + self._log.debug("Key pair ref present is %s",authorized_key.key_pair_ref) + if authorized_key.key_pair_ref in self._key_pairs: + key_pairs.append(self._key_pairs[authorized_key.key_pair_ref].key) + + for authorized_key in self._nsd_msg.key_pair: + self._log.debug("Key pair NSD is %s",authorized_key) + key_pairs.append(authorized_key.key) + + if key_pairs: + cloud_config["key-pairs"] = key_pairs + + users = list() + for user_entry in self._nsr_config_msg.user: + self._log.debug("User present is %s",user_entry) + user = {} + user["name"] = user_entry.name + user["key-pairs"] = list() + for ssh_key in user_entry.key_pair: + user["key-pairs"].append(ssh_key.key) + users.append(user) + + for user_entry in self._nsd_msg.user: + self._log.debug("User present in NSD is %s",user_entry) + user = {} + user["name"] = user_entry.name + user["key-pairs"] = list() + for ssh_key in user_entry.key_pair: + user["key-pairs"].append(ssh_key.key) + users.append(user) + + if users: + cloud_config["users"] = users + + self._log.debug("Cloud config formed is %s",cloud_config) + return cloud_config + @property def openmano_instance_create_yaml(self): @@ -295,6 +336,10 @@ class OpenmanoNsr(object): openmano_instance_create["name"] = self._nsr_config_msg.name openmano_instance_create["description"] = self._nsr_config_msg.description openmano_instance_create["scenario"] = self._nsd_uuid + + cloud_config = self.get_ssh_key_pairs() + if cloud_config: + openmano_instance_create["cloud-config"] = cloud_config if self._nsr_config_msg.has_field("om_datacenter"): openmano_instance_create["datacenter"] = self._nsr_config_msg.om_datacenter openmano_instance_create["vnfs"] = {} @@ -344,6 +389,7 @@ class OpenmanoNsr(object): openmano_instance_create["networks"][vld_msg.name]["sites"].append(network) if ip_profile: openmano_instance_create["networks"][vld_msg.name]['ip-profile'] = ip_profile + return yaml.safe_dump(openmano_instance_create, default_flow_style=False) @@ -673,7 +719,7 @@ class OpenmanoNsPlugin(rwnsmplugin.NsmPluginBase): ro_account.openmano.tenant_id, ) - def create_nsr(self, nsr_config_msg, nsd_msg): + def create_nsr(self, nsr_config_msg, nsd_msg, key_pairs=None): """ Create Network service record """ @@ -685,7 +731,8 @@ class OpenmanoNsPlugin(rwnsmplugin.NsmPluginBase): self._cli_api, self._http_api, nsd_msg, - nsr_config_msg + nsr_config_msg, + key_pairs ) self._openmano_nsrs[nsr_config_msg.id] = openmano_nsr diff --git a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsmtasklet.py b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsmtasklet.py index f4c0aef1..9877ae9c 100755 --- a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsmtasklet.py +++ b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsmtasklet.py @@ -1231,7 +1231,7 @@ class NetworkServiceRecord(object): """ Network service record """ XPATH = "D,/nsr:ns-instance-opdata/nsr:nsr" - def __init__(self, dts, log, loop, nsm, nsm_plugin, nsr_cfg_msg, sdn_account_name, restart_mode=False): + def __init__(self, dts, log, loop, nsm, nsm_plugin, nsr_cfg_msg, sdn_account_name, key_pairs, restart_mode=False): self._dts = dts self._log = log self._loop = loop @@ -1243,6 +1243,7 @@ class NetworkServiceRecord(object): self._nsd = None self._nsr_msg = None self._nsr_regh = None + self._key_pairs = key_pairs self._vlrs = [] self._vnfrs = {} self._vnfds = {} @@ -3053,6 +3054,7 @@ class NsrDtsHandler(object): """ The network service DTS handler """ NSR_XPATH = "C,/nsr:ns-instance-config/nsr:nsr" SCALE_INSTANCE_XPATH = "C,/nsr:ns-instance-config/nsr:nsr/nsr:scaling-group/nsr:instance" + KEY_PAIR_XPATH = "C,/nsr:key-pair" def __init__(self, dts, log, loop, nsm): self._dts = dts @@ -3062,6 +3064,7 @@ class NsrDtsHandler(object): self._nsr_regh = None self._scale_regh = None + self._key_pair_regh = None @property def nsm(self): @@ -3195,12 +3198,20 @@ class NsrDtsHandler(object): return added_cfgs, deleted_cfgs, updated_cfgs + def get_nsr_key_pairs(dts_member_reg, xact): + key_pairs = {} + for instance_cfg, keyspec in dts_member_reg.get_xact_elements(xact, include_keyspec=True): + self._log.debug("Key pair received is {} KS: {}".format(instance_cfg, keyspec)) + xpath = keyspec.to_xpath(RwNsrYang.get_schema()) + key_pairs[instance_cfg.name] = instance_cfg + return key_pairs + def on_apply(dts, acg, xact, action, scratch): """Apply the configuration""" self._log.debug("Got nsr apply (xact: %s) (action: %s)(scr: %s)", xact, action, scratch) - def handle_create_nsr(msg, restart_mode=False): + def handle_create_nsr(msg, key_pairs=None, restart_mode=False): # Handle create nsr requests """ # Do some validations if not msg.has_field("nsd"): @@ -3210,7 +3221,7 @@ class NsrDtsHandler(object): self._log.debug("Creating NetworkServiceRecord %s from nsr config %s", msg.id, msg.as_dict()) - nsr = self.nsm.create_nsr(msg, restart_mode=restart_mode) + nsr = self.nsm.create_nsr(msg, key_pairs=key_pairs, restart_mode=restart_mode) return nsr def handle_delete_nsr(msg): @@ -3241,8 +3252,11 @@ class NsrDtsHandler(object): xact, action, scratch) if action == rwdts.AppconfAction.INSTALL and xact.id is None: + key_pairs = [] + for element in self._key_pair_regh.elements: + key_pairs.append(element) for element in self._nsr_regh.elements: - nsr = handle_create_nsr(element, restart_mode=True) + nsr = handle_create_nsr(element, key_pairs, restart_mode=True) self._loop.create_task(begin_instantiation(nsr)) @@ -3256,7 +3270,8 @@ class NsrDtsHandler(object): for msg in added_msgs: if msg.id not in self._nsm.nsrs: self._log.info("Create NSR received in on_apply to instantiate NS:%s", msg.id) - nsr = handle_create_nsr(msg) + key_pairs = get_nsr_key_pairs(self._key_pair_regh, xact) + nsr = handle_create_nsr(msg,key_pairs) self._loop.create_task(begin_instantiation(nsr)) for msg in deleted_msgs: @@ -3373,6 +3388,11 @@ class NsrDtsHandler(object): flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY| rwdts.Flag.CACHE, ) + self._key_pair_regh = acg.register( + xpath=NsrDtsHandler.KEY_PAIR_XPATH, + flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY | rwdts.Flag.CACHE, + ) + class NsrOpDataDtsHandler(object): """ The network service op data DTS handler """ @@ -3792,7 +3812,7 @@ class NsManager(object): # Not calling in a separate task as this is called from a separate task yield from nsr.delete_vl_instance(vld) - def create_nsr(self, nsr_msg, restart_mode=False): + def create_nsr(self, nsr_msg, key_pairs=None,restart_mode=False): """ Create an NSR instance """ if nsr_msg.id in self._nsrs: msg = "NSR id %s already exists" % nsr_msg.id @@ -3813,10 +3833,11 @@ class NsManager(object): nsm_plugin, nsr_msg, sdn_account_name, + key_pairs, restart_mode=restart_mode ) self._nsrs[nsr_msg.id] = nsr - nsm_plugin.create_nsr(nsr_msg, nsr_msg.nsd) + nsm_plugin.create_nsr(nsr_msg, nsr_msg.nsd, key_pairs) return nsr -- 2.25.1