def target(target_iqn=None): """ Handle the definition of the iscsi target name The target is added to the configuration object, seeding the configuration for ALL gateways :param target_iqn: IQN of the target each gateway will use **RESTRICTED** """ if request.method == 'PUT': gateway_ip_list = [] target = GWTarget(logger, str(target_iqn), gateway_ip_list) if target.error: logger.error("Unable to create an instance of the GWTarget class") return jsonify(message="GWTarget problem - " "{}".format(target.error_msg)), 500 target.manage('init') if target.error: logger.error("Failure during gateway 'init' processing") return jsonify( message="iscsi target 'init' process failed " "for {} - {}".format(target_iqn, target.error_msg)), 500 return jsonify(message="Target defined successfully"), 200 else: # return unrecognised request return jsonify(message="Invalid method ({}) to target " "API".format(request.method)), 405
def define_gateway(): """ define the iSCSI target and tpgs :return: (object) gateway object """ gw_ip_list = config.config['gateways'].get('ip_list', None) gw_iqn = config.config['gateways'].get('iqn', None) # Gateway Definition : Handle the creation of the Target/TPG(s) and Portals # Although we create the tpgs, we flick the enable_portal flag off so the # enabled tpg will not have an outside IP address. This prevents clients # from logging in too early, failing and giving up because the nodeACL # hasn't been defined yet (yes Windows I'm looking at you!) # first check if there are tpgs already in LIO (True) - this would indicate # a restart or reload call has been made. If the tpg count is 0, this is a # boot time request gateway = GWTarget(logger, gw_iqn, gw_ip_list, enable_portal=portals_active()) if gateway.error: halt("Error initializing iSCSI target: {}".format(gateway.error_msg)) gateway.manage('target') if gateway.error: halt("Error creating the iSCSI target (target, TPGs, Portals): " "{}".format(gateway.error_msg)) return gateway
def ansible_main(): # Configures the gateway on the host. All images defined are added to # the default tpg for later allocation to clients fields = { "gateway_iqn": { "required": True, "type": "str" }, "gateway_ip_list": { "required": True }, # "type": "list"}, "mode": { "required": True, "choices": ['target', 'map'] } } module = AnsibleModule( argument_spec=fields, # noqa: F405 supports_check_mode=False) cfg = Config(logger) if cfg.config['version'] > 3: module.fail_json(msg="Unsupported iscsigws.yml/iscsi-gws.yml setting " "detected. Remove depreciated iSCSI target, LUN, " "client, and gateway settings from " "iscsigws.yml/iscsi-gws.yml. See " "iscsigws.yml.sample for list of supported " "settings") gateway_iqn = module.params['gateway_iqn'] gateway_ip_list = module.params['gateway_ip_list'].split(',') mode = module.params['mode'] if not valid_ip(gateway_ip_list): module.fail_json(msg="Invalid gateway IP address(es) provided - port " "22 check failed ({})".format(gateway_ip_list)) logger.info("START - GATEWAY configuration started - mode {}".format(mode)) gateway = GWTarget(logger, gateway_iqn, gateway_ip_list) if gateway.error: logger.critical("(ansible_main) Gateway init failed - " "{}".format(gateway.error_msg)) module.fail_json(msg="iSCSI gateway initialisation failed " "({})".format(gateway.error_msg)) gateway.manage(mode) if gateway.error: logger.critical("(main) Gateway creation or load failed, " "unable to continue") module.fail_json(msg="iSCSI gateway creation/load failure " "({})".format(gateway.error_msg)) logger.info("END - GATEWAY configuration complete") module.exit_json(changed=gateway.changes_made, meta={"msg": "Gateway setup complete"})
def ansible_main(): # Configures the gateway on the host. All images defined are added to # the default tpg for later allocation to clients fields = {"gateway_iqn": {"required": True, "type": "str"}, "gateway_ip_list": {"required": True}, # "type": "list"}, "mode": { "required": True, "choices": ['target', 'map'] } } module = AnsibleModule(argument_spec=fields, supports_check_mode=False) gateway_iqn = module.params['gateway_iqn'] gateway_ip_list = module.params['gateway_ip_list'].split(',') mode = module.params['mode'] if not valid_ip(gateway_ip_list): module.fail_json(msg="Invalid gateway IP address(es) provided - port 22 check failed ({})".format(gateway_ip_list)) logger.info("START - GATEWAY configuration started in mode {}".format(mode)) gateway = GWTarget(logger, gateway_iqn, gateway_ip_list) if gateway.error: logger.critical("(ansible_main) Gateway init failed - {}".format(gateway.error_msg)) module.fail_json(msg="iSCSI gateway initialisation failed ({})".format(gateway.error_msg)) gateway.manage(mode) if gateway.error: logger.critical("(main) Gateway creation or load failed, unable to continue") module.fail_json(msg="iSCSI gateway creation/load failure ({})".format(gateway.error_msg)) logger.info("END - GATEWAY configuration complete") module.exit_json(changed=gateway.changes_made, meta={"msg": "Gateway setup complete"})
def activate(self): disk = self.config.config['disks'].get(self.config_key, None) if not disk: raise CephiSCSIError("Image {} not found.".format(self.image)) wwn = disk.get('wwn', None) if not wwn: raise CephiSCSIError("LUN {} missing wwn".format(self.image)) # re-add backend storage object so = self.lio_stg_object() if not so: self.add_dev_to_lio(wwn) if self.error: raise CephiSCSIError("LUN activate failure - {}".format( self.error_msg)) # re-add LUN to target local_gw = this_host() targets_items = [ item for item in self.config.config['targets'].items() if self.config_key in item[1]['disks'] and local_gw in item[1]['portals'] ] for target_iqn, target in targets_items: ip_list = target['ip_list'] # Add the mapping for the lun to ensure the block device is # present on all TPG's gateway = GWTarget(self.logger, target_iqn, ip_list) gateway.manage('map') if gateway.error: raise CephiSCSIError("LUN mapping failed - {}".format( gateway.error_msg)) # re-map LUN to hosts client_err = '' for client_iqn in target['clients']: client_metadata = target['clients'][client_iqn] if client_metadata.get('group_name', ''): continue image_list = list(client_metadata['luns'].keys()) if self.config_key not in image_list: continue client_chap = CHAP(client_metadata['auth']['chap']) chap_str = client_chap.chap_str if client_chap.error: raise CephiSCSIError("Password decode issue : " "{}".format(client_chap.error_msg)) client_chap_mutual = CHAP( client_metadata['auth']['chap_mutual']) chap_mutual_str = client_chap_mutual.chap_str if client_chap_mutual.error: raise CephiSCSIError("Password decode issue : " "{}".format( client_chap_mutual.error_msg)) client = GWClient(self.logger, client_iqn, image_list, chap_str, chap_mutual_str, target_iqn) client.manage('present') if client.error: client_err = "LUN mapping failed {} - {}".format( client_iqn, client.error_msg) # re-map LUN to host groups for group_name in target['groups']: host_group = target['groups'][group_name] members = host_group.get('members') disks = host_group.get('disks').keys() if self.config_key not in disks: continue group = Group(self.logger, target_iqn, group_name, members, disks) group.apply() if group.error: client_err = "LUN mapping failed {} - {}".format( group_name, group.error_msg) if client_err: raise CephiSCSIError(client_err)
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
def manage_gateway(gateway_name=None): """ Manage the local iSCSI gateway definition Internal Use ONLY Gateways may be be added(PUT), queried (GET) or deleted (DELETE) from the configuration :param gateway_name: (str) gateway name, normally the DNS name **RESTRICTED** """ if request.method == 'GET': if gateway_name in config.config['gateways']: return jsonify(config.config['gateways'][gateway_name]), 200 else: return jsonify(message="Gateway doesn't exist in the " "configuration"), 404 elif request.method == 'PUT': # the parameters need to be cast to str for compatibility # with the comparison logic in common.config.add_item logger.debug("Attempting create of gateway {}".format(gateway_name)) gateway_ips = str(request.form['gateway_ip_list']) target_iqn = str(request.form['target_iqn']) target_mode = str(request.form.get('mode', 'target')) gateway_ip_list = gateway_ips.split(',') gateway = GWTarget(logger, target_iqn, gateway_ip_list) if gateway.error: logger.error("Unable to create an instance of the GWTarget class") return jsonify(message="Failed to create the gateway"), 500 gateway.manage(target_mode) if gateway.error: logger.error("manage({}) logic failed for {}".format( target_mode, gateway_name)) return jsonify(message="Failed to create the gateway"), 500 logger.info("created the gateway") if target_mode == 'target': # refresh only for target definitions, since that's when the config # will actually change logger.info("refreshing the configuration after the gateway " "creation") config.refresh() return jsonify(message="Gateway defined/mapped"), 200 else: # DELETE gateway request gateway = GWTarget(logger, config.config['gateways']['iqn'], '') if gateway.error: return jsonify(message="Failed to connect to the gateway"), 500 gateway.manage('clearconfig') if gateway.error: logger.error("clearconfig failed for {} : " "{}".format(gateway_name, gateway.error_msg)) return jsonify(message="Unable to remove {} from the " "configuration".format(gateway_name)), 400 else: config.refresh() return jsonify(message="Gateway removed successfully"), 200