def all_client_luns(client_iqn): """ Coordinate the addition(PUT) and removal(DELETE) of a disk from a client :param client_iqn: (str) IQN of the client :param disk: (str) rbd image name of the format pool.image **RESTRICTED** """ http_mode = 'https' if settings.config.api_secure else 'http' local_gw = this_host() logger.debug("this host is {}".format(local_gw)) gateways = [ key for key in config.config['gateways'] if isinstance(config.config['gateways'][key], dict) ] logger.debug("other gateways - {}".format(gateways)) gateways.remove(local_gw) disk = request.form.get('disk') lun_list = config.config['clients'][client_iqn]['luns'].keys() if request.method == 'PUT': lun_list.append(disk) else: # this is a delete request if disk in lun_list: lun_list.remove(disk) else: return jsonify(message="disk not mapped to client"), 400 chap_obj = CHAP(config.config['clients'][client_iqn]['auth']['chap']) chap = "{}/{}".format(chap_obj.user, chap_obj.password) image_list = ','.join(lun_list) client_usable = valid_client(mode='disk', client_iqn=client_iqn, image_list=image_list) if client_usable != 'ok': logger.error("Bad disk request for client {} : " "{}".format(client_iqn, client_usable)) return jsonify(message=client_usable), 400 # committing host is the local LIO node api_vars = { "committing_host": local_gw, "image_list": image_list, "chap": chap } clientlun_api = '{}://127.0.0.1:{}/api/clientlun/{}'.format( http_mode, settings.config.api_port, client_iqn) api = APIRequest(clientlun_api, data=api_vars) api.put() if api.response.status_code == 200: logger.info("disk mapping update for {} successful".format(client_iqn)) for gw in gateways: clientlun_api = '{}://{}:{}/api/clientlun/{}'.format( http_mode, gw, settings.config.api_port, client_iqn) logger.debug("Updating disk map for {} on GW {}".format( client_iqn, gw)) api = APIRequest(clientlun_api, data=api_vars) api.put() if api.response.status_code == 200: logger.debug("gateway '{}' updated".format(gw)) continue else: logger.error("disk mapping update on {} failed".format(gw)) return jsonify(message="disk map updated failed on " "{}".format(gw)), \ api.response.status_code return jsonify(message="ok"), 200 else: # disk map update failed at the first hurdle! logger.error("disk map update failed on the local LIO instance") return jsonify(message="failed to update local LIO instance"), \ api.response.status_code
def all_client(client_iqn): """ Handle the client create/delete actions across gateways :param client_iqn: (str) IQN of the client to create or delete **RESTRICTED** Examples: curl --insecure --user admin:admin -X PUT https://192.168.122.69:5001/api/all_client/iqn.1994-05.com.redhat:myhost4 curl --insecure --user admin:admin -X DELETE https://192.168.122.69:5001/api/all_client/iqn.1994-05.com.redhat:myhost4 """ method = {"PUT": 'create', "DELETE": 'delete'} http_mode = 'https' if settings.config.api_secure else 'http' local_gw = this_host() logger.debug("this host is {}".format(local_gw)) gateways = [ key for key in config.config['gateways'] if isinstance(config.config['gateways'][key], dict) ] logger.debug("other gateways - {}".format(gateways)) gateways.remove(local_gw) # committing host is the node responsible for updating the config object api_vars = {"committing_host": local_gw} # validate the PUT/DELETE request first client_usable = valid_client(mode=method[request.method], client_iqn=client_iqn) if client_usable != 'ok': return jsonify(message=client_usable), 400 if request.method == 'PUT': client_api = '{}://127.0.0.1:{}/api/client/{}'.format( http_mode, settings.config.api_port, client_iqn) logger.debug("Processing client CREATE for {}".format(client_iqn)) api = APIRequest(client_api, data=api_vars) api.put() if api.response.status_code == 200: logger.info("Client {} added to local LIO".format(client_iqn)) for gw in gateways: client_api = '{}://{}:{}/api/client/{}'.format( http_mode, gw, settings.config.api_port, client_iqn) logger.debug("sending request to {} to create {}".format( gw, client_iqn)) api = APIRequest(client_api, data=api_vars) api.put() if api.response.status_code == 200: logger.info("Client '{}' added to {}".format( client_iqn, gw)) continue else: # client create failed against the remote LIO instance msg = api.response.json()['message'] logger.error("Client create for {} failed on {} " ": {}".format(client_iqn, gw, msg)) return jsonify(message=msg), 500 # all gateways processed return a success state to the caller return jsonify(message='ok'), 200 else: # client create failed against the local LIO instance msg = api.response.json()['message'] logger.error("Client create on local LIO instance failed " "for {} : {}".format(client_iqn, msg)) return jsonify(message=msg), 500 else: # DELETE client request # Process flow: remote gateways > local > delete config object entry for gw in gateways: client_api = '{}://{}:{}/api/client/{}'.format( http_mode, gw, settings.config.api_port, client_iqn) logger.info("- removing '{}' from {}".format(client_iqn, gw)) api = APIRequest(client_api, data=api_vars) api.delete() if api.response.status_code == 200: logger.info("- '{}' removed".format(client_iqn)) continue elif api.response.status_code == 400: logger.error("- '{}' is in use on {}".format(client_iqn, gw)) return jsonify(message="Client in use"), 400 else: msg = api.response.json()['message'] logger.error("Failed to remove {} from {}".format( client_iqn, gw)) return jsonify(message="failed to remove client '{}' on " "{}".format(client_iqn, msg)), 500 # At this point the other gateways have removed the client, so # remove from the local LIO instance client_api = '{}://127.0.0.1:{}/api/client/{}'.format( http_mode, settings.config.api_port, client_iqn) api = APIRequest(client_api, data=api_vars) api.delete() if api.response.status_code == 200: logger.info("successfully removed '{}'".format(client_iqn)) return jsonify(message="ok"), 200 else: return jsonify(message="Unable to delete {} from local LIO " "instance".format(client_iqn)), \ api.response.status_code
def all_client_auth(client_iqn): """ Coordinate client authentication changes across each gateway node The following parameters are needed to manage client auth :param client_iqn: (str) client IQN name :param chap: (str) chap string of the form user/password or '' **RESTRICTED** """ http_mode = 'https' if settings.config.api_secure else 'http' local_gw = this_host() logger.debug("this host is {}".format(local_gw)) gateways = [ key for key in config.config['gateways'] if isinstance(config.config['gateways'][key], dict) ] logger.debug("other gateways - {}".format(gateways)) gateways.remove(local_gw) lun_list = config.config['clients'][client_iqn]['luns'].keys() image_list = ','.join(lun_list) chap = request.form.get('chap') client_usable = valid_client(mode='auth', client_iqn=client_iqn, chap=chap) if client_usable != 'ok': logger.error("BAD auth request from {}".format(request.remote_addr)) return jsonify(message=client_usable), 400 api_vars = { "committing_host": local_gw, "image_list": image_list, "chap": chap } clientauth_api = '{}://127.0.0.1:{}/api/clientauth/{}'.format( http_mode, settings.config.api_port, client_iqn) logger.debug("Issuing client update to local gw for {}".format(client_iqn)) api = APIRequest(clientauth_api, data=api_vars) api.put() if api.response.status_code == 200: logger.debug("Client update succeeded on local LIO") for gw in gateways: clientauth_api = '{}://{}:{}/api/clientauth/{}'.format( http_mode, gw, settings.config.api_port, client_iqn) logger.debug("updating client {} on {}".format(client_iqn, gw)) api = APIRequest(clientauth_api, data=api_vars) api.put() if api.response.status_code == 200: logger.info("client update successful on {}".format(gw)) continue else: return jsonify(message="client update failed on " "{}".format(gw)), \ api.response.status_code logger.info("All gateways updated") return jsonify(message="ok"), 200 else: # the local update failed, so abort further updates return jsonify(message="Client updated failed on local " "LIO instance"), api.response.status_code