def delete_infrastructure(infra_id): """ Delete the specified infrastructure """ logger = custom_logger.CustomAdapter(logging.getLogger(__name__), {'id': infra_id}) if 'type' not in request.args: db = database.get_db() if db.connect(): # Get current status of infrastructure (_, status, _, _, _) = db.deployment_get_im_infra_id(infra_id) # If it has already been deleted, don't do anything but return success if status == 'deleted': db.close() logger.info('Infrastructure has already been deleted') return jsonify({}), 200 elif status == 'deletion-requested': db.close() logger.info( 'Infrastructure deletion has already been requested') return jsonify({}), 200 success = db.deployment_update_status_with_retries( infra_id, 'deletion-requested') if success: db.close() logger.info( 'Infrastructure deletion request successfully initiated') return jsonify({}), 200 logger.critical( 'Infrastructure deletion request failed, possibly a database issue' ) return jsonify({}), 400 elif request.args.get('type') == 'im': cloud = request.args.get('cloud') db = database.get_db() if db.connect(): clouds_info_list = utilities.create_clouds_list( CONFIG.get('clouds', 'path')) token = tokens.get_token(cloud, None, db, clouds_info_list) db.close() im_auth = utilities.create_im_auth(cloud, token, clouds_info_list) client = imclient.IMClient(url=CONFIG.get('im', 'url'), data=im_auth) (status, msg) = client.getauth() if status != 0: logger.critical('Error reading IM auth file: %s', msg) return jsonify({}), 400 client.destroy(infra_id, 30) return jsonify({}), 200 return jsonify({}), 400
def deployer(infra_id): """ Deploy infrastructure """ logging.basicConfig(filename=CONFIG.get('logs', 'filename').replace( '.log', '-deploy-%s.log' % infra_id), level=logging.INFO, format='%(asctime)s %(message)s') logging.info('Starting deployment of infrastructure %s', infra_id) # Random sleep time.sleep(random.randint(0, 4)) db = database.get_db() if db.connect(): logging.info('Connected to DB, about to deploy infrastructure for job') # Deploy infrastructure success = provisioner.deploy_job(db, infra_id) if success is None: logging.info('Setting status to unable - permanent failure') db.deployment_update_status_with_retries(infra_id, 'unable') elif not success: logging.info('Setting status to waiting - temporary failure') db.deployment_update_status_with_retries(infra_id, 'waiting') db.close() if not success: logging.critical('Unable to deploy infrastructure on any cloud') logging.info('Completed deploying infrastructure')
def get_infrastructure(infra_id): """ Get current status of specified infrastructure """ logger = custom_logger.CustomAdapter(logging.getLogger(__name__), {'id': infra_id}) logger.info('Infrastructure status request') im_infra_id = None status = None status_reason = None cloud = None db = database.get_db() if db.connect(): (im_infra_id, status, cloud, _, _) = db.deployment_get_im_infra_id(infra_id) if status in ('unable', 'failed'): status_reason = db.deployment_get_status_reason(infra_id) db.close() if status: return jsonify({ 'status': status, 'status_reason': status_reason, 'cloud': cloud, 'infra_id': im_infra_id }), 200 return jsonify({'status': 'invalid'}), 404
def get_infrastructures(): """ Get list of infrastructures in the specified state or type """ if 'status' in request.args and 'type' not in request.args: cloud = None if 'cloud' in request.args: cloud = request.args.get('cloud') db = database.get_db() if db.connect(): infra = db.deployment_get_infra_in_state_cloud( request.args.get('status'), cloud) db.close() return jsonify(infra), 200 elif 'type' in request.args and 'cloud' in request.args: if request.args.get('type') == 'im': cloud = request.args.get('cloud') db = database.get_db() if db.connect(): clouds_info_list = utilities.create_clouds_list( CONFIG.get('clouds', 'path')) token = tokens.get_token(cloud, None, db, clouds_info_list) db.close() im_auth = utilities.create_im_auth(cloud, token, clouds_info_list) client = imclient.IMClient(url=CONFIG.get('im', 'url'), data=im_auth) (status, msg) = client.getauth() if status != 0: logger.critical('Error reading IM auth file: %s', msg) return jsonify({}), 400 (status, ids) = client.list_infra_ids(10) im_list = [] if ids: for uri in ids: pieces = uri.split('/') im_id = pieces[len(pieces) - 1] im_list.append(im_id) return jsonify(im_list), 200 return jsonify({}), 400
def create_infrastructure(): """ Create infrastructure """ using_idempotency_key = False if request.headers.get('Idempotency-Key'): uid = request.headers.get('Idempotency-Key') using_idempotency_key = True if not utilities.valid_uuid(uid): uid = str(uuid.uuid4()) else: uid = str(uuid.uuid4()) logger = custom_logger.CustomAdapter(logging.getLogger(__name__), {'id': uid}) if using_idempotency_key: logger.info('Using Idempotency-Key as infra id') identity = None if 'identity' in request.get_json(): identity = request.get_json()['identity'] identifier = None if 'identifier' in request.get_json(): identifier = request.get_json()['identifier'] if 'dryrun' in request.get_json(): sites = return_sites.return_sites(request.get_json()) return jsonify({'sites': sites}), 200 db = database.get_db() if db.connect(): check = db.deployment_check_infra_id(uid) if check == 1: success = db.deployment_create_with_retries( uid, request.get_json(), identity, identifier) db.close() if success: logger.info( 'Infrastructure creation request successfully initiated') return jsonify({'id': uid}), 201 elif check == 0: db.close() logger.info('Duplicate Idempotency-Key used') return jsonify({'id': uid}), 200 else: db.close() logger.critical( 'Unable to check if infrastructure ID was already used') logger.critical( 'Infrastructure creation request failed, possibly a database issue') return jsonify({'id': uid}), 400
def destroyer(infra_id): """ Destroy infrastructure """ logging.basicConfig(filename=CONFIG.get('logs', 'filename').replace( '.log', '-destroy-%s.log' % infra_id), level=logging.INFO, format='%(asctime)s %(message)s') logging.info('Starting deletion of infrastructure %s', infra_id) # Random sleep time.sleep(random.randint(0, 4)) db = database.get_db() if db.connect(): destroy.delete(infra_id) db.close() logging.info('Completed deleting infrastructure')
def create_user_credentials(): """ Insert or update user credentials """ username = None refresh_token = None data = request.get_json() if 'username' in data: username = data['username'] if 'refresh_token' in data: refresh_token = data['refresh_token'] if not username or not refresh_token: return jsonify({'error': 'json data not valid'}), 400 db = database.get_db() if db.connect(): status = db.set_user_credentials(username, refresh_token) db.close() if status: return jsonify({}), 201 return jsonify({}), 400
# Setup handlers for the root logger handler = RotatingFileHandler(CONFIG.get('logs', 'filename'), maxBytes=int(CONFIG.get('logs', 'max_bytes')), backupCount=int(CONFIG.get('logs', 'num'))) formatter = logging.Formatter( '%(asctime)s %(levelname)s [%(name)s] %(message)s') handler.setFormatter(formatter) logger = logging.getLogger() logger.addHandler(handler) logger.setLevel(logging.INFO) # Create flask application app = Flask(__name__) # Initialize DB if necessary dbi = database.get_db() dbi.init() def authenticate(): """ Sends a 401 response """ return jsonify({'error': 'Authentication failure'}), 401 def valid_credentials(username, password): """ Check if the supplied credentials are valid """ return username == CONFIG.get(
def delete(unique_id): """ Delete the infrastructure with the specified id """ logger.info('Deleting infrastructure') db = database.get_db() db.connect() (im_infra_id, infra_status, cloud, _, _) = db.deployment_get_im_infra_id(unique_id) logger.info('Obtained IM id %s and cloud %s and status %s', im_infra_id, cloud, infra_status) # Get full list of cloud info clouds_info_list = utilities.create_clouds_list( CONFIG.get('clouds', 'path')) # Deterime resource type resource_type = None for cloud_info in clouds_info_list: if cloud_info['name'] == cloud: resource_type = cloud_info['type'] if im_infra_id and cloud: if resource_type == 'cloud': match_obj_name = re.match( r'\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b', im_infra_id) if match_obj_name: logger.info('Deleting cloud infrastructure with IM id %s', im_infra_id) # Get the identity of the user who created the infrastructure identity = db.deployment_get_identity(unique_id) # Check & get auth token if necessary token = tokens.get_token(cloud, identity, db, clouds_info_list) # Setup Infrastructure Manager client im_auth = utilities.create_im_auth(cloud, token, clouds_info_list) client = imclient.IMClient(url=CONFIG.get('im', 'url'), data=im_auth) (status, msg) = client.getauth() if status != 0: logger.critical('Error reading IM auth file: %s', msg) db.close() return False destroyed = destroy(client, im_infra_id) if destroyed: db.deployment_update_status_with_retries( unique_id, 'deleted') logger.info( 'Destroyed infrastructure with IM infrastructure id %s', im_infra_id) else: db.deployment_update_status_with_retries( unique_id, 'deletion-failed') logger.critical( 'Unable to destroy infrastructure with IM infrastructure id %s', im_infra_id) return False else: logger.critical('IM infrastructure id %s does not match regex', im_infra_id) db.deployment_update_status_with_retries(unique_id, 'deleted') elif resource_type == 'batch': match_obj_name = re.match(r'[\d]+', im_infra_id) if match_obj_name: logger.info( 'Deleting batch infrastructure with HTCondor job id %s', im_infra_id) #client = htcondorclient.HTCondorClient() #client.destroy(int(im_infra_id)) else: logger.info( 'No need to destroy infrastructure because resource infrastructure id is %s, resource name is %s, resource type is %s', im_infra_id, cloud, resource_type) db.deployment_update_status_with_retries(unique_id, 'deleted') db.close() return True