Merge "Inject guest conf files to configurable location"
This commit is contained in:
commit
ee4b194a53
@ -1,4 +1,4 @@
|
||||
These conf files are read and used by the guest to provide extra
|
||||
information to the guest. The first example of this is the
|
||||
guest_info which will have the uuid of the instance so that
|
||||
guest_info.conf which will have the uuid of the instance so that
|
||||
the guest can report back things to the infra.
|
||||
|
@ -1 +0,0 @@
|
||||
# Arbitrary information that the guest needs to work
|
1
etc/trove/conf.d/guest_info.conf
Normal file
1
etc/trove/conf.d/guest_info.conf
Normal file
@ -0,0 +1 @@
|
||||
# Guest-specific information injected by the taskmanager
|
@ -194,7 +194,11 @@ pydev_debug = disabled
|
||||
#pydev_path = <path>
|
||||
|
||||
# ================= Guestagent related ========================
|
||||
#guest_config = $pybasedir/etc/trove/trove-guestagent.conf.sample
|
||||
#guest_config = /etc/trove/trove-guestagent.conf
|
||||
# Use 'guest_info = /etc/guest_info' for pre-Kilo compatibility
|
||||
#guest_info = guest_info.conf
|
||||
# Use 'injected_config_location = /etc/trove' for pre-Kilo compatibility
|
||||
#injected_config_location = /etc/trove/conf.d
|
||||
#cloudinit_location = /etc/trove/cloudinit
|
||||
|
||||
# ================= Security groups related ========================
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright 2011 OpenStack Foundation
|
||||
# copyright 2011 OpenStack Foundation
|
||||
# Copyright 2014 Rackspace Hosting
|
||||
# All Rights Reserved.
|
||||
#
|
||||
@ -342,9 +342,18 @@ common_opts = [
|
||||
'expression.'),
|
||||
cfg.StrOpt('cloudinit_location', default='/etc/trove/cloudinit',
|
||||
help='Path to folder with cloudinit scripts.'),
|
||||
cfg.StrOpt('injected_config_location', default='/etc/trove/conf.d',
|
||||
help='Path to folder on the Guest where config files will be '
|
||||
'injected during instance creation.'),
|
||||
cfg.StrOpt('guest_config',
|
||||
default='$pybasedir/etc/trove/trove-guestagent.conf.sample',
|
||||
help='Path to the Guest Agent config file.'),
|
||||
default='/etc/trove/trove-guestagent.conf',
|
||||
help='Path to the Guest Agent config file to be injected '
|
||||
'during instance creation.'),
|
||||
cfg.StrOpt('guest_info',
|
||||
default='guest_info.conf',
|
||||
help='The guest info filename found in the injected config '
|
||||
'location. If a full path is specified then it will '
|
||||
'be used as the path to the guest info file'),
|
||||
cfg.DictOpt('datastore_registry_ext', default=dict(),
|
||||
help='Extension for default datastore managers. '
|
||||
'Allows the use of custom managers for each of '
|
||||
|
@ -217,6 +217,32 @@ class ClusterTasks(Cluster):
|
||||
|
||||
|
||||
class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
|
||||
def _get_injected_files(self, datastore_manager):
|
||||
injected_config_location = CONF.get('injected_config_location')
|
||||
guest_info = CONF.get('guest_info')
|
||||
|
||||
if ('/' in guest_info):
|
||||
# Set guest_info_file to exactly guest_info from the conf file.
|
||||
# This should be /etc/guest_info for pre-Kilo compatibility.
|
||||
guest_info_file = guest_info
|
||||
else:
|
||||
guest_info_file = os.path.join(injected_config_location,
|
||||
guest_info)
|
||||
|
||||
files = {guest_info_file: (
|
||||
"[DEFAULT]\n"
|
||||
"guest_id=%s\n"
|
||||
"datastore_manager=%s\n"
|
||||
"tenant_id=%s\n"
|
||||
% (self.id, datastore_manager, self.tenant_id))}
|
||||
|
||||
if os.path.isfile(CONF.get('guest_config')):
|
||||
with open(CONF.get('guest_config'), "r") as f:
|
||||
files[os.path.join(injected_config_location,
|
||||
"trove-guestagent.conf")] = f.read()
|
||||
|
||||
return files
|
||||
|
||||
def create_instance(self, flavor, image_id, databases, users,
|
||||
datastore_manager, packages, volume_size,
|
||||
backup_id, availability_zone, root_password, nics,
|
||||
@ -242,6 +268,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
|
||||
LOG.debug("Successfully created security group for "
|
||||
"instance: %s" % self.id)
|
||||
|
||||
files = self._get_injected_files(datastore_manager)
|
||||
|
||||
if use_heat:
|
||||
volume_info = self._create_server_volume_heat(
|
||||
flavor,
|
||||
@ -249,7 +277,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
|
||||
datastore_manager,
|
||||
volume_size,
|
||||
availability_zone,
|
||||
nics)
|
||||
nics,
|
||||
files)
|
||||
elif use_nova_server_volume:
|
||||
volume_info = self._create_server_volume(
|
||||
flavor['id'],
|
||||
@ -258,7 +287,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
|
||||
datastore_manager,
|
||||
volume_size,
|
||||
availability_zone,
|
||||
nics)
|
||||
nics,
|
||||
files)
|
||||
else:
|
||||
volume_info = self._create_server_volume_individually(
|
||||
flavor['id'],
|
||||
@ -267,7 +297,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
|
||||
datastore_manager,
|
||||
volume_size,
|
||||
availability_zone,
|
||||
nics)
|
||||
nics,
|
||||
files)
|
||||
|
||||
config = self._render_config(flavor)
|
||||
config_overrides = self._render_override_config(flavor,
|
||||
@ -454,11 +485,10 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
|
||||
|
||||
def _create_server_volume(self, flavor_id, image_id, security_groups,
|
||||
datastore_manager, volume_size,
|
||||
availability_zone, nics):
|
||||
availability_zone, nics, files):
|
||||
LOG.debug("Begin _create_server_volume for id: %s" % self.id)
|
||||
try:
|
||||
files, userdata = self._prepare_file_and_userdata(
|
||||
datastore_manager)
|
||||
userdata = self._prepare_userdata(datastore_manager)
|
||||
name = self.hostname or self.name
|
||||
volume_desc = ("datastore volume for %s" % self.id)
|
||||
volume_name = ("datastore-%s" % self.id)
|
||||
@ -508,10 +538,9 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
|
||||
return final
|
||||
|
||||
def _create_server_volume_heat(self, flavor, image_id,
|
||||
datastore_manager,
|
||||
volume_size, availability_zone,
|
||||
nics):
|
||||
LOG.debug("begin _create_server_volume_heat for id: %s" % self.id)
|
||||
datastore_manager, volume_size,
|
||||
availability_zone, nics, files):
|
||||
LOG.debug("Begin _create_server_volume_heat for id: %s" % self.id)
|
||||
try:
|
||||
client = create_heat_client(self.context)
|
||||
tcp_rules_mapping_list = self._build_sg_rules_mapping(CONF.get(
|
||||
@ -526,7 +555,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
|
||||
ifaces=ifaces, ports=ports,
|
||||
tcp_rules=tcp_rules_mapping_list,
|
||||
udp_rules=udp_ports_mapping_list,
|
||||
datastore_manager=datastore_manager)
|
||||
datastore_manager=datastore_manager,
|
||||
files=files)
|
||||
try:
|
||||
heat_template = heat_template_unicode.encode('utf-8')
|
||||
except UnicodeEncodeError:
|
||||
@ -604,8 +634,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
|
||||
|
||||
def _create_server_volume_individually(self, flavor_id, image_id,
|
||||
security_groups, datastore_manager,
|
||||
volume_size,
|
||||
availability_zone, nics):
|
||||
volume_size, availability_zone,
|
||||
nics, files):
|
||||
LOG.debug("Begin _create_server_volume_individually for id: %s" %
|
||||
self.id)
|
||||
server = None
|
||||
@ -616,7 +646,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
|
||||
server = self._create_server(flavor_id, image_id, security_groups,
|
||||
datastore_manager,
|
||||
block_device_mapping,
|
||||
availability_zone, nics)
|
||||
availability_zone, nics, files)
|
||||
server_id = server.id
|
||||
# Save server ID.
|
||||
self.update_db(compute_instance_id=server_id)
|
||||
@ -707,28 +737,19 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
|
||||
'volumes': created_volumes}
|
||||
return volume_info
|
||||
|
||||
def _prepare_file_and_userdata(self, datastore_manager):
|
||||
files = {"/etc/guest_info": ("[DEFAULT]\nguest_id=%s\n"
|
||||
"datastore_manager=%s\n"
|
||||
"tenant_id=%s\n" %
|
||||
(self.id, datastore_manager,
|
||||
self.tenant_id))}
|
||||
if os.path.isfile(CONF.get('guest_config')):
|
||||
with open(CONF.get('guest_config'), "r") as f:
|
||||
files["/etc/trove-guestagent.conf"] = f.read()
|
||||
def _prepare_userdata(self, datastore_manager):
|
||||
userdata = None
|
||||
cloudinit = os.path.join(CONF.get('cloudinit_location'),
|
||||
"%s.cloudinit" % datastore_manager)
|
||||
if os.path.isfile(cloudinit):
|
||||
with open(cloudinit, "r") as f:
|
||||
userdata = f.read()
|
||||
return files, userdata
|
||||
return userdata
|
||||
|
||||
def _create_server(self, flavor_id, image_id, security_groups,
|
||||
datastore_manager, block_device_mapping,
|
||||
availability_zone, nics):
|
||||
files, userdata = self._prepare_file_and_userdata(
|
||||
datastore_manager)
|
||||
availability_zone, nics, files={}):
|
||||
userdata = self._prepare_userdata(datastore_manager)
|
||||
name = self.hostname or self.name
|
||||
bdmap = block_device_mapping
|
||||
config_drive = CONF.use_nova_server_config_drive
|
||||
|
@ -34,16 +34,14 @@ Resources:
|
||||
AWS::CloudFormation::Init:
|
||||
config:
|
||||
files:
|
||||
/etc/guest_info:
|
||||
content:
|
||||
Fn::Join:
|
||||
- ''
|
||||
- ["[DEFAULT]\nguest_id=", {Ref: InstanceId},
|
||||
"\ndatastore_manager=", {Ref: DatastoreManager},
|
||||
"\ntenant_id=", {Ref: TenantId}]
|
||||
{% for file, content in files.iteritems() %}
|
||||
{{ file }}:
|
||||
content: |
|
||||
{{ content | indent(16) }}
|
||||
mode: '000644'
|
||||
owner: root
|
||||
group: root
|
||||
{% endfor %}
|
||||
Properties:
|
||||
ImageId: {Ref: ImageId}
|
||||
InstanceType: {Ref: Flavor}
|
||||
|
@ -168,7 +168,8 @@ class HeatTemplateLoadTest(testtools.TestCase):
|
||||
volume_support=True,
|
||||
ifaces=[], ports=[],
|
||||
tcp_rules=tcp_rules,
|
||||
udp_rules=[])
|
||||
udp_rules=[],
|
||||
files={})
|
||||
self.assertIsNotNone(output)
|
||||
self.assertIn('FromPort: "3306"', output)
|
||||
self.assertIn('ToPort: "3309"', output)
|
||||
@ -182,7 +183,8 @@ class HeatTemplateLoadTest(testtools.TestCase):
|
||||
volume_support=True,
|
||||
ifaces=[], ports=[],
|
||||
tcp_rules=[],
|
||||
udp_rules=[])
|
||||
udp_rules=[],
|
||||
files={})
|
||||
self.assertIsNotNone(output)
|
||||
self.assertNotIn('- IpProtocol: "tcp"', output)
|
||||
self.assertNotIn('- IpProtocol: "udp"', output)
|
||||
|
@ -226,16 +226,48 @@ class FreshInstanceTasksTest(testtools.TestCase):
|
||||
def fake_conf_getter(*args, **kwargs):
|
||||
if args[0] == 'guest_config':
|
||||
return self.guestconfig
|
||||
if args[0] == 'guest_info':
|
||||
return 'guest_info.conf'
|
||||
if args[0] == 'injected_config_location':
|
||||
return '/etc/trove/conf.d'
|
||||
else:
|
||||
return ''
|
||||
|
||||
mock_conf.get.side_effect = fake_conf_getter
|
||||
# execute
|
||||
server = self.freshinstancetasks._create_server(
|
||||
None, None, None, "test", None, None, None)
|
||||
files = self.freshinstancetasks._get_injected_files("test")
|
||||
# verify
|
||||
self.assertTrue('/etc/trove-guestagent.conf' in server.files)
|
||||
self.assertEqual(server.files['/etc/trove-guestagent.conf'],
|
||||
self.guestconfig_content)
|
||||
self.assertTrue(
|
||||
'/etc/trove/conf.d/guest_info.conf' in files)
|
||||
self.assertTrue(
|
||||
'/etc/trove/conf.d/trove-guestagent.conf' in files)
|
||||
self.assertEqual(
|
||||
files['/etc/trove/conf.d/trove-guestagent.conf'],
|
||||
self.guestconfig_content)
|
||||
|
||||
@patch('trove.taskmanager.models.CONF')
|
||||
def test_create_instance_guestconfig_compat(self, mock_conf):
|
||||
def fake_conf_getter(*args, **kwargs):
|
||||
if args[0] == 'guest_config':
|
||||
return self.guestconfig
|
||||
if args[0] == 'guest_info':
|
||||
return '/etc/guest_info'
|
||||
if args[0] == 'injected_config_location':
|
||||
return '/etc'
|
||||
else:
|
||||
return ''
|
||||
|
||||
mock_conf.get.side_effect = fake_conf_getter
|
||||
# execute
|
||||
files = self.freshinstancetasks._get_injected_files("test")
|
||||
# verify
|
||||
self.assertTrue(
|
||||
'/etc/guest_info' in files)
|
||||
self.assertTrue(
|
||||
'/etc/trove-guestagent.conf' in files)
|
||||
self.assertEqual(
|
||||
files['/etc/trove-guestagent.conf'],
|
||||
self.guestconfig_content)
|
||||
|
||||
@patch('trove.taskmanager.models.CONF')
|
||||
def test_create_instance_with_az_kwarg(self, mock_conf):
|
||||
|
Loading…
x
Reference in New Issue
Block a user