diff --git a/salt/cloud/clouds/nova.py b/salt/cloud/clouds/nova.py index ddcc7a6ce1..5fda980240 100644 --- a/salt/cloud/clouds/nova.py +++ b/salt/cloud/clouds/nova.py @@ -727,7 +727,7 @@ def avail_sizes(): return conn.flavor_list() -def list_nodes(call=None): +def list_nodes(call=None, **kwargs): ''' Return a list of the VMs that in this location ''' diff --git a/salt/modules/cloud.py b/salt/modules/cloud.py index 2d867459f3..58e4eeb6b5 100644 --- a/salt/modules/cloud.py +++ b/salt/modules/cloud.py @@ -201,6 +201,22 @@ def create(provider, names, **kwargs): return info +def volume_list(provider): + ''' + List block storage volumes + + CLI Example: + + .. code-block:: bash + + salt minionname cloud.volume_list my-nova + + ''' + client = _get_client() + info = client.volume_action(provider, action='list') + return info + + def volume_delete(provider, names, **kwargs): ''' Delete volume @@ -209,7 +225,7 @@ def volume_delete(provider, names, **kwargs): .. code-block:: bash - salt minionname cloud.volume_delete myblock + salt minionname cloud.volume_delete my-nova myblock ''' client = _get_client() @@ -225,7 +241,8 @@ def volume_create(provider, names, **kwargs): .. code-block:: bash - salt minionname cloud.volume_create mynova myblock size=100 voltype=SSD + salt minionname cloud.volume_create my-nova myblock size=100 \ + voltype=SSD ''' client = _get_client() @@ -241,7 +258,8 @@ def volume_attach(provider, names, **kwargs): .. code-block:: bash - salt minionname cloud.volume_attach myblock server_name=myserver \ + salt minionname cloud.volume_attach my-nova myblock \ + server_name=myserver \ device='/dev/xvdf' ''' @@ -258,7 +276,8 @@ def volume_detach(provider, names, **kwargs): .. code-block:: bash - salt minionname cloud.volume_detach myblock server_name=myserver + salt minionname cloud.volume_detach my-nova myblock \ + server_name=myserver ''' client = _get_client() diff --git a/salt/states/cloud.py b/salt/states/cloud.py index 87f8cee4f0..4baaf6aa41 100644 --- a/salt/states/cloud.py +++ b/salt/states/cloud.py @@ -25,6 +25,20 @@ def __virtual__(): return 'cloud' if 'cloud.profile' in __salt__ else False +def _check_name(name): + ret = {'name': name, + 'changes': {}, + 'result': None, + 'comment': ''} + if suc.check_name(name, 'a-zA-Z0-9._-'): + ret['comment'] = 'Invalid characters in name.' + ret['result'] = False + return ret + else: + ret['result'] = True + return ret + + def _valid(name, comment='', changes=None): if not changes: changes = {} @@ -263,3 +277,91 @@ def profile(name, profile, onlyif=None, unless=None, **kwargs): profile, ) return ret + + +def volume_exists(name, provider=None, **kwargs): + ''' + Check that a block volume exists. + ''' + ret = _check_name(name) + if not ret['result']: + return ret + + volume = __salt__['cloud.volume_list'](provider=provider)[name] + + if volume: + ret['comment'] = 'Volume exists: {0}'.format(name) + ret['result'] = True + return ret + elif __opts__['test']: + ret['comment'] = 'Volume {0} will be created.'.format(name) + ret['result'] = None + return ret + + response = __salt__['cloud.volume_create']( + name=name, + profile=profile, + **kwargs + ) + if response: + ret['result'] = True + ret['comment'] = 'Volume {0} was created'.format(name) + ret['changes'] = {'old': None, 'new': response} + else: + ret['result'] = False + ret['comment'] = 'Volume {0} failed to create.'.format(name) + return ret + + +def volume_attached(name, server_name, provider=None, **kwargs): + ''' + Check if a block volume is attached. + ''' + ret = _check_name(name) + if not ret['result']: + return ret + + ret = _check_name(server_name) + if not ret['result']: + return ret + + volume = __salt__['cloud.volume_list'](provider=provider)[name] + server = __salt__['cloud.action']( + action='list_nodes', + provider=provider + )[server_name] + + if volume and volume['attachments']: + ret['comment'] = ('Volume {name} is already' + 'attached: {attachments}').format(**volume) + ret['result'] = True + return ret + elif __opts__['test']: + ret['comment'] = 'Volume {0} will be will be attached.'.format( + name + ) + ret['result'] = None + return ret + elif not volume: + ret['comment'] = 'Volume {0} does not exist'.format(name) + ret['result'] = False + return ret + elif not server: + ret['comment'] = 'Server {0} does not exist'.format(server_name) + ret['result'] = False + return ret + + response = __salt__['cloud.volume_attach']( + name, + provider=provider, + server_name=server_name, + **kwargs + ) + if response: + ret['result'] = True + ret['comment'] = 'Volume {0} was created'.format(name) + ret['changes'] = {'old': volume, 'new': response} + else: + ret['result'] = False + ret['comment'] = 'Volume {0} failed to attach.'.format(name) + return ret