Ejemplo n.º 1
0
    def _valid_request(self, pool, image, size):
        """
        Validate the parameters of a create request
        :param pool: rados pool name
        :param image: rbd image name
        :param size: size of the rbd (unit suffixed e.g. 20G)
        :return: boolean, indicating whether the parameters may be used or not
        """

        ui_root = self.get_ui_root()
        state = True
        discovered_pools = [
            rados_pool.name
            for rados_pool in ui_root.ceph.local_ceph.pools.children
        ]
        existing_rbds = self.disk_info.keys()

        storage_key = "{}.{}".format(pool, image)
        if not size:
            self.logger.error("Size parameter is missing")
            state = False
        elif not valid_size(size):
            self.logger.error("Size is invalid")
            state = False
        elif pool not in discovered_pools:
            self.logger.error("pool name is invalid")
            state = False
        elif storage_key in existing_rbds:
            self.logger.error("image of that name already defined")
            state = False

        return state
Ejemplo n.º 2
0
def ansible_main():

    # Define the fields needs to create/map rbd's the the host(s)
    # NB. features and state are reserved/unused
    fields = {
        "pool": {"required": False, "default": "rbd", "type": "str"},
        "image": {"required": True, "type": "str"},
        "size": {"required": True, "type": "str"},
        "host": {"required": True, "type": "str"},
        "features": {"required": False, "type": "str"},
        "state": {
            "required": False,
            "default": "present",
            "choices": ['present', 'absent'],
            "type": "str"
        },
    }

    # not supporting check mode currently
    module = AnsibleModule(argument_spec=fields,
                           supports_check_mode=False)

    pool = module.params["pool"]
    image = module.params['image']
    size = module.params['size']
    allocating_host = module.params['host']
    desired_state = module.params['state']

    ################################################
    # Validate the parameters passed from Ansible  #
    ################################################
    if not valid_size(size):
        logger.critical("image '{}' has an invalid size specification '{}' in the ansible configuration".format(image,
                                                                                                         size))
        module.fail_json(msg="(main) Unable to use the size parameter '{}' for image '{}' from the playbook - "
                             "must be a number suffixed by M, G or T".format(size, image))

    # define a lun object and perform some initial parameter validation
    lun = LUN(logger, pool, image, size, allocating_host)
    if lun.error:
        module.fail_json(msg=lun.error_msg)

    logger.info("START - LUN configuration started for {}/{}".format(pool, image))

    # attempt to create/allocate the LUN for LIO
    lun.manage(desired_state)
    if lun.error:
        module.fail_json(msg=lun.error_msg)

    if lun.num_changes == 0:
        logger.info("END   - No changes needed")
    else:
        logger.info("END   - {} configuration changes made".format(lun.num_changes))

    module.exit_json(changed=(lun.num_changes > 0), meta={"msg": "Configuration updated"})
Ejemplo n.º 3
0
    def resize(self, size):
        """
        Perform the resize operation, and sync the disk size across each of the
        gateways
        :param size: (int) new size for the rbd image
        :return:
        """
        # resize is actually managed by the same lun and api endpoint as
        # create so this logic is very similar to a 'create' request

        size_rqst = size.upper()
        if not valid_size(size_rqst):
            self.logger.error("Size is invalid")
            return

        # At this point the size request needs to be honoured
        self.logger.debug("Resizing {} to {}".format(self.image_id, size_rqst))

        local_gw = this_host()

        # Issue the api request for the resize
        disk_api = ('{}://localhost:{}/api/'
                    'disk/{}'.format(self.http_mode, settings.config.api_port,
                                     self.image_id))

        api_vars = {
            'pool': self.pool,
            'size': size_rqst,
            'owner': local_gw,
            'mode': 'resize'
        }

        self.logger.debug("Issuing resize request")
        api = APIRequest(disk_api, data=api_vars)
        api.put()

        if api.response.status_code == 200:
            # at this point the resize request was successful, so we need to
            # update the ceph pool meta data (%commit etc)
            self._update_pool()
            self.size_h = size_rqst
            self.size = convert_2_bytes(size_rqst)

            self.logger.info('ok')

        else:
            self.logger.error("Failed to resize : "
                              "{}".format(
                                  response_message(api.response, self.logger)))
