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"})
def define_luns(gateway): """ define the disks in the config to LIO :param gateway: (object) gateway object - used for mapping :return: None """ local_gw = this_host() # sort the disks dict keys, so the disks are registered in a specific # sequence disks = config.config['disks'] srtd_disks = sorted(disks) pools = {disks[disk_key]['pool'] for disk_key in srtd_disks} if pools: with rados.Rados(conffile=settings.config.cephconf) as cluster: for pool in pools: logger.debug("Processing rbd's in '{}' pool".format(pool)) with cluster.open_ioctx(pool) as ioctx: pool_disks = [disk_key for disk_key in srtd_disks if disk_key.startswith(pool)] for disk_key in pool_disks: pool, image_name = disk_key.split('.') try: with rbd.Image(ioctx, image_name) as rbd_image: image_bytes = rbd_image.size() image_size_h = human_size(image_bytes) lun = LUN(logger, pool, image_name, image_size_h, local_gw) if lun.error: halt("Error defining rbd image " "{}".format(disk_key)) lun.allocate() if lun.error: halt("Error unable to register {} with " "LIO - {}".format(disk_key, lun.error_msg)) except rbd.ImageNotFound: halt("Disk '{}' defined to the config, but image " "'{}' can not be found in " "'{}' pool".format(disk_key, image_name, pool)) # Gateway Mapping : Map the LUN's registered to all tpg's within the # LIO target gateway.manage('map') if gateway.error: halt("Error mapping the LUNs to the tpg's within the iscsi Target") else: logger.info("No LUNs to export")
def manage_disk(image_id): """ Manage a disk definition on the local gateway Internal Use ONLY Disks can be created and added to each gateway, or deleted through this call :param image_id: (str) of the form pool.image_name **RESTRICTED** """ if request.method == 'GET': if image_id in config.config['disks']: return jsonify(config.config["disks"][image_id]), 200 else: return jsonify(message="rbd image {} not " "found".format(image_id)), 404 elif request.method == 'PUT': # A put is for either a create or a resize # put('http://127.0.0.1:5000/api/disk/rbd.ansible3',data={'pool': 'rbd','size': '3G','owner':'ceph-1'}) rqst_fields = set(request.form.keys()) if rqst_fields.issuperset(("pool", "size", "owner", "mode")): image_name = str(image_id.split('.', 1)[1]) lun = LUN(logger, str(request.form['pool']), image_name, str(request.form['size']), str(request.form['owner'])) if lun.error: logger.error("Unable to create a LUN instance" " : {}".format(lun.error_msg)) return jsonify(message="Unable to establish LUN instance"), 500 lun.allocate() if lun.error: logger.error("LUN alloc problem - {}".format(lun.error_msg)) return jsonify(message="LUN allocation failure"), 500 if request.form['mode'] == 'create': # new disk is allocated, so refresh the local config object config.refresh() iqn = config.config['gateways']['iqn'] ip_list = config.config['gateways']['ip_list'] # Add the mapping for the lun to ensure the block device is # present on all TPG's gateway = GWTarget(logger, iqn, ip_list) gateway.manage('map') if gateway.error: logger.error("LUN mapping failed : " "".format(gateway.error_msg)) return jsonify(message="LUN map failed"), 500 return jsonify(message="LUN created"), 200 elif request.form['mode'] == 'resize': return jsonify(message="LUN resized"), 200 else: # this is an invalid request return jsonify(message="Invalid Request - need to provide" "pool, size and owner"), 400 else: # DELETE request # let's assume that the request has been validated by the caller # if valid_request(request.remote_addr): purge_host = request.form['purge_host'] pool, image = image_id.split('.', 1) lun = LUN(logger, pool, image, '0G', purge_host) if lun.error: # problem defining the LUN instance logger.error("Error initialising the LUN : " "{}".format(lun.error_msg)) return jsonify(message="Error establishing LUN instance"), 500 lun.remove_lun() if lun.error: if 'allocated to' in lun.error_msg: # attempted to remove rbd that is still allocated to a client status_code = 400 else: status_code = 500 logger.error("LUN remove failed : {}".format(lun.error_msg)) return jsonify(message="Failed to remove the LUN"), status_code config.refresh() return jsonify(message="LUN removed"), 200