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:
parent
57dac72b55
commit
cb2801cc7b
|
@ -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'),
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue