Add user_data_update_policy property to OS::Nova::Server
This may be set to either 'REPLACE' (default) or 'IGNORE'. This allows template authors to choose the desired behaviour when the user_data property is changed. Co-Authored-By: Steve Hardy <shardy@redhat.com> Change-Id: I3239c7252a2c329330283b86181abd52aee9e967 Closes-Bug: #1539541
This commit is contained in:
parent
edeae75de4
commit
d4188127a1
@ -56,14 +56,14 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin,
|
||||
ADMIN_USER, AVAILABILITY_ZONE, SECURITY_GROUPS, NETWORKS,
|
||||
SCHEDULER_HINTS, METADATA, USER_DATA_FORMAT, USER_DATA,
|
||||
RESERVATION_ID, CONFIG_DRIVE, DISK_CONFIG, PERSONALITY,
|
||||
ADMIN_PASS, SOFTWARE_CONFIG_TRANSPORT
|
||||
ADMIN_PASS, SOFTWARE_CONFIG_TRANSPORT, USER_DATA_UPDATE_POLICY
|
||||
) = (
|
||||
'name', 'image', 'block_device_mapping', 'block_device_mapping_v2',
|
||||
'flavor', 'flavor_update_policy', 'image_update_policy', 'key_name',
|
||||
'admin_user', 'availability_zone', 'security_groups', 'networks',
|
||||
'scheduler_hints', 'metadata', 'user_data_format', 'user_data',
|
||||
'reservation_id', 'config_drive', 'diskConfig', 'personality',
|
||||
'admin_pass', 'software_config_transport'
|
||||
'admin_pass', 'software_config_transport', 'user_data_update_policy'
|
||||
)
|
||||
|
||||
_BLOCK_DEVICE_MAPPING_KEYS = (
|
||||
@ -446,10 +446,22 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin,
|
||||
constraints.AllowedValues(_SOFTWARE_CONFIG_TRANSPORTS),
|
||||
]
|
||||
),
|
||||
USER_DATA_UPDATE_POLICY: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
_('Policy on how to apply a user_data update; either by '
|
||||
'ignorning it or by replacing the entire server.'),
|
||||
default='REPLACE',
|
||||
constraints=[
|
||||
constraints.AllowedValues(['REPLACE', 'IGNORE']),
|
||||
],
|
||||
support_status=support.SupportStatus(version='6.0.0'),
|
||||
update_allowed=True
|
||||
),
|
||||
USER_DATA: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
_('User data script to be executed by cloud-init.'),
|
||||
default=''
|
||||
default='',
|
||||
update_allowed=True
|
||||
),
|
||||
RESERVATION_ID: properties.Schema(
|
||||
properties.Schema.STRING,
|
||||
@ -1093,6 +1105,12 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin,
|
||||
if image_update_policy == 'REPLACE':
|
||||
return True
|
||||
|
||||
if self.USER_DATA in changed_properties_set:
|
||||
ud_update_policy = (
|
||||
after_props.get(self.USER_DATA_UPDATE_POLICY) or
|
||||
before_props.get(self.USER_DATA_UPDATE_POLICY))
|
||||
return ud_update_policy == 'REPLACE'
|
||||
|
||||
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||
if 'Metadata' in tmpl_diff:
|
||||
# If SOFTWARE_CONFIG user_data_format is enabled we require
|
||||
|
@ -2129,6 +2129,46 @@ class ServersTest(common.HeatTestCase):
|
||||
updater = scheduler.TaskRunner(server.update, update_template)
|
||||
self.assertRaises(exception.UpdateReplace, updater)
|
||||
|
||||
def test_server_update_server_userdata_replace(self):
|
||||
stack_name = 'update_udatrep'
|
||||
(tmpl, stack) = self._setup_test_stack(stack_name)
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||
self._mock_get_image_id_success('F17-x86_64-gold', 'image_id')
|
||||
self.m.ReplayAll()
|
||||
resource_defns = tmpl.resource_definitions(stack)
|
||||
server = servers.Server('server_update_userdata_replace',
|
||||
resource_defns['WebServer'], stack)
|
||||
|
||||
update_template = copy.deepcopy(server.t)
|
||||
update_template['Properties']['user_data'] = 'changed'
|
||||
server.action = server.CREATE
|
||||
updater = scheduler.TaskRunner(server.update, update_template)
|
||||
self.assertRaises(exception.UpdateReplace, updater)
|
||||
|
||||
def test_server_update_server_userdata_ignore(self):
|
||||
stack_name = 'update_udatignore'
|
||||
(tmpl, stack) = self._setup_test_stack(stack_name)
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||
self._mock_get_image_id_success('F17-x86_64-gold', 'image_id')
|
||||
self.m.ReplayAll()
|
||||
self.patchobject(servers.Server, 'prepare_for_replace')
|
||||
self.patchobject(servers.Server, 'check_update_complete',
|
||||
return_value=True)
|
||||
|
||||
resource_defns = tmpl.resource_definitions(stack)
|
||||
server = servers.Server('server_update_userdata_ignore',
|
||||
resource_defns['WebServer'], stack)
|
||||
|
||||
update_template = copy.deepcopy(server.t)
|
||||
update_template['Properties']['user_data'] = 'changed'
|
||||
update_template['Properties']['user_data_update_policy'] = 'IGNORE'
|
||||
server.action = server.CREATE
|
||||
scheduler.TaskRunner(server.update, update_template)()
|
||||
self.assertEqual((server.UPDATE, server.COMPLETE), server.state)
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_server_update_image_replace(self):
|
||||
stack_name = 'update_imgrep'
|
||||
(tmpl, stack) = self._setup_test_stack(stack_name)
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- The OS::Nova::Server now supports a new property user_data_update_policy,
|
||||
which may be set to either 'REPLACE' (default) or 'IGNORE' if you wish to
|
||||
allow user_data updates to be ignored on stack update. This is useful when
|
||||
managing a group of servers where changed user_data should apply to new
|
||||
servers without replacing existing servers.
|
Loading…
Reference in New Issue
Block a user