Ejemplo n.º 4
0
    def ui_command_create(self,
                          pool=None,
                          image=None,
                          size=None,
                          backstore=None,
                          count=1):
        """
        Create a RBD image and assign to the gateway(s).

        The create command supports two request formats;

        Long format  : create pool=<name> image=<name> size=<size>
        Short format : create pool/image <size>

        e.g.
        create pool=rbd image=testimage size=100g
        create rbd.testimage 100g

        The syntax of each parameter is as follows;
        pool  : Pool and image name may contain a-z, A-Z, 0-9, '_', or '-'
        image   characters.
        size  : integer, suffixed by the allocation unit - either m/M, g/G or
                t/T representing the MB/GB/TB [1]
        backstore  : lio backstore
        count : integer (default is 1)[2]. If the request provides a count=<n>
                parameter the image name will be used as a prefix, and the count
                used as a suffix to create multiple images from the same request.
                e.g.
                create rbd.test 1g count=5
                -> create 5 images called test1..test5 each of 1GB in size
                   from the rbd pool

        Notes.
        1) size does not support decimal representations
        2) Using a count to create multiple images will lock the CLI until all
           images have been created
        """
        # NB the text above is shown on a help create request in the CLI

        if pool and '/' in pool:
            # shorthand version of the command
            self.logger.debug("user provided pool/image format request")

            if image:
                if size:
                    try:
                        count = int(size)
                    except ValueError:
                        self.logger.error("Invalid count provided "
                                          "({} ?)".format(size))
                        return
                size = image
            pool, image = pool.split('/')

        else:
            # long format request
            if not pool or not image:
                self.logger.error("Invalid create: pool and image "
                                  "parameters are needed")
                return

        if size and not valid_size(size):
            self.logger.error("Invalid size requested. Must be an integer, "
                              "suffixed by M, G or T. See help for more info")
            return

        if count:
            if not str(count).isdigit():
                self.logger.error("invalid count format, must be an integer")
                return

        self.logger.debug("CMD: /disks/ create pool={} "
                          "image={} size={} "
                          "count={} ".format(pool, image, size, count))
        self.create_disk(pool=pool,
                         image=image,
                         size=size,
                         count=count,
                         backstore=backstore)
Ejemplo n.º 5
0
def valid_disk(**kwargs):
    """
    determine whether the given image info is valid for a disk operation

    :param image_id: (str) <pool>.<image> format
    :return: (str) either 'ok' or an error description
    """

    mode_vars = {"create": ['pool', 'image', 'size', 'count'],
                 "resize": ['pool', 'image', 'size'],
                 "delete": ['pool', 'image']}

    config = get_config()
    if not config:
        return "Unable to query the local API for the current config"

    if 'mode' in kwargs.keys():
        mode = kwargs['mode']
    else:
        mode = None

    if mode in mode_vars:
        if not all(x in kwargs for x in mode_vars[mode]):
            return ("{} request must contain the following "
                    "variables: ".format(mode,
                                         ','.join(mode_vars[mode])))
    else:
        return "disk operation mode '{}' is invalid".format(mode)

    disk_key = "{}.{}".format(kwargs['pool'], kwargs['image'])

    if mode in ['create', 'resize']:

        if not valid_size(kwargs['size']):
            return "Size is invalid"

        elif kwargs['pool'] not in rados_pools():
            return "pool name is invalid"

    if mode == 'create':

        if kwargs['count'].isdigit():
            if not 1 <= int(kwargs['count']) <= 10:
                return "invalid count specified, must be an integer (1-10)"
        else:
            return "invalid count specified, must be an integer (1-10)"

        if kwargs['count'] == '1':
            new_disks = {disk_key}
        else:
            limit = int(kwargs['count']) + 1
            new_disks = set(['{}{}'.format(disk_key, ctr)
                             for ctr in range(1, limit)])

        if any(new_disk in config['disks'] for new_disk in new_disks):
            return ("at least one rbd image(s) with that name/prefix is "
                    "already defined")

        gateways_defined = len([key for key in config['gateways']
                               if isinstance(config['gateways'][key],
                                             dict)])
        if gateways_defined < settings.config.minimum_gateways:
            return ("disks can not be added until at least {} gateways "
                    "are defined".format(settings.config.minimum_gateways))


    if mode in ["resize", "delete"]:
        # disk must exist in the config
        if disk_key not in config['disks']:
            return ("rbd {}/{} is not defined to the "
                    "configuration".format(kwargs['pool'],
                                           kwargs['image']))


    if mode == 'resize':

        size = kwargs['size'].upper()
        current_size = rbd_size(kwargs['pool'], kwargs['image'])
        if convert_2_bytes(size) <= current_size:
            return ("resize value must be larger than the "
                    "current size ({}/{})".format(human_size(current_size),
                                                  current_size))

    if mode == 'delete':

        # disk must *not* be allocated to a client in the config
        allocation_list = []
        for client_iqn in config['clients']:
            client_metadata = config['clients'][client_iqn]
            if disk_key in client_metadata['luns']:
                allocation_list.append(client_iqn)

        if allocation_list:
            return ("Unable to delete {}. Allocated "
                    "to: {}".format(disk_key,
                                    ','.join(allocation_list)))

    return 'ok'
