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,
|
ADMIN_USER, AVAILABILITY_ZONE, SECURITY_GROUPS, NETWORKS,
|
||||||
SCHEDULER_HINTS, METADATA, USER_DATA_FORMAT, USER_DATA,
|
SCHEDULER_HINTS, METADATA, USER_DATA_FORMAT, USER_DATA,
|
||||||
RESERVATION_ID, CONFIG_DRIVE, DISK_CONFIG, PERSONALITY,
|
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',
|
'name', 'image', 'block_device_mapping', 'block_device_mapping_v2',
|
||||||
'flavor', 'flavor_update_policy', 'image_update_policy', 'key_name',
|
'flavor', 'flavor_update_policy', 'image_update_policy', 'key_name',
|
||||||
'admin_user', 'availability_zone', 'security_groups', 'networks',
|
'admin_user', 'availability_zone', 'security_groups', 'networks',
|
||||||
'scheduler_hints', 'metadata', 'user_data_format', 'user_data',
|
'scheduler_hints', 'metadata', 'user_data_format', 'user_data',
|
||||||
'reservation_id', 'config_drive', 'diskConfig', 'personality',
|
'reservation_id', 'config_drive', 'diskConfig', 'personality',
|
||||||
'admin_pass', 'software_config_transport'
|
'admin_pass', 'software_config_transport', 'user_data_update_policy'
|
||||||
)
|
)
|
||||||
|
|
||||||
_BLOCK_DEVICE_MAPPING_KEYS = (
|
_BLOCK_DEVICE_MAPPING_KEYS = (
|
||||||
@ -446,10 +446,22 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin,
|
|||||||
constraints.AllowedValues(_SOFTWARE_CONFIG_TRANSPORTS),
|
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(
|
USER_DATA: properties.Schema(
|
||||||
properties.Schema.STRING,
|
properties.Schema.STRING,
|
||||||
_('User data script to be executed by cloud-init.'),
|
_('User data script to be executed by cloud-init.'),
|
||||||
default=''
|
default='',
|
||||||
|
update_allowed=True
|
||||||
),
|
),
|
||||||
RESERVATION_ID: properties.Schema(
|
RESERVATION_ID: properties.Schema(
|
||||||
properties.Schema.STRING,
|
properties.Schema.STRING,
|
||||||
@ -1093,6 +1105,12 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin,
|
|||||||
if image_update_policy == 'REPLACE':
|
if image_update_policy == 'REPLACE':
|
||||||
return True
|
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):
|
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||||
if 'Metadata' in tmpl_diff:
|
if 'Metadata' in tmpl_diff:
|
||||||
# If SOFTWARE_CONFIG user_data_format is enabled we require
|
# 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)
|
updater = scheduler.TaskRunner(server.update, update_template)
|
||||||
self.assertRaises(exception.UpdateReplace, updater)
|
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):
|
def test_server_update_image_replace(self):
|
||||||
stack_name = 'update_imgrep'
|
stack_name = 'update_imgrep'
|
||||||
(tmpl, stack) = self._setup_test_stack(stack_name)
|
(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