# HG changeset patch # User Elena Ouyang # Date 1436389224 25200 # Node ID 0aecdc531b7742a7f27354b9b2d8777c2de5c23f # Parent c1143cad49f21bf800acb56ce5542b3145efcb1d 19774239 Nova should support setting the Admin Password diff -r c1143cad49f2 -r 0aecdc531b77 components/openstack/horizon/files/local_settings.py --- a/components/openstack/horizon/files/local_settings.py Wed Jul 22 17:20:10 2015 -0700 +++ b/components/openstack/horizon/files/local_settings.py Wed Jul 08 14:00:24 2015 -0700 @@ -175,7 +175,7 @@ #Setting this to True, will add a new "Retrieve Password" action on instance, #allowing Admin session password retrieval/decryption. -#OPENSTACK_ENABLE_PASSWORD_RETRIEVE = False +OPENSTACK_ENABLE_PASSWORD_RETRIEVE = True # The Xen Hypervisor has the ability to set the mount point for volumes # attached to instances (other Hypervisors currently do not). Setting @@ -183,7 +183,7 @@ # from the UI. OPENSTACK_HYPERVISOR_FEATURES = { 'can_set_mount_point': False, - 'can_set_password': False, + 'can_set_password': True, } # The OPENSTACK_CINDER_FEATURES settings can be used to enable optional diff -r c1143cad49f2 -r 0aecdc531b77 components/openstack/horizon/files/overrides.py --- a/components/openstack/horizon/files/overrides.py Wed Jul 22 17:20:10 2015 -0700 +++ b/components/openstack/horizon/files/overrides.py Wed Jul 08 14:00:24 2015 -0700 @@ -96,6 +96,7 @@ project_tables.AssociateIP, project_tables.SimpleDisassociateIP, project_tables.EditInstance, + project_tables.DecryptInstancePassword, project_tables.ConsoleLink, project_tables.LogLink, project_tables.SoftRebootInstance, diff -r c1143cad49f2 -r 0aecdc531b77 components/openstack/nova/files/solariszones/driver.py --- a/components/openstack/nova/files/solariszones/driver.py Wed Jul 22 17:20:10 2015 -0700 +++ b/components/openstack/nova/files/solariszones/driver.py Wed Jul 08 14:00:24 2015 -0700 @@ -19,6 +19,7 @@ Driver for Solaris Zones (nee Containers): """ +import base64 import glob import os import platform @@ -39,13 +40,16 @@ from eventlet import greenthread from lxml import etree from oslo_config import cfg - +from passlib.hash import sha256_crypt + +from nova.api.metadata import password from nova.compute import power_state from nova.compute import task_states from nova.compute import vm_states from nova.console import type as ctype from nova import conductor from nova import context as nova_context +from nova import crypto from nova import exception from nova.i18n import _ from nova.image import glance @@ -1046,7 +1050,7 @@ with ZoneConfig(zone) as zc: zc.setprop('global', 'tenant', tenant_id) - def _verify_sysconfig(self, sc_dir, instance): + def _verify_sysconfig(self, sc_dir, instance, admin_password=None): """verify the SC profile(s) passed in contain an entry for system/config-user to configure the root account. If an SSH key is specified, configure root's profile to use it. @@ -1058,6 +1062,11 @@ hostname_needed = True sshkey = instance.get('key_data') name = instance.get('display_name') + encrypted_password = None + + # encrypt admin password, using SHA-256 as default + if admin_password is not None: + encrypted_password = sha256_crypt.encrypt(admin_password) # find all XML files in sc_dir for root, dirs, files in os.walk(sc_dir): @@ -1085,12 +1094,22 @@ if root_account_needed: fp = os.path.join(sc_dir, 'config-root.xml') - if sshkey is not None: - # set up the root account as 'normal' with no expiration and - # an ssh key - tree = sysconfig.create_default_root_account(sshkey=sshkey) + if admin_password is not None and sshkey is not None: + # store password for horizon retrieval + ctxt = nova_context.get_admin_context() + enc = crypto.ssh_encrypt_text(sshkey, admin_password) + instance.system_metadata.update( + password.convert_password(ctxt, base64.b64encode(enc))) + instance.save() + + if encrypted_password is not None or sshkey is not None: + # set up the root account as 'normal' with no expiration, + # an ssh key, and a root password + tree = sysconfig.create_default_root_account( + sshkey=sshkey, password=encrypted_password) else: - # set up the root account as 'normal' but to expire immediately + # sets up root account with expiration if sshkey is None + # and password is none tree = sysconfig.create_default_root_account(expire='0') sysconfig.create_sc_profile(fp, tree) @@ -1104,8 +1123,8 @@ fp = os.path.join(sc_dir, 'hostname.xml') sysconfig.create_sc_profile(fp, sysconfig.create_hostname(name)) - def _create_config(self, context, instance, network_info, - connection_info, extra_specs, sc_dir): + def _create_config(self, context, instance, network_info, connection_info, + extra_specs, sc_dir, admin_password=None): """Create a new Solaris Zone configuration.""" name = instance['name'] if self._get_zone_by_name(name) is not None: @@ -1127,7 +1146,7 @@ elif os.path.isdir(sc_profile): shutil.copytree(sc_profile, os.path.join(sc_dir, 'sysconfig')) - self._verify_sysconfig(sc_dir, instance) + self._verify_sysconfig(sc_dir, instance, admin_password) zonemanager = self.rad_connection.get_object(zonemgr.ZoneManager()) try: @@ -1459,8 +1478,9 @@ LOG.debug(_("creating zone configuration for '%s' (%s)") % (name, instance['display_name'])) - self._create_config(context, instance, network_info, - connection_info, extra_specs, sc_dir) + + self._create_config(context, instance, network_info, connection_info, + extra_specs, sc_dir, admin_password) try: self._install(instance, image, extra_specs, sc_dir) self._power_on(instance) diff -r c1143cad49f2 -r 0aecdc531b77 components/openstack/nova/files/solariszones/sysconfig.py --- a/components/openstack/nova/files/solariszones/sysconfig.py Wed Jul 22 17:20:10 2015 -0700 +++ b/components/openstack/nova/files/solariszones/sysconfig.py Wed Jul 08 14:00:24 2015 -0700 @@ -152,7 +152,7 @@ return svcbundle -def create_default_root_account(expire=None, sshkey=None): +def create_default_root_account(expire=None, sshkey=None, password=None): """ return an etree object representing the root account """ svcbundle = etree.Element("service_bundle", type="profile", @@ -163,11 +163,16 @@ name="default") root_pg = etree.SubElement(instance, "property_group", type="application", name="root_account") - etree.SubElement(root_pg, "propval", type="astring", name="password", - value="NP") etree.SubElement(root_pg, "propval", type="astring", name="type", value="normal") + if password is not None: + etree.SubElement(root_pg, "propval", type="astring", name="password", + value=password) + else: + etree.SubElement(root_pg, "propval", type="astring", name="password", + value='NP') + if expire is not None: etree.SubElement(root_pg, "propval", type="astring", name="expire", value=expire)