Ejemplo n.º 6
0
    def valid_disk(ceph_iscsi_config, logger, **kwargs):
        """
        determine whether the given image info is valid for a disk operation

        :param ceph_iscsi_config: Config object
        :param logger: logger object
        :param image_id: (str) <pool>.<image> format
        :return: (str) either 'ok' or an error description
        """

        # create can also pass optional controls dict
        mode_vars = {
            "create": ['pool', 'image', 'size', 'count'],
            "resize": ['pool', 'image', 'size'],
            "reconfigure": ['pool', 'image', 'controls'],
            "delete": ['pool', 'image']
        }

        if 'mode' in kwargs.keys():
            mode = kwargs['mode']
        else:
            mode = None

        backstore = kwargs['backstore']
        if backstore not in LUN.BACKSTORES:
            return "Invalid '{}' backstore - Supported backstores: " \
                   "{}".format(backstore, ','.join(LUN.BACKSTORES))

        if mode in mode_vars:
            if not all(x in kwargs for x in mode_vars[mode]):
                return ("{} request must contain the following "
                        "variables: ".format(mode, ','.join(mode_vars[mode])))
        else:
            return "disk operation mode '{}' is invalid".format(mode)

        config = ceph_iscsi_config.config

        disk_key = "{}.{}".format(kwargs['pool'], kwargs['image'])

        if mode in ['create', 'resize']:

            if kwargs['pool'] not in get_pools():
                return "pool name is invalid"

        if mode == 'create':
            if kwargs['size'] and not valid_size(kwargs['size']):
                return "Size is invalid"

            if len(config['disks']) >= 256:
                return "Disk limit of 256 reached."

            disk_regex = re.compile(r"^[a-zA-Z0-9\-_]+$")
            if not disk_regex.search(kwargs['pool']):
                return "Invalid pool name (use alphanumeric, '_', or '-' characters)"
            if not disk_regex.search(kwargs['image']):
                return "Invalid image name (use alphanumeric, '_', or '-' characters)"

            if kwargs['count'].isdigit():
                if not 1 <= int(kwargs['count']) <= 10:
                    return "invalid count specified, must be an integer (1-10)"
            else:
                return "invalid count specified, must be an integer (1-10)"

            if kwargs['count'] == '1':
                new_disks = {disk_key}
            else:
                limit = int(kwargs['count']) + 1
                new_disks = set(
                    ['{}{}'.format(disk_key, ctr) for ctr in range(1, limit)])

            if any(new_disk in config['disks'] for new_disk in new_disks):
                return ("at least one rbd image(s) with that name/prefix is "
                        "already defined")

        if mode in ["resize", "delete", "reconfigure"]:
            # disk must exist in the config
            if disk_key not in config['disks']:
                return ("rbd {}/{} is not defined to the "
                        "configuration".format(kwargs['pool'],
                                               kwargs['image']))

        if mode == 'resize':

            if not valid_size(kwargs['size']):
                return "Size is invalid"

            size = kwargs['size'].upper()
            current_size = get_rbd_size(kwargs['pool'], kwargs['image'])
            if convert_2_bytes(size) <= current_size:
                return ("resize value must be larger than the "
                        "current size ({}/{})".format(human_size(current_size),
                                                      current_size))

        if mode in ['create', 'reconfigure']:

            try:
                settings.Settings.normalize_controls(kwargs['controls'],
                                                     LUN.SETTINGS[backstore])
            except ValueError as err:
                return (err)

        if mode == 'delete':

            # disk must *not* be allocated to a client in the config
            mapped_list = []
            allocation_list = []
            for target_iqn, target in config['targets'].items():
                if disk_key in target['disks']:
                    mapped_list.append(target_iqn)
                for client_iqn in target['clients']:
                    client_metadata = target['clients'][client_iqn]
                    if disk_key in client_metadata['luns']:
                        allocation_list.append(client_iqn)

            if allocation_list:
                return ("Unable to delete {}. Allocated "
                        "to: {}".format(disk_key, ','.join(allocation_list)))

            if mapped_list:
                return ("Unable to delete {}. Mapped "
                        "to: {}".format(disk_key, ','.join(mapped_list)))

        return 'ok'
