From 0a399fd97193f994071ac1fac7a040ccd1caee16 Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Tue, 12 Aug 2014 13:47:38 -0500 Subject: [PATCH 1/3] Support config_drive and user_data in rax_scaling_group --- cloud/rax_scaling_group.py | 46 +++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/cloud/rax_scaling_group.py b/cloud/rax_scaling_group.py index d884d3c1303..16be9ac4c0f 100644 --- a/cloud/rax_scaling_group.py +++ b/cloud/rax_scaling_group.py @@ -24,6 +24,14 @@ description: - Manipulate Rackspace Cloud Autoscale Groups version_added: 1.7 options: + config_drive: + description: + - Attach read-only configuration drive to server as label config-2 + default: no + choices: + - "yes" + - "no" + version_added: 1.8 cooldown: description: - The period of time, in seconds, that must pass before any scaling can @@ -92,6 +100,11 @@ options: - present - absent default: present + user_data: + description: + - Data to be uploaded to the servers config drive. This option implies + I(config_drive). Can be a file path or a string + version_added: 1.8 author: Matt Martz extends_documentation_fragment: rackspace ''' @@ -128,17 +141,27 @@ except ImportError: def rax_asg(module, cooldown=300, disk_config=None, files={}, flavor=None, image=None, key_name=None, loadbalancers=[], meta={}, min_entities=0, max_entities=0, name=None, networks=[], - server_name=None, state='present'): + server_name=None, state='present', user_data=None, + config_drive=False): changed = False au = pyrax.autoscale - cnw = pyrax.cloud_networks - cs = pyrax.cloudservers - if not au or not cnw or not cs: + if not au: module.fail_json(msg='Failed to instantiate clients. This ' 'typically indicates an invalid region or an ' 'incorrectly capitalized region name.') + if user_data: + config_drive = True + + if user_data and os.path.isfile(user_data): + try: + f = open(user_data) + user_data = f.read() + f.close() + except Exception, e: + module.fail_json(msg='Failed to load %s' % user_data) + if state == 'present': # Normalize and ensure all metadata values are strings if meta: @@ -204,7 +227,8 @@ def rax_asg(module, cooldown=300, disk_config=None, files={}, flavor=None, flavor=flavor, disk_config=disk_config, metadata=meta, personality=files, networks=nics, load_balancers=lbs, - key_name=key_name) + key_name=key_name, config_drive=config_drive, + user_data=user_data) changed = True except Exception, e: module.fail_json(msg='%s' % e.message) @@ -256,6 +280,12 @@ def rax_asg(module, cooldown=300, disk_config=None, files={}, flavor=None, if key_name != lc.get('key_name'): lc_args['key_name'] = key_name + if config_drive != lc.get('config_drive'): + lc_args['config_drive'] = config_drive + + if user_data != lc.get('user_data'): + lc_args['user_data'] = user_data + if lc_args: # Work around for https://github.com/rackspace/pyrax/pull/389 if 'flavor' not in lc_args: @@ -284,6 +314,7 @@ def main(): argument_spec = rax_argument_spec() argument_spec.update( dict( + config_drive=dict(default=False, type='bool'), cooldown=dict(type='int', default=300), disk_config=dict(choices=['auto', 'manual']), files=dict(type='list', default=[]), @@ -298,6 +329,7 @@ def main(): networks=dict(type='list', default=['public', 'private']), server_name=dict(required=True), state=dict(default='present', choices=['present', 'absent']), + user_data=dict(no_log=True), ) ) @@ -309,6 +341,7 @@ def main(): if not HAS_PYRAX: module.fail_json(msg='pyrax is required for this module') + config_drive = module.params.get('config_drive') cooldown = module.params.get('cooldown') disk_config = module.params.get('disk_config') if disk_config: @@ -325,6 +358,7 @@ def main(): networks = module.params.get('networks') server_name = module.params.get('server_name') state = module.params.get('state') + user_data = module.params.get('user_data') if not 0 <= min_entities <= 1000 or not 0 <= max_entities <= 1000: module.fail_json(msg='min_entities and max_entities must be an ' @@ -340,7 +374,7 @@ def main(): key_name=key_name, loadbalancers=loadbalancers, min_entities=min_entities, max_entities=max_entities, name=name, networks=networks, server_name=server_name, - state=state) + state=state, config_drive=config_drive, user_data=user_data) # import module snippets From 924bff94817302a003e7bec64594fcb4b7c6bb3c Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Tue, 2 Sep 2014 14:46:31 -0500 Subject: [PATCH 2/3] Ensure that files is the right type, and that we send the formatted personality var --- cloud/rax_scaling_group.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloud/rax_scaling_group.py b/cloud/rax_scaling_group.py index 16be9ac4c0f..3b7fa8f4aca 100644 --- a/cloud/rax_scaling_group.py +++ b/cloud/rax_scaling_group.py @@ -225,7 +225,7 @@ def rax_asg(module, cooldown=300, disk_config=None, files={}, flavor=None, launch_config_type='launch_server', server_name=server_name, image=image, flavor=flavor, disk_config=disk_config, - metadata=meta, personality=files, + metadata=meta, personality=personality, networks=nics, load_balancers=lbs, key_name=key_name, config_drive=config_drive, user_data=user_data) @@ -317,7 +317,7 @@ def main(): config_drive=dict(default=False, type='bool'), cooldown=dict(type='int', default=300), disk_config=dict(choices=['auto', 'manual']), - files=dict(type='list', default=[]), + files=dict(type='dict', default={}), flavor=dict(required=True), image=dict(required=True), key_name=dict(), From fbadfd590298097545cef147bfac55a70a019c5e Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Tue, 2 Sep 2014 14:47:44 -0500 Subject: [PATCH 3/3] Fix determination if a few configurations change in the launch config --- cloud/rax_scaling_group.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/cloud/rax_scaling_group.py b/cloud/rax_scaling_group.py index 3b7fa8f4aca..dcd8dbbfeaa 100644 --- a/cloud/rax_scaling_group.py +++ b/cloud/rax_scaling_group.py @@ -131,6 +131,8 @@ EXAMPLES = ''' register: asg ''' +import base64 + try: import pyrax HAS_PYRAX = True @@ -261,14 +263,23 @@ def rax_asg(module, cooldown=300, disk_config=None, files={}, flavor=None, if flavor != lc.get('flavor'): lc_args['flavor'] = flavor - if disk_config != lc.get('disk_config'): + disk_config = disk_config or 'AUTO' + if ((disk_config or lc.get('disk_config')) and + disk_config != lc.get('disk_config')): lc_args['disk_config'] = disk_config - if meta != lc.get('metadata'): + if (meta or lc.get('meta')) and meta != lc.get('metadata'): lc_args['metadata'] = meta - if files != lc.get('personality'): - lc_args['personality'] = files + test_personality = [] + for p in personality: + test_personality.append({ + 'path': p['path'], + 'contents': base64.b64encode(p['contents']) + }) + if ((test_personality or lc.get('personality')) and + test_personality != lc.get('personality')): + lc_args['personality'] = personality if nics != lc.get('networks'): lc_args['networks'] = nics @@ -283,7 +294,7 @@ def rax_asg(module, cooldown=300, disk_config=None, files={}, flavor=None, if config_drive != lc.get('config_drive'): lc_args['config_drive'] = config_drive - if user_data != lc.get('user_data'): + if base64.b64encode(user_data) != lc.get('user_data'): lc_args['user_data'] = user_data if lc_args: