%PDF- %PDF-
Direktori : /lib/python2.7/site-packages/salt/modules/ |
Current File : //lib/python2.7/site-packages/salt/modules/purefa.py |
# -*- coding: utf-8 -*- ## # Copyright 2017 Pure Storage Inc # # Licensed under the Apache License, Version 2.0 (the 'License'); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an 'AS IS' BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ''' Management of Pure Storage FlashArray Installation Prerequisites -------------------------- - You will need the ``purestorage`` python package in your python installation path that is running salt. .. code-block:: bash pip install purestorage - Configure Pure Storage FlashArray authentication. Use one of the following three methods. 1) From the minion config .. code-block:: yaml pure_tags: fa: san_ip: management vip or hostname for the FlashArray api_token: A valid api token for the FlashArray being managed 2) From environment (PUREFA_IP and PUREFA_API) 3) From the pillar (PUREFA_IP and PUREFA_API) :maintainer: Simon Dodsley (simon@purestorage.com) :maturity: new :requires: purestorage :platform: all .. versionadded:: 2018.3.0 ''' # Import Python libs from __future__ import absolute_import, print_function, unicode_literals import os import platform from datetime import datetime # Import Salt libs from salt.ext import six from salt.exceptions import CommandExecutionError # Import 3rd party modules try: import purestorage HAS_PURESTORAGE = True except ImportError: HAS_PURESTORAGE = False __docformat__ = 'restructuredtext en' VERSION = '1.0.0' USER_AGENT_BASE = 'Salt' __virtualname__ = 'purefa' # Default symbols to use for passwords. Avoids visually confusing characters. # ~6 bits per symbol DEFAULT_PASSWORD_SYMBOLS = ('23456789', # Removed: 0,1 'ABCDEFGHJKLMNPQRSTUVWXYZ', # Removed: I, O 'abcdefghijkmnopqrstuvwxyz') # Removed: l def __virtual__(): ''' Determine whether or not to load this module ''' if HAS_PURESTORAGE: return __virtualname__ return (False, 'purefa execution module not loaded: purestorage python library not available.') def _get_system(): ''' Get Pure Storage FlashArray configuration 1) From the minion config pure_tags: fa: san_ip: management vip or hostname for the FlashArray api_token: A valid api token for the FlashArray being managed 2) From environment (PUREFA_IP and PUREFA_API) 3) From the pillar (PUREFA_IP and PUREFA_API) ''' agent = {'base': USER_AGENT_BASE, 'class': __name__, 'version': VERSION, 'platform': platform.platform() } user_agent = '{base} {class}/{version} ({platform})'.format(**agent) try: array = __opts__['pure_tags']['fa'].get('san_ip') api = __opts__['pure_tags']['fa'].get('api_token') if array and api: system = purestorage.FlashArray(array, api_token=api, user_agent=user_agent) except (KeyError, NameError, TypeError): try: san_ip = os.environ.get('PUREFA_IP') api_token = os.environ.get('PUREFA_API') system = purestorage.FlashArray(san_ip, api_token=api_token, user_agent=user_agent) except (ValueError, KeyError, NameError): try: system = purestorage.FlashArray(__pillar__['PUREFA_IP'], api_token=__pillar__['PUREFA_API'], user_agent=user_agent) except (KeyError, NameError): raise CommandExecutionError('No Pure Storage FlashArray credentials found.') try: system.get() except Exception: raise CommandExecutionError('Pure Storage FlashArray authentication failed.') return system def _get_volume(name, array): '''Private function to check volume''' try: return array.get_volume(name) except purestorage.PureError: return None def _get_snapshot(name, suffix, array): '''Private function to check snapshot''' snapshot = name + '.' + suffix try: for snap in array.get_volume(name, snap=True): if snap['name'] == snapshot: return snapshot except purestorage.PureError: return None def _get_deleted_volume(name, array): '''Private function to check deleted volume''' try: return array.get_volume(name, pending='true') except purestorage.PureError: return None def _get_pgroup(name, array): '''Private function to check protection group''' pgroup = None for temp in array.list_pgroups(): if temp['name'] == name: pgroup = temp break return pgroup def _get_deleted_pgroup(name, array): '''Private function to check deleted protection group''' try: return array.get_pgroup(name, pending='true') except purestorage.PureError: return None def _get_hgroup(name, array): '''Private function to check hostgroup''' hostgroup = None for temp in array.list_hgroups(): if temp['name'] == name: hostgroup = temp break return hostgroup def _get_host(name, array): '''Private function to check host''' host = None for temp in array.list_hosts(): if temp['name'] == name: host = temp break return host def snap_create(name, suffix=None): ''' Create a volume snapshot on a Pure Storage FlashArray. Will return False is volume selected to snap does not exist. .. versionadded:: 2018.3.0 name : string name of volume to snapshot suffix : string if specificed forces snapshot name suffix. If not specified defaults to timestamp. CLI Example: .. code-block:: bash salt '*' purefa.snap_create foo salt '*' purefa.snap_create foo suffix=bar ''' array = _get_system() if suffix is None: suffix = 'snap-' + six.text_type((datetime.utcnow() - datetime(1970, 1, 1, 0, 0, 0, 0)).total_seconds()) suffix = suffix.replace('.', '') if _get_volume(name, array) is not None: try: array.create_snapshot(name, suffix=suffix) return True except purestorage.PureError: return False else: return False def snap_delete(name, suffix=None, eradicate=False): ''' Delete a volume snapshot on a Pure Storage FlashArray. Will return False if selected snapshot does not exist. .. versionadded:: 2018.3.0 name : string name of volume suffix : string name of snapshot eradicate : boolean Eradicate snapshot after deletion if True. Default is False CLI Example: .. code-block:: bash salt '*' purefa.snap_delete foo suffix=snap eradicate=True ''' array = _get_system() if _get_snapshot(name, suffix, array) is not None: try: snapname = name + '.' + suffix array.destroy_volume(snapname) except purestorage.PureError: return False if eradicate is True: try: array.eradicate_volume(snapname) return True except purestorage.PureError: return False else: return True else: return False def snap_eradicate(name, suffix=None): ''' Eradicate a deleted volume snapshot on a Pure Storage FlashArray. Will return False if snapshot is not in a deleted state. .. versionadded:: 2018.3.0 name : string name of volume suffix : string name of snapshot CLI Example: .. code-block:: bash salt '*' purefa.snap_eradicate foo suffix=snap ''' array = _get_system() if _get_snapshot(name, suffix, array) is not None: snapname = name + '.' + suffix try: array.eradicate_volume(snapname) return True except purestorage.PureError: return False else: return False def volume_create(name, size=None): ''' Create a volume on a Pure Storage FlashArray. Will return False if volume already exists. .. versionadded:: 2018.3.0 name : string name of volume (truncated to 63 characters) size : string if specificed capacity of volume. If not specified default to 1G. Refer to Pure Storage documentation for formatting rules. CLI Example: .. code-block:: bash salt '*' purefa.volume_create foo salt '*' purefa.volume_create foo size=10T ''' if len(name) > 63: name = name[0:63] array = _get_system() if _get_volume(name, array) is None: if size is None: size = '1G' try: array.create_volume(name, size) return True except purestorage.PureError: return False else: return False def volume_delete(name, eradicate=False): ''' Delete a volume on a Pure Storage FlashArray. Will return False if volume doesn't exist is already in a deleted state. .. versionadded:: 2018.3.0 name : string name of volume eradicate : boolean Eradicate volume after deletion if True. Default is False CLI Example: .. code-block:: bash salt '*' purefa.volume_delete foo eradicate=True ''' array = _get_system() if _get_volume(name, array) is not None: try: array.destroy_volume(name) except purestorage.PureError: return False if eradicate is True: try: array.eradicate_volume(name) return True except purestorage.PureError: return False else: return True else: return False def volume_eradicate(name): ''' Eradicate a deleted volume on a Pure Storage FlashArray. Will return False is volume is not in a deleted state. .. versionadded:: 2018.3.0 name : string name of volume CLI Example: .. code-block:: bash salt '*' purefa.volume_eradicate foo ''' array = _get_system() if _get_deleted_volume(name, array) is not None: try: array.eradicate_volume(name) return True except purestorage.PureError: return False else: return False def volume_extend(name, size): ''' Extend an existing volume on a Pure Storage FlashArray. Will return False if new size is less than or equal to existing size. .. versionadded:: 2018.3.0 name : string name of volume size : string New capacity of volume. Refer to Pure Storage documentation for formatting rules. CLI Example: .. code-block:: bash salt '*' purefa.volume_extend foo 10T ''' array = _get_system() vol = _get_volume(name, array) if vol is not None: if __utils__['stringutils.human_to_bytes'](size) > vol['size']: try: array.extend_volume(name, size) return True except purestorage.PureError: return False else: return False else: return False def snap_volume_create(name, target, overwrite=False): ''' Create R/W volume from snapshot on a Pure Storage FlashArray. Will return False if target volume already exists and overwrite is not specified, or selected snapshot doesn't exist. .. versionadded:: 2018.3.0 name : string name of volume snapshot target : string name of clone volume overwrite : boolean overwrite clone if already exists (default: False) CLI Example: .. code-block:: bash salt '*' purefa.snap_volume_create foo.bar clone overwrite=True ''' array = _get_system() source, suffix = name.split('.') if _get_snapshot(source, suffix, array) is not None: if _get_volume(target, array) is None: try: array.copy_volume(name, target) return True except purestorage.PureError: return False else: if overwrite: try: array.copy_volume(name, target, overwrite=overwrite) return True except purestorage.PureError: return False else: return False else: return False def volume_clone(name, target, overwrite=False): ''' Clone an existing volume on a Pure Storage FlashArray. Will return False if source volume doesn't exist, or target volume already exists and overwrite not specified. .. versionadded:: 2018.3.0 name : string name of volume target : string name of clone volume overwrite : boolean overwrite clone if already exists (default: False) CLI Example: .. code-block:: bash salt '*' purefa.volume_clone foo bar overwrite=True ''' array = _get_system() if _get_volume(name, array) is not None: if _get_volume(target, array) is None: try: array.copy_volume(name, target) return True except purestorage.PureError: return False else: if overwrite: try: array.copy_volume(name, target, overwrite=overwrite) return True except purestorage.PureError: return False else: return False else: return False def volume_attach(name, host): ''' Attach a volume to a host on a Pure Storage FlashArray. Host and volume must exist or else will return False. .. versionadded:: 2018.3.0 name : string name of volume host : string name of host CLI Example: .. code-block:: bash salt '*' purefa.volume_attach foo bar ''' array = _get_system() if _get_volume(name, array) is not None and _get_host(host, array) is not None: try: array.connect_host(host, name) return True except purestorage.PureError: return False else: return False def volume_detach(name, host): ''' Detach a volume from a host on a Pure Storage FlashArray. Will return False if either host or volume do not exist, or if selected volume isn't already connected to the host. .. versionadded:: 2018.3.0 name : string name of volume host : string name of host CLI Example: .. code-block:: bash salt '*' purefa.volume_detach foo bar ''' array = _get_system() if _get_volume(name, array) is None or _get_host(host, array) is None: return False elif _get_volume(name, array) is not None and _get_host(host, array) is not None: try: array.disconnect_host(host, name) return True except purestorage.PureError: return False def host_create(name, iqn=None, wwn=None): ''' Add a host on a Pure Storage FlashArray. Will return False if host already exists, or the iSCSI or Fibre Channel parameters are not in a valid format. See Pure Storage FlashArray documentation. .. versionadded:: 2018.3.0 name : string name of host (truncated to 63 characters) iqn : string iSCSI IQN of host wwn : string Fibre Channel WWN of host CLI Example: .. code-block:: bash salt '*' purefa.host_create foo iqn='<Valid iSCSI IQN>' wwn='<Valid WWN>' ''' array = _get_system() if len(name) > 63: name = name[0:63] if _get_host(name, array) is None: try: array.create_host(name) except purestorage.PureError: return False if iqn is not None: try: array.set_host(name, addiqnlist=[iqn]) except purestorage.PureError: array.delete_host(name) return False if wwn is not None: try: array.set_host(name, addwwnlist=[wwn]) except purestorage.PureError: array.delete_host(name) return False else: return False return True def host_update(name, iqn=None, wwn=None): ''' Update a hosts port definitions on a Pure Storage FlashArray. Will return False if new port definitions are already in use by another host, or are not in a valid format. See Pure Storage FlashArray documentation. .. versionadded:: 2018.3.0 name : string name of host iqn : string Additional iSCSI IQN of host wwn : string Additional Fibre Channel WWN of host CLI Example: .. code-block:: bash salt '*' purefa.host_update foo iqn='<Valid iSCSI IQN>' wwn='<Valid WWN>' ''' array = _get_system() if _get_host(name, array) is not None: if iqn is not None: try: array.set_host(name, addiqnlist=[iqn]) except purestorage.PureError: return False if wwn is not None: try: array.set_host(name, addwwnlist=[wwn]) except purestorage.PureError: return False return True else: return False def host_delete(name): ''' Delete a host on a Pure Storage FlashArray (detaches all volumes). Will return False if the host doesn't exist. .. versionadded:: 2018.3.0 name : string name of host CLI Example: .. code-block:: bash salt '*' purefa.host_delete foo ''' array = _get_system() if _get_host(name, array) is not None: for vol in array.list_host_connections(name): try: array.disconnect_host(name, vol['vol']) except purestorage.PureError: return False try: array.delete_host(name) return True except purestorage.PureError: return False else: return False def hg_create(name, host=None, volume=None): ''' Create a hostgroup on a Pure Storage FlashArray. Will return False if hostgroup already exists, or if named host or volume do not exist. .. versionadded:: 2018.3.0 name : string name of hostgroup (truncated to 63 characters) host : string name of host to add to hostgroup volume : string name of volume to add to hostgroup CLI Example: .. code-block:: bash salt '*' purefa.hg_create foo host=bar volume=vol ''' array = _get_system() if len(name) > 63: name = name[0:63] if _get_hgroup(name, array) is None: try: array.create_hgroup(name) except purestorage.PureError: return False if host is not None: if _get_host(host, array): try: array.set_hgroup(name, addhostlist=[host]) except purestorage.PureError: return False else: hg_delete(name) return False if volume is not None: if _get_volume(volume, array): try: array.connect_hgroup(name, volume) except purestorage.PureError: hg_delete(name) return False else: hg_delete(name) return False return True else: return False def hg_update(name, host=None, volume=None): ''' Adds entries to a hostgroup on a Pure Storage FlashArray. Will return False is hostgroup doesn't exist, or host or volume do not exist. .. versionadded:: 2018.3.0 name : string name of hostgroup host : string name of host to add to hostgroup volume : string name of volume to add to hostgroup CLI Example: .. code-block:: bash salt '*' purefa.hg_update foo host=bar volume=vol ''' array = _get_system() if _get_hgroup(name, array) is not None: if host is not None: if _get_host(host, array): try: array.set_hgroup(name, addhostlist=[host]) except purestorage.PureError: return False else: return False if volume is not None: if _get_volume(volume, array): try: array.connect_hgroup(name, volume) except purestorage.PureError: return False else: return False return True else: return False def hg_delete(name): ''' Delete a hostgroup on a Pure Storage FlashArray (removes all volumes and hosts). Will return False is hostgroup is already in a deleted state. .. versionadded:: 2018.3.0 name : string name of hostgroup CLI Example: .. code-block:: bash salt '*' purefa.hg_delete foo ''' array = _get_system() if _get_hgroup(name, array) is not None: for vol in array.list_hgroup_connections(name): try: array.disconnect_hgroup(name, vol['vol']) except purestorage.PureError: return False host = array.get_hgroup(name) try: array.set_hgroup(name, remhostlist=host['hosts']) array.delete_hgroup(name) return True except purestorage.PureError: return False else: return False def hg_remove(name, volume=None, host=None): ''' Remove a host and/or volume from a hostgroup on a Pure Storage FlashArray. Will return False is hostgroup does not exist, or named host or volume are not in the hostgroup. .. versionadded:: 2018.3.0 name : string name of hostgroup volume : string name of volume to remove from hostgroup host : string name of host to remove from hostgroup CLI Example: .. code-block:: bash salt '*' purefa.hg_remove foo volume=test host=bar ''' array = _get_system() if _get_hgroup(name, array) is not None: if volume is not None: if _get_volume(volume, array): for temp in array.list_hgroup_connections(name): if temp['vol'] == volume: try: array.disconnect_hgroup(name, volume) return True except purestorage.PureError: return False return False else: return False if host is not None: if _get_host(host, array): temp = _get_host(host, array) if temp['hgroup'] == name: try: array.set_hgroup(name, remhostlist=[host]) return True except purestorage.PureError: return False else: return False else: return False if host is None and volume is None: return False else: return False def pg_create(name, hostgroup=None, host=None, volume=None, enabled=True): ''' Create a protection group on a Pure Storage FlashArray. Will return False is the following cases: * Protection Grop already exists * Protection Group in a deleted state * More than one type is specified - protection groups are for only hostgroups, hosts or volumes * Named type for protection group does not exist .. versionadded:: 2018.3.0 name : string name of protection group hostgroup : string name of hostgroup to add to protection group host : string name of host to add to protection group volume : string name of volume to add to protection group CLI Example: .. code-block:: bash salt '*' purefa.pg_create foo [hostgroup=foo | host=bar | volume=vol] enabled=[true | false] ''' array = _get_system() if hostgroup is None and host is None and volume is None: if _get_pgroup(name, array) is None: try: array.create_pgroup(name) except purestorage.PureError: return False try: array.set_pgroup(name, snap_enabled=enabled) return True except purestorage.PureError: pg_delete(name) return False else: return False elif __utils__['value.xor'](hostgroup, host, volume): if _get_pgroup(name, array) is None: try: array.create_pgroup(name) except purestorage.PureError: return False try: array.set_pgroup(name, snap_enabled=enabled) except purestorage.PureError: pg_delete(name) return False if hostgroup is not None: if _get_hgroup(hostgroup, array) is not None: try: array.set_pgroup(name, addhgrouplist=[hostgroup]) return True except purestorage.PureError: pg_delete(name) return False else: pg_delete(name) return False elif host is not None: if _get_host(host, array) is not None: try: array.set_pgroup(name, addhostlist=[host]) return True except purestorage.PureError: pg_delete(name) return False else: pg_delete(name) return False elif volume is not None: if _get_volume(volume, array) is not None: try: array.set_pgroup(name, addvollist=[volume]) return True except purestorage.PureError: pg_delete(name) return False else: pg_delete(name) return False else: return False else: return False def pg_update(name, hostgroup=None, host=None, volume=None): ''' Update a protection group on a Pure Storage FlashArray. Will return False in the following cases: * Protection group does not exist * Incorrect type selected for current protection group type * Specified type does not exist .. versionadded:: 2018.3.0 name : string name of protection group hostgroup : string name of hostgroup to add to protection group host : string name of host to add to protection group volume : string name of volume to add to protection group CLI Example: .. code-block:: bash salt '*' purefa.pg_update foo [hostgroup=foo | host=bar | volume=vol] ''' array = _get_system() pgroup = _get_pgroup(name, array) if pgroup is not None: if hostgroup is not None and pgroup['hgroups'] is not None: if _get_hgroup(hostgroup, array) is not None: try: array.add_hgroup(hostgroup, name) return True except purestorage.PureError: return False else: return False elif host is not None and pgroup['hosts'] is not None: if _get_host(host, array) is not None: try: array.add_host(host, name) return True except purestorage.PureError: return False else: return False elif volume is not None and pgroup['volumes'] is not None: if _get_volume(volume, array) is not None: try: array.add_volume(volume, name) return True except purestorage.PureError: return False else: return False else: if pgroup['hgroups'] is None and pgroup['hosts'] is None and pgroup['volumes'] is None: if hostgroup is not None: if _get_hgroup(hostgroup, array) is not None: try: array.set_pgroup(name, addhgrouplist=[hostgroup]) return True except purestorage.PureError: return False else: return False elif host is not None: if _get_host(host, array) is not None: try: array.set_pgroup(name, addhostlist=[host]) return True except purestorage.PureError: return False else: return False elif volume is not None: if _get_volume(volume, array) is not None: try: array.set_pgroup(name, addvollist=[volume]) return True except purestorage.PureError: return False else: return False else: return False else: return False def pg_delete(name, eradicate=False): ''' Delete a protecton group on a Pure Storage FlashArray. Will return False if protection group is already in a deleted state. .. versionadded:: 2018.3.0 name : string name of protection group CLI Example: .. code-block:: bash salt '*' purefa.pg_delete foo ''' array = _get_system() if _get_pgroup(name, array) is not None: try: array.destroy_pgroup(name) except purestorage.PureError: return False if eradicate is True: try: array.eradicate_pgroup(name) return True except purestorage.PureError: return False else: return True else: return False def pg_eradicate(name): ''' Eradicate a deleted protecton group on a Pure Storage FlashArray. Will return False if protection group is not in a deleted state. .. versionadded:: 2018.3.0 name : string name of protection group CLI Example: .. code-block:: bash salt '*' purefa.pg_eradicate foo ''' array = _get_system() if _get_deleted_pgroup(name, array) is not None: try: array.eradicate_pgroup(name) return True except purestorage.PureError: return False else: return False def pg_remove(name, hostgroup=None, host=None, volume=None): ''' Remove a hostgroup, host or volume from a protection group on a Pure Storage FlashArray. Will return False in the following cases: * Protection group does not exist * Specified type is not currently associated with the protection group .. versionadded:: 2018.3.0 name : string name of hostgroup hostgroup : string name of hostgroup to remove from protection group host : string name of host to remove from hostgroup volume : string name of volume to remove from hostgroup CLI Example: .. code-block:: bash salt '*' purefa.pg_remove foo [hostgroup=bar | host=test | volume=bar] ''' array = _get_system() pgroup = _get_pgroup(name, array) if pgroup is not None: if hostgroup is not None and pgroup['hgroups'] is not None: if _get_hgroup(hostgroup, array) is not None: try: array.remove_hgroup(hostgroup, name) return True except purestorage.PureError: return False else: return False elif host is not None and pgroup['hosts'] is not None: if _get_host(host, array) is not None: try: array.remove_host(host, name) return True except purestorage.PureError: return False else: return False elif volume is not None and pgroup['volumes'] is not None: if _get_volume(volume, array) is not None: try: array.remove_volume(volume, name) return True except purestorage.PureError: return False else: return False else: return False else: return False