Ejemplo n.º 7
0
    def valid_disk(ceph_iscsi_config, logger, **kwargs):
        """
        determine whether the given image info is valid for a disk operation

        :param ceph_iscsi_config: Config object
        :param logger: logger object
        :param image_id: (str) <pool>.<image> format
        :return: (str) either 'ok' or an error description
        """

        # create can also pass optional controls dict
        mode_vars = {
            "create": ['pool', 'image', 'size', 'count'],
            "resize": ['pool', 'image', 'size'],
            "reconfigure": ['pool', 'image', 'controls'],
            "delete": ['pool', 'image']
        }

        if 'mode' in kwargs.keys():
            mode = kwargs['mode']
        else:
            mode = None

        if mode in mode_vars:
            if not all(x in kwargs for x in mode_vars[mode]):
                return ("{} request must contain the following "
                        "variables: ".format(mode, ','.join(mode_vars[mode])))
        else:
            return "disk operation mode '{}' is invalid".format(mode)

        config = ceph_iscsi_config.config

        disk_key = "{}.{}".format(kwargs['pool'], kwargs['image'])

        if mode in ['create', 'resize']:

            if not valid_size(kwargs['size']):
                return "Size is invalid"

            elif kwargs['pool'] not in get_pools():
                return "pool name is invalid"

        if mode == 'create':
            if len(config['disks']) >= 256:
                return "Disk limit of 256 reached."

            disk_regex = re.compile(r"^[a-zA-Z0-9\-_]+$")
            if not disk_regex.search(kwargs['pool']):
                return "Invalid pool name (use alphanumeric, '_', or '-' characters)"
            if not disk_regex.search(kwargs['image']):
                return "Invalid image name (use alphanumeric, '_', or '-' characters)"

            if kwargs['count'].isdigit():
                if not 1 <= int(kwargs['count']) <= 10:
                    return "invalid count specified, must be an integer (1-10)"
            else:
                return "invalid count specified, must be an integer (1-10)"

            if kwargs['count'] == '1':
                new_disks = {disk_key}
            else:
                limit = int(kwargs['count']) + 1
                new_disks = set(
                    ['{}{}'.format(disk_key, ctr) for ctr in range(1, limit)])

            if any(new_disk in config['disks'] for new_disk in new_disks):
                return ("at least one rbd image(s) with that name/prefix is "
                        "already defined")

            gateways_defined = len([
                key for key in config['gateways']
                if isinstance(config['gateways'][key], dict)
            ])
            if gateways_defined < settings.config.minimum_gateways:
                return ("disks can not be added until at least {} gateways "
                        "are defined".format(settings.config.minimum_gateways))

        if mode in ["resize", "delete", "reconfigure"]:
            # disk must exist in the config
            if disk_key not in config['disks']:
                return ("rbd {}/{} is not defined to the "
                        "configuration".format(kwargs['pool'],
                                               kwargs['image']))

        if mode == 'resize':

            size = kwargs['size'].upper()
            current_size = get_rbd_size(kwargs['pool'], kwargs['image'])
            if convert_2_bytes(size) <= current_size:
                return ("resize value must be larger than the "
                        "current size ({}/{})".format(human_size(current_size),
                                                      current_size))

        if mode in ['create', 'reconfigure']:

            try:
                settings.Settings.normalize_controls(kwargs['controls'],
                                                     LUN.SETTINGS)
            except ValueError as err:
                return (err)

        if mode == 'delete':

            # disk must *not* be allocated to a client in the config
            allocation_list = []
            for client_iqn in config['clients']:
                client_metadata = config['clients'][client_iqn]
                if disk_key in client_metadata['luns']:
                    allocation_list.append(client_iqn)

            if allocation_list:
                return ("Unable to delete {}. Allocated "
                        "to: {}".format(disk_key, ','.join(allocation_list)))

            try:
                with rados.Rados(conffile=settings.config.cephconf) as cluster:
                    with cluster.open_ioctx(kwargs['pool']) as ioctx:
                        with rbd.Image(ioctx, kwargs['image']) as rbd_image:
                            if list(rbd_image.list_snaps()):
                                return ("Unable to delete {}. Snapshots must "
                                        "be removed first.".format(disk_key))
            except rbd.ImageNotFound:
                pass
            except Exception as e:
                return "Unable to query {}: {}".format(disk_key, e)

        return 'ok'
