Allow overriding the instance_user per server

I have called the property 'admin_user' as the bug suggests.

Closes-bug: #1229825
Change-Id: I578ba9c0419383b34ac137e714f9cc00fe696ea3
This commit is contained in:
Angus Salkeld 2013-10-11 16:54:57 +11:00
parent 57dac72b55
commit cb2801cc7b
4 changed files with 42 additions and 6 deletions

View File

@ -122,7 +122,7 @@ def get_keypair(nova_client, key_name):
raise exception.UserKeyPairMissing(key_name=key_name) raise exception.UserKeyPairMissing(key_name=key_name)
def build_userdata(resource, userdata=None): def build_userdata(resource, userdata=None, instance_user=None):
''' '''
Build multipart data blob for CloudInit which includes user-supplied Build multipart data blob for CloudInit which includes user-supplied
Metadata, user data, and the required Heat in-instance configuration. Metadata, user data, and the required Heat in-instance configuration.
@ -131,6 +131,8 @@ def build_userdata(resource, userdata=None):
:type resource: heat.engine.Resource :type resource: heat.engine.Resource
:param userdata: user data string :param userdata: user data string
:type userdata: str or None :type userdata: str or None
:param instance_user: the user to create on the server
:type instance_user: string
:returns: multipart mime as a string :returns: multipart mime as a string
''' '''
@ -145,7 +147,7 @@ def build_userdata(resource, userdata=None):
def read_cloudinit_file(fn): def read_cloudinit_file(fn):
data = pkgutil.get_data('heat', 'cloudinit/%s' % fn) data = pkgutil.get_data('heat', 'cloudinit/%s' % fn)
data = data.replace('@INSTANCE_USER@', data = data.replace('@INSTANCE_USER@',
cfg.CONF.instance_user) instance_user or cfg.CONF.instance_user)
return data return data
attachments = [(read_cloudinit_file('config'), 'cloud-config'), attachments = [(read_cloudinit_file('config'), 'cloud-config'),

View File

@ -13,6 +13,10 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from oslo.config import cfg
cfg.CONF.import_opt('instance_user', 'heat.common.config')
from heat.common import exception from heat.common import exception
from heat.engine import clients from heat.engine import clients
from heat.engine import scheduler from heat.engine import scheduler
@ -95,6 +99,12 @@ class Server(resource.Resource):
'key_name': { 'key_name': {
'Type': 'String', 'Type': 'String',
'Description': _('Name of keypair to inject into the server')}, 'Description': _('Name of keypair to inject into the server')},
'admin_user': {
'Type': 'String',
'Default': cfg.CONF.instance_user,
'Description': _('Name of the administrative user to use '
' on the server')},
'availability_zone': { 'availability_zone': {
'Type': 'String', 'Type': 'String',
'Description': _('Name of the availability zone for server ' 'Description': _('Name of the availability zone for server '
@ -171,7 +181,8 @@ class Server(resource.Resource):
def get_mime_string(self, userdata): def get_mime_string(self, userdata):
if not self.mime_string: if not self.mime_string:
self.mime_string = nova_utils.build_userdata(self, userdata) self.mime_string = nova_utils.build_userdata(
self, userdata, instance_user=self.properties['admin_user'])
return self.mime_string return self.mime_string
def physical_resource_name(self): def physical_resource_name(self):

View File

@ -14,12 +14,15 @@
# under the License. # under the License.
"""Tests for :module:'heat.engine.resources.nova_utls'.""" """Tests for :module:'heat.engine.resources.nova_utls'."""
import testscenarios
import uuid import uuid
from heat.common import exception from heat.common import exception
from heat.engine.resources import nova_utils from heat.engine.resources import nova_utils
from heat.tests.common import HeatTestCase from heat.tests.common import HeatTestCase
load_tests = testscenarios.load_tests_apply_scenarios
class NovaUtilsTests(HeatTestCase): class NovaUtilsTests(HeatTestCase):
""" """
@ -84,19 +87,38 @@ class NovaUtilsTests(HeatTestCase):
self.nova_client, 'notakey') self.nova_client, 'notakey')
self.m.VerifyAll() self.m.VerifyAll()
class NovaUtilsUserdataTests(HeatTestCase):
scenarios = [
('no_conf_no_prop', dict(
conf_user='ec2-user', instance_user=None, expect='ec2-user')),
('no_conf_prop', dict(
conf_user='ec2-user', instance_user='fruity', expect='fruity')),
('conf_no_prop', dict(
conf_user='nutty', instance_user=None, expect='nutty')),
('conf_prop', dict(
conf_user='nutty', instance_user='fruity', expect='fruity')),
]
def setUp(self):
super(NovaUtilsUserdataTests, self).setUp()
self.nova_client = self.m.CreateMockAnything()
def test_build_userdata(self): def test_build_userdata(self):
"""Tests the build_userdata function.""" """Tests the build_userdata function."""
resource = self.m.CreateMockAnything() resource = self.m.CreateMockAnything()
resource.t = {} resource.t = {}
self.m.StubOutWithMock(nova_utils.cfg, 'CONF') self.m.StubOutWithMock(nova_utils.cfg, 'CONF')
cnf = nova_utils.cfg.CONF cnf = nova_utils.cfg.CONF
cnf.instance_user = 'testuser' cnf.instance_user = self.conf_user
cnf.heat_metadata_server_url = 'http://server.test:123' cnf.heat_metadata_server_url = 'http://server.test:123'
cnf.heat_watch_server_url = 'http://server.test:345' cnf.heat_watch_server_url = 'http://server.test:345'
cnf.instance_connection_is_secure = False cnf.instance_connection_is_secure = False
cnf.instance_connection_https_validate_certificates = False cnf.instance_connection_https_validate_certificates = False
self.m.ReplayAll() self.m.ReplayAll()
data = nova_utils.build_userdata(resource) data = nova_utils.build_userdata(resource,
instance_user=self.instance_user)
self.assertTrue("Content-Type: text/cloud-config;" in data) self.assertTrue("Content-Type: text/cloud-config;" in data)
self.assertTrue("Content-Type: text/cloud-boothook;" in data) self.assertTrue("Content-Type: text/cloud-boothook;" in data)
self.assertTrue("Content-Type: text/part-handler;" in data) self.assertTrue("Content-Type: text/part-handler;" in data)
@ -105,5 +127,5 @@ class NovaUtilsTests(HeatTestCase):
self.assertTrue("http://server.test:345" in data) self.assertTrue("http://server.test:345" in data)
self.assertTrue("http://server.test:123" in data) self.assertTrue("http://server.test:123" in data)
self.assertTrue("[Boto]" in data) self.assertTrue("[Boto]" in data)
self.assertTrue('testuser' in data) self.assertTrue(self.expect in data)
self.m.VerifyAll() self.m.VerifyAll()

View File

@ -10,6 +10,7 @@ mock>=1.0
mox>=0.5.3 mox>=0.5.3
testtools>=0.9.32 testtools>=0.9.32
testrepository>=0.0.17 testrepository>=0.0.17
testscenarios>=0.4
python-glanceclient>=0.9.0 python-glanceclient>=0.9.0
sphinx>=1.1.2 sphinx>=1.1.2
oslo.sphinx oslo.sphinx