def launch(): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger(request, session['email']) access_logger.launch(request.form['demoChoice']) demo = request.form['demoChoice'].lower().replace(' ', '-') command = [ 'DEMO_AWS_ACCESS_KEY=%s' % os.environ['DEMO_AWS_ACCESS_KEY'], 'DEMO_AWS_SECRET_KEY=%s' % os.environ['DEMO_AWS_SECRET_KEY'], 'USER_EMAIL=%s' % session['email'], 'DEMO=%s' % demo, 'TTL=%s' % request.form['ttl'], 'PORT=%s' % APP_PORTS[demo], 'SIZE=%s' % request.form['clustersize'], 'MODE=-k', '%s/vagrant/multi-node-demo/new-cluster' % top_level_directory, '&' ] msg(access_logger, ' '.join(command[4:]), 'debug') msg(access_logger, 'Launching new demo: %s.' % demo) logger.info('Executing: %s', ' '.join(command)) os.system(' '.join(command)) return redirect(url_for('dashboard_api.index'))
def demo_launches(): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger(request, session['email'], init_log=False) if 'admin' not in session: msg(access_logger, 'Enable admin privileges first.', 'error') return redirect(request.referrer) msg(access_logger, 'This query is expensive. Please do not refresh more than needed.', 'warn', log=False) history = access_logger.get_demo_launches() headings = ['demo', 'user', 'time'] if 'advanced' in request.args: headings += ['form_variables', 'request'] description = '''Views: <a href="{0}">Simple</a> | <a href="{0}?advanced">Advanced</a> '''.format(request.url_rule) return render_template('history.jinja2', title='Launch History (by Demo)', description=description, headings=headings, history=history)
def kill(): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger(request, session['email']) reservation_ids = request.args['reservation_ids'] success = False failure = False for reservation_id in reservation_ids.split(','): result = ec2.kill_reservation(reservation_id) if result: success = True else: failure = True if success: msg(access_logger, 'Instance(s) terminated successfully.', 'success') if failure: msg(access_logger, 'Instance termination(s) may not have succeeded.', 'warn') return redirect(url_for('dashboard_api.index'))
def error_handling(access_logger, response, postvars, state): # tag the instances appropriately reservation_id = ec2.find_reservation_id_by_tag('cluster_name', postvars['full_name']) ec2.tag_reservation(reservation_id, 'status', 'Failure seen on startup. Discard cluster.') # alert the user by flash message msg(access_logger, 'Error seen on %s: %s' % (state, str(response)), 'error') return 'ctool.jinja2'
def admin_history(page=0): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger(request, session['email'], init_log=False) if 'admin' not in session: msg(access_logger, 'Enable admin privileges first.', 'error') return redirect(request.referrer) msg(access_logger, 'This query is expensive. Please do not refresh more than needed.', 'warn', log=False) date = datetime.datetime.combine(datetime.date.today(), datetime.datetime.min.time()) date = date + datetime.timedelta(days=-1 * page) page_range = 9 start_range = page - page_range / 2 if (page - page_range / 2) > 0 else 0 paging = { 'date': datetime.date.today() + datetime.timedelta(days=-1 * page), 'page': page, 'start_range': start_range, 'end_range': start_range + page_range, 'back': page - 1 if (page - 1) > 0 else 0, 'forward': page + 1 } history = access_logger.get_access_log(date) headings = [ 'user', 'request', 'request_update', 'method', 'endpoint', 'level', 'message', 'form_variables', 'get_variables', ] return render_template('history.jinja2', history_log=True, title='Admin History', paging=paging, headings=headings, history=history)
def ttl(): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger(request, session['email']) request_ttl = int(request.form['ttl']) reservation_ids = request.form['reservation-ids'] for reservation_id in reservation_ids.split(','): ec2.tag_reservation(reservation_id, 'ttl', request_ttl) msg(access_logger, 'TTL updated to %s.' % request_ttl) return redirect(url_for('dashboard_api.index'))
def start_opscenter(access_logger, postvars, reservation_id): if postvars['opscenter-install'] == 'yes': ec2.tag_reservation(reservation_id, 'status', 'Starting opscenter...') start_command = 'ctool' \ ' --provider %(cloud-option)s' \ ' start' \ ' %(full_name)s' \ ' opscenter' start_command = start_command % postvars msg(access_logger, start_command) logger.info('Executing: %s', start_command) response = execute.run(start_command) if response.stderr: return response
def start(access_logger, postvars, reservation_id): ec2.tag_reservation(reservation_id, 'status', 'Starting %(product-name)s...' % postvars) start_command = 'ctool' \ ' --provider %(cloud-option)s' \ ' start' \ ' %(full_name)s' \ ' %(product-name)s' start_command = start_command % postvars msg(access_logger, start_command) logger.info('Executing: %s', start_command) response = execute.run(start_command) if response.stderr: return response
def remove_admin(): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger(request, session['email'], init_log=False) if 'admin' not in session: msg(access_logger, 'Enable admin privileges first.', 'error') return redirect(request.referrer) if 'email' in request.args and request.args['email']: current_app.cluster.set_admin(request.args['email'], False) else: msg(access_logger, 'Please specify an email address.', 'warn') return redirect(url_for('admin_api.add_admin'))
def login(): access_logger = current_app.cluster.get_access_logger(request) if request.method == 'POST': user_record = current_app.cluster.get_user(request.form['email']) password_hash = auth.hash(request.form['password'], current_app.secret_key) if user_record and user_record[0]['password_hash'] == password_hash: msg(access_logger, 'Login successful.', 'debug') session['email'] = request.form['email'] session['admin'] = user_record[0]['admin'] return redirect(url_for('dashboard_api.index')) else: msg(access_logger, 'Authentication failed.', 'error') return render_template('login.jinja2') else: return render_template('login.jinja2')
def last_seen(): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger(request, session['email'], init_log=False) if 'admin' not in session: msg(access_logger, 'Enable admin privileges first.', 'error') return redirect(request.referrer) history = access_logger.get_last_seen_log() headings = ['user', 'date'] return render_template('history.jinja2', title='Last Seen', headings=headings, history=history)
def start_agent(access_logger, postvars, reservation_id): if postvars['opscenter-install'] == 'yes': ec2.tag_reservation(reservation_id, 'status', 'Starting DataStax Agents...') start_command = 'ctool' \ ' --provider %(cloud-option)s' \ ' run' \ ' %(full_name)s' \ ' all' \ ' "sudo service datastax-agent start"' start_command = start_command % postvars msg(access_logger, start_command) logger.info('Executing: %s', start_command) response = execute.run(start_command) if response.stderr: return response
def install_opscenter(access_logger, postvars, reservation_id): if postvars['opscenter-install'] == 'yes': ec2.tag_reservation(reservation_id, 'status', 'Installing opscenter...') install_command = 'ctool' \ ' --provider %(cloud-option)s' \ ' install' \ ' --repo qa' \ ' --version_or_branch %(opscenter-version)s' \ ' %(full_name)s' \ ' opscenter' install_command = install_command % postvars msg(access_logger, install_command) logger.info('Executing: %s', install_command) response = execute.run(install_command) if response.stderr: return response
def admin_history(page=0): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger(request, session['email'], init_log=False) if 'admin' not in session: msg(access_logger, 'Enable admin privileges first.', 'error') return redirect(request.referrer) msg(access_logger, 'This query is expensive. Please do not refresh more than needed.', 'warn', log=False) date = datetime.datetime.combine(datetime.date.today(), datetime.datetime.min.time()) date = date + datetime.timedelta(days=-1 * page) page_range = 9 start_range = page - page_range / 2 if (page - page_range / 2) > 0 else 0 paging = { 'date': datetime.date.today() + datetime.timedelta(days=-1 * page), 'page': page, 'start_range': start_range, 'end_range': start_range + page_range, 'back': page - 1 if (page - 1) > 0 else 0, 'forward': page + 1 } history = access_logger.get_access_log(date) headings = ['user', 'request', 'request_update', 'method', 'endpoint', 'level', 'message', 'form_variables', 'get_variables', ] return render_template('history.jinja2', history_log=True, title='Admin History', paging=paging, headings=headings, history=history)
def toggle_admin(): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger(request, session['email']) user_record = current_app.cluster.get_user(session['email']) if not user_record or not user_record[0]['admin']: msg(access_logger, 'Admin privileges not enabled for this account.', 'error') return redirect(request.referrer) if 'admin' not in session: session['admin'] = True return redirect(request.referrer) else: del session['admin'] return redirect(url_for('dashboard_api.index'))
def pemfile(): user = session['email'] if 'email' in session else 'Unauthenticated User' access_logger = current_app.cluster.get_access_logger(request, user) if request.method == 'POST': request_vars = request.form else: request_vars = request.args pem_file = ctoolutils.pemfile(request_vars) if request.method == 'GET' and not pem_file.stdout \ or 'error' in pem_file.stdout: msg(access_logger, 'Key not found: %s' % str(pem_file), 'error') return redirect('/') response = make_response(pem_file.stdout) response.headers['Content-Disposition'] = 'attachment; filename=%s.pem' % \ request_vars['cluster-id'] return response
def toggle_admin(): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger( request, session['email']) user_record = current_app.cluster.get_user(session['email']) if not user_record or not user_record[0]['admin']: msg(access_logger, 'Admin privileges not enabled for this account.', 'error') return redirect(request.referrer) if 'admin' not in session: session['admin'] = True return redirect(request.referrer) else: del session['admin'] return redirect(url_for('dashboard_api.index'))
def change_password(): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger(request, session['email']) if request.method == 'POST': if request.form['new-password'] != request.form['confirm-password']: msg(access_logger, 'New passwords did not match.', 'error') return render_template('change-password.jinja2') user_record = current_app.cluster.get_user(session['email']) password_hash = auth.hash(request.form['current-password'], current_app.secret_key) if user_record and user_record[0]['password_hash'] == password_hash: current_app.cluster.set_password(session['email'], auth.hash( request.form['new-password'], current_app.secret_key)) msg(access_logger, 'Password has been updated.', 'success') return render_template('change-password.jinja2') else: msg(access_logger, 'Current password did not match.', 'error') return render_template('change-password.jinja2') return render_template('change-password.jinja2')
def launch(access_logger, postvars): # currently chose shell commands to teach presales ctool in a more # relatable fashion launch_command = 'ctool' \ ' --log-dir /portal/demo-portal/automaton_logs/' \ '%(clean_email)s' \ ' --log-file %(log_file)s' \ ' --provider %(cloud-option)s' \ ' launch' \ ' --instance-type %(instance-type)s' \ ' --platform %(platform)s' \ ' --tags \'%(tags)s\'' \ ' %(full_name)s' \ ' %(num_nodes)s' launch_command = launch_command % postvars msg(access_logger, launch_command) logger.info('Executing: %s', launch_command) response = execute.run(launch_command) if response.stderr: return response
def add_admin(): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger(request, session['email'], init_log=False) if 'admin' not in session: msg(access_logger, 'Enable admin privileges first.', 'error') return redirect(request.referrer) if request.method == 'POST': if 'email' in request.form and request.form['email']: current_app.cluster.set_admin(request.form['email'], True) else: msg(access_logger, 'Please specify an email address.', 'warn') headings = ['user', 'admin'] users = current_app.cluster.get_users() users = [user for user in users if user['admin']] return render_template('users.jinja2', title='Add Admin User', headings=headings, users=users)
def request_password(): access_logger = current_app.cluster.get_access_logger(request) if request.method == 'POST': safe_email = False try: safe_email = auth.is_valid_domain(request.form['email'], 'datastax.com') if not safe_email: user_record = current_app.cluster.get_user( request.form['email']) if user_record and \ user_record[0]['user'] == request.form['email']: safe_email = user_record[0]['user'] except: logger.exception('Email deemed unsafe!') if not safe_email: msg(access_logger, 'Error occurred when validating email address. ' 'Please contact administrator.', 'error') return render_template('login.jinja2') password = auth.create_new_password() current_app.cluster.set_password(safe_email, auth.hash(password, current_app.secret_key)) body = 'Your email and password is: {0} / {1}\n\n' \ 'Feel free to bookmark this personalized address: ' \ 'http://demos.datastax.com:5000/login?email={0}' body = body.format(safe_email, password) message = Message(subject='DataStax Demo Portal Authentication', recipients=[safe_email], body=body) try: current_app.mail.send(message) except: logger.exception('Error sending email.') msg(access_logger, 'Error occurred when sending email. ' 'Please contact administrator.', 'error') return render_template('login.jinja2') msg(access_logger, 'Password emailed.') return redirect('%s?email=%s' % (url_for('authentication_api.login'), safe_email)) else: return render_template('login.jinja2')
def install(access_logger, postvars, reservation_id): ec2.tag_reservation(reservation_id, 'user', remove=True) ec2.tag_reservation(reservation_id, 'status', 'Installing %(product-name)s...' % postvars) postvars['spark_hadoop'] = '--spark-hadoop' \ if 'spark-and-hadoop' in postvars else '' postvars['tarball'] = '--install_type tar' \ if not postvars['dse-version'].endswith('-1') else '' if len(postvars['advanced_nodes']['cluster']['nodes']) == 0: # calculate install values postvars['percent_analytics'] = float(postvars['hadoop-nodes']) / \ postvars['num_nodes'] postvars['percent_search'] = float(postvars['search-nodes']) / \ postvars['num_nodes'] postvars['percent_spark'] = float(postvars['spark-nodes']) / \ postvars['num_nodes'] install_command = 'ctool ' \ ' --provider %(cloud-option)s' \ ' install' \ ' --repo qa' \ ' --percent-analytics %(percent_analytics)s' \ ' --percent-search %(percent_search)s' \ ' --percent-spark %(percent_spark)s' \ ' %(spark_hadoop)s' \ ' %(tarball)s' \ ' --version_or_branch %(dse-version)s' \ ' --num-tokens %(num-of-tokens)s' \ ' %(full_name)s' \ ' %(product-name)s' install_command = install_command % postvars logger.info('Executing: %s', install_command) response = execute.run(install_command) msg(access_logger, install_command) else: with NamedTemporaryFile() as f: postvars['config_file'] = f.name f.write(json.dumps(postvars['advanced_nodes'], indent=4, sort_keys=True)) f.flush() install_command = 'ctool' \ ' --provider %(cloud-option)s' \ ' install' \ ' --repo qa' \ ' --config-file %(config_file)s' \ ' %(spark_hadoop)s' \ ' --version_or_branch %(dse-version)s' \ ' --num-tokens %(num-of-tokens)s' \ ' %(full_name)s' \ ' %(product-name)s' install_command = install_command % postvars logger.info('Executing: %s', install_command) logger.debug('With config-file: \n%s', f.read()) response = execute.run(install_command) msg(access_logger, install_command) msg(access_logger, '--config-file: %s' % json.dumps(postvars['advanced_nodes'])) if response.stderr: return response
def install(access_logger, postvars, reservation_id): ec2.tag_reservation(reservation_id, 'user', remove=True) ec2.tag_reservation(reservation_id, 'status', 'Installing %(product-name)s...' % postvars) postvars['spark_hadoop'] = '--spark-hadoop' \ if 'spark-and-hadoop' in postvars else '' postvars['tarball'] = '--install_type tar' \ if not postvars['dse-version'].endswith('-1') else '' if len(postvars['advanced_nodes']['cluster']['nodes']) == 0: # calculate install values postvars['percent_analytics'] = float(postvars['hadoop-nodes']) / \ postvars['num_nodes'] postvars['percent_search'] = float(postvars['search-nodes']) / \ postvars['num_nodes'] postvars['percent_spark'] = float(postvars['spark-nodes']) / \ postvars['num_nodes'] install_command = 'ctool ' \ ' --provider %(cloud-option)s' \ ' install' \ ' --repo qa' \ ' --percent-analytics %(percent_analytics)s' \ ' --percent-search %(percent_search)s' \ ' --percent-spark %(percent_spark)s' \ ' %(spark_hadoop)s' \ ' %(tarball)s' \ ' --version_or_branch %(dse-version)s' \ ' --num-tokens %(num-of-tokens)s' \ ' %(full_name)s' \ ' %(product-name)s' install_command = install_command % postvars logger.info('Executing: %s', install_command) response = execute.run(install_command) msg(access_logger, install_command) else: with NamedTemporaryFile() as f: postvars['config_file'] = f.name f.write( json.dumps(postvars['advanced_nodes'], indent=4, sort_keys=True)) f.flush() install_command = 'ctool' \ ' --provider %(cloud-option)s' \ ' install' \ ' --repo qa' \ ' --config-file %(config_file)s' \ ' %(spark_hadoop)s' \ ' --version_or_branch %(dse-version)s' \ ' --num-tokens %(num-of-tokens)s' \ ' %(full_name)s' \ ' %(product-name)s' install_command = install_command % postvars logger.info('Executing: %s', install_command) logger.debug('With config-file: \n%s', f.read()) response = execute.run(install_command) msg(access_logger, install_command) msg(access_logger, '--config-file: %s' % json.dumps(postvars['advanced_nodes'])) if response.stderr: return response
def ctool(): if 'email' not in session: return redirect(url_for('authentication_api.login')) access_logger = current_app.cluster.get_access_logger(request, session['email']) # only process form if form has been submitted if request.form: access_logger.launch('ctool') # make a mutable dict copy postvars = request.form.copy().to_dict() # ensure jQuery doesn't fail if not postvars['clustername']: msg(access_logger, 'Clustername must be set', 'error') return render_template('ctool.jinja2') postvars = ctoolutils.process(postvars, session) # ensure jQuery doesn't fail if postvars['num_nodes'] < 1: msg(access_logger, 'Must launch at least one node', 'error') return render_template('ctool.jinja2') try: response = ctoolutils.launch(access_logger, postvars) if response: return render_template( ctoolutils.error_handling(access_logger, response, postvars, 'launch')) reservation_id = ec2.find_reservation_id_by_tag('cluster_name', postvars[ 'full_name']) response = ctoolutils.install(access_logger, postvars, reservation_id) if response: return render_template( ctoolutils.error_handling(access_logger, response, postvars, 'install')) response = ctoolutils.install_opscenter(access_logger, postvars, reservation_id) if response: return render_template( ctoolutils.error_handling(access_logger, response, postvars, 'install')) response = ctoolutils.start(access_logger, postvars, reservation_id) if response: return render_template( ctoolutils.error_handling(access_logger, response, postvars, 'start')) response = ctoolutils.start_opscenter(access_logger, postvars, reservation_id) if response: return render_template( ctoolutils.error_handling(access_logger, response, postvars, 'start')) response = ctoolutils.start_agent(access_logger, postvars, reservation_id) if response: return render_template( ctoolutils.error_handling(access_logger, response, postvars, 'start')) ec2.tag_reservation(reservation_id, 'status', 'Complete.') return redirect('/') except: logger.exception('Exception seen on /ctool:') msg(access_logger, traceback.format_exc(), 'debug') return render_template( ctoolutils.error_handling(access_logger,'Logic exception.', postvars, '/ctool')) return render_template('ctool.jinja2')