Ejemplo n.º 8
0
    def ui_command_create(self,
                          pool=None,
                          image=None,
                          size=None,
                          count=1,
                          max_data_area_mb=None):
        """
        Create a LUN and assign to the gateway(s).

        The create command supports two request formats;

        Long format  : create pool=<name> image=<name> size=<size> [max_data_area_mb=<buffer_size>]
        Short format : create pool.image <size>

        e.g.
        create pool=rbd image=testimage size=100g ring_buffer_size=16
        create rbd.testimage 100g

        The syntax of each parameter is as follows;
        pool  : Pool and image name may contain a-z, A-Z, 0-9 or '-' chars
        image
        size  : integer, suffixed by the allocation unit - either m/M, g/G or
                t/T representing the MB/GB/TB [1]
        count : integer (default is 1)[2]. If the request provides a count=<n>
                parameter the image name will be used as a prefix, and the count
                used as a suffix to create multiple LUNs from the same request.
                e.g.
                create rbd.test 1g count=5
                -> create 5 LUNs called test1..test5 each of 1GB in size
                   from the rbd pool
        max_data_area_mb : integer, optional size of kernel data ring buffer (MiB).

        Notes.
        1) size does not support decimal representations
        2) Using a count to create multiple LUNs will lock the CLI until all
           LUNs have been created
        """
        # NB the text above is shown on a help create request in the CLI

        if '.' in pool:
            # shorthand version of the command
            self.logger.debug("user provided pool.image format request")

            if image:
                if size:
                    try:
                        count = int(size)
                    except ValueError:
                        self.logger.error("Invalid count provided "
                                          "({} ?)".format(size))
                        return
                size = image
            else:
                self.logger.error("Shorthand command is create <pool>.<image>"
                                  " <size>")
                return
            pool, image = pool.split('.')

        else:
            # long format request
            if not pool or not image or not size:
                self.logger.error("Invalid create: pool, image and size "
                                  "parameters are needed")
                return

        if not valid_size(size):
            self.logger.error("Invalid size requested. Must be an integer, "
                              "suffixed by M, G or T. See help for more info")
            return

        if count:
            if not str(count).isdigit():
                self.logger.error("invalid count format, must be an integer")
                return
        if max_data_area_mb:
            if not str(max_data_area_mb).isdigit():
                self.logger.error(
                    "invalid max data area format, must be an integer in MiB")
                return

        self.logger.debug("CMD: /disks/ create pool={} "
                          "image={} size={} count={} "
                          "max_data_area_mb={}".format(pool, image, size,
                                                       count,
                                                       max_data_area_mb))

        self.create_disk(pool=pool,
                         image=image,
                         size=size,
                         count=count,
                         max_data_area_mb=max_data_area_mb)
Ejemplo n.º 9
0
    def ui_command_create(self,
                          pool=None,
                          image=None,
                          size=None,
                          count=1,
                          **attributes):
        """
        Create a LUN and assign to the gateway(s).

        The create command supports two request formats;

        Long format  : create pool=<name> image=<name> size=<size> [attributes:
                       max_data_area_mb=<buffer_size> osd_op_timeout=<seconds> ...]
        Short format : create pool.image <size>

        e.g.
        create pool=rbd image=testimage size=100g max_data_area_mb=16
        create rbd.testimage 100g

        The syntax of each parameter is as follows;
        pool  : Pool and image name may contain a-z, A-Z, 0-9, '_', or '-'
        image   characters.
        size  : integer, suffixed by the allocation unit - either m/M, g/G or
                t/T representing the MB/GB/TB [1]
        count : integer (default is 1)[2]. If the request provides a count=<n>
                parameter the image name will be used as a prefix, and the count
                used as a suffix to create multiple LUNs from the same request.
                e.g.
                create rbd.test 1g count=5
                -> create 5 LUNs called test1..test5 each of 1GB in size
                   from the rbd pool
        attributes :
        max_data_area_mb : integer, optional size of kernel data ring buffer (MiB).
                           Default 8.
        qfull_timeout: integer, optional time in seconds to wait for ring space.
                       Default 5.
        osd_op_timeout: integer, optional time in seconds to wait for a Ceph op.
                        Default 30.
        hw_max_sectors: integer, optional in units of 512 byte sectors reported to
                        initiators as max IO size. Default 1024.

        Notes.
        1) size does not support decimal representations
        2) Using a count to create multiple LUNs will lock the CLI until all
           LUNs have been created
        """
        # NB the text above is shown on a help create request in the CLI

        if pool and '.' in pool:
            # shorthand version of the command
            self.logger.debug("user provided pool.image format request")

            if image:
                if size:
                    try:
                        count = int(size)
                    except ValueError:
                        self.logger.error("Invalid count provided "
                                          "({} ?)".format(size))
                        return
                size = image
            else:
                self.logger.error("Shorthand command is create <pool>.<image>"
                                  " <size>")
                return
            pool, image = pool.split('.')

        else:
            # long format request
            if not pool or not image or not size:
                self.logger.error("Invalid create: pool, image and size "
                                  "parameters are needed")
                return

        if not valid_size(size):
            self.logger.error("Invalid size requested. Must be an integer, "
                              "suffixed by M, G or T. See help for more info")
            return

        if count:
            if not str(count).isdigit():
                self.logger.error("invalid count format, must be an integer")
                return

        try:
            controls = settings.Settings.normalize_controls(
                attributes, LUN.SETTINGS)
        except ValueError as err:
            self.logger.error(err)
            return

        for k, v in controls.iteritems():
            if not v:
                self.logger.error("Missing value for {}.".format(k))
                return

        self.logger.debug("CMD: /disks/ create pool={} "
                          "image={} size={} count={} "
                          "controls={}".format(pool, image, size, count,
                                               attributes))
        self.create_disk(pool=pool,
                         image=image,
                         size=size,
                         count=count,
                         controls=attributes)
Ejemplo n.º 10
0
    def ui_command_resize(self, size=None):
        """
        The resize command allows you to increase the size of an
        existing rbd image. Attempting to decrease the size of an
        rbd will be ignored.

        size: new size including unit suffix e.g. 300G

        """

        # resize is actually managed by the same lun and api endpoint as
        # create so this logic is very similar to a 'create' request

        if not size:
            self.logger.error(
                "Specify a size value (current size is {})".format(
                    self.size_h))
            return

        size_rqst = size.upper()
        if not valid_size(size_rqst):
            self.logger.error(
                "Size parameter value is not valid syntax (must be of the form 100G, or 1T)"
            )
            return

        new_size = convert_2_bytes(size_rqst)
        if self.size >= new_size:
            # current size is larger, so nothing to do
            self.logger.error(
                "New size isn't larger than the current image size, ignoring request"
            )
            return

        # At this point the size request needs to be honoured
        self.logger.debug("Resizing {} to {}".format(self.image_id, size_rqst))

        local_gw = this_host()
        other_gateways = get_other_gateways(self.parent.parent.target.children)

        # make call to local api server first!
        disk_api = '{}://127.0.0.1:{}/api/disk/{}'.format(
            self.http_mode, settings.config.api_port, self.image_id)

        api_vars = {
            'pool': self.pool,
            'size': size_rqst,
            'owner': local_gw,
            'mode': 'resize'
        }

        self.logger.debug("Processing local LIO instance")
        response = put(disk_api,
                       data=api_vars,
                       auth=(settings.config.api_user,
                             settings.config.api_password),
                       verify=settings.config.api_ssl_verify)

        if response.status_code == 200:
            # rbd resize request successful, so update the local information
            self.logger.debug("- LUN resize complete")
            self.get_meta_data()

            self.logger.debug("Processing other gateways")
            for gw in other_gateways:
                disk_api = '{}://{}:{}/api/disk/{}'.format(
                    self.http_mode, gw, settings.config.api_port,
                    self.image_id)

                response = put(disk_api,
                               data=api_vars,
                               auth=(settings.config.api_user,
                                     settings.config.api_password),
                               verify=settings.config.api_ssl_verify)

                if response.status_code == 200:
                    self.logger.debug(
                        "- LUN resize registered on {}".format(gw))
                else:
                    raise GatewayAPIError(response.text)

        else:
            raise GatewayAPIError(response.text)

        self.logger.info('ok')
Ejemplo n.º 11
0
def ansible_main():

    # Define the fields needs to create/map rbd's the the host(s)
    # NB. features and state are reserved/unused
    fields = {
        "pool": {"required": False, "default": "rbd", "type": "str"},
        "image": {"required": True, "type": "str"},
        "size": {"required": True, "type": "str"},
        "host": {"required": True, "type": "str"},
        "features": {"required": False, "type": "str"},
        "state": {
            "required": False,
            "default": "present",
            "choices": ['present', 'absent'],
            "type": "str"
        },
    }

    # not supporting check mode currently
    module = AnsibleModule(argument_spec=fields,
                           supports_check_mode=False)

    pool = module.params["pool"]
    image = module.params['image']
    size = module.params['size']
    allocating_host = module.params['host']
    desired_state = module.params['state']

    ################################################
    # Validate the parameters passed from Ansible  #
    ################################################
    if not valid_size(size):
        logger.critical("image '{}' has an invalid size specification '{}' "
                        "in the ansible configuration".format(image,
                                                              size))
        module.fail_json(msg="(main) Unable to use the size parameter '{}' "
                             "for image '{}' from the playbook - "
                             "must be a number suffixed by M,G "
                             "or T".format(size,
                                           image))

    # define a lun object and perform some initial parameter validation
    lun = LUN(logger, pool, image, size, allocating_host)
    if lun.error:
        module.fail_json(msg=lun.error_msg)

    logger.info("START - LUN configuration started for {}/{}".format(pool,
                                                                     image))

    # attempt to create/allocate the LUN for LIO
    lun.manage(desired_state)
    if lun.error:
        module.fail_json(msg=lun.error_msg)

    if lun.num_changes == 0:
        logger.info("END   - No changes needed")
    else:
        logger.info("END   - {} configuration changes "
                    "made".format(lun.num_changes))

    module.exit_json(changed=(lun.num_changes > 0),
                     meta={"msg": "Configuration updated"})