Commit 06c28956 authored by Georgios Ouzounis's avatar Georgios Ouzounis
Browse files

Refactored create lambda instance form and the way drop down lists are filled with data

parent d19f9fd7
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
create(newLambdaInstance) {
newLambdaInstance.set('instanceName', this.get('instanceName'));
newLambdaInstance.set('masterName', this.get('masterName'));
newLambdaInstance.set('slaves', this.$("input[name='slaves']")[0].value);
newLambdaInstance.set('projectName', this.$("select[name='okeanos_project']")[0].value);
newLambdaInstance.set('VCPUsMaster', this.$("select[name='vcpus_master']")[0].value);
newLambdaInstance.set('VCPUsSlave', this.$("select[name='vcpus_slave']")[0].value);
newLambdaInstance.set('RamMaster', this.$("select[name='ram_master']")[0].value);
newLambdaInstance.set('RamSlave', this.$("select[name='ram_slave']")[0].value);
newLambdaInstance.set('DiskMaster', this.$("select[name='disk_master']")[0].value);
newLambdaInstance.set('DiskSlave', this.$("select[name='disk_slave']")[0].value);
var requestedPublicKeys = [];
var options = this.$("select[name='public_key_name']")[0].options;
for(var i = 0;i < options.length;i++){
if(options[i].selected){
requestedPublicKeys.push(options[i].value);
}
}
newLambdaInstance.set('publicKeyName', requestedPublicKeys);
var kafkaOutputTopics, kafkaInputTopics;
var kafkaInputTopicsString = this.get('kafkaInputTopics');
if (kafkaInputTopicsString) {
kafkaInputTopics = kafkaInputTopicsString.replace(/\s+/g, '').split(',');
}
var kafkaOutputTopicsString = this.get('kafkaOutputTopics');
if (kafkaOutputTopicsString) {
kafkaOutputTopics = kafkaOutputTopicsString.replace(/\s+/g, '').split(',');
}
var duplicateTopic = false;
if (kafkaInputTopics && kafkaOutputTopics) {
kafkaInputTopics.forEach(function (inputTopic) {
if (kafkaOutputTopics.indexOf(inputTopic) !== -1) {
duplicateTopic = true;
}
});
}
if (duplicateTopic) {
this.set('duplicate_message', 'Apache Kafka input and output topics must be different!');
this.set('duplicate', true);
document.getElementById('inputTopics').focus();
}
else {
newLambdaInstance.set('kafkaInputTopics', kafkaInputTopics);
newLambdaInstance.set('kafkaOutputTopics', kafkaOutputTopics);
this.sendAction('saveAction', newLambdaInstance);
}
},
close_alert: function()
{
this.set('duplicate', false);
},
}
});
import Ember from "ember";
export default Ember.Controller.extend({
selectedProject: null,
selectedNumberOfSlaves: null,
selectedMasterNodeCPUs: null,
selectedSlaveNodeCPUs: null,
selectedMasterNodeRAM: null,
selectedSlaveNodeRAM: null,
selectedMasterNodeDisk: null,
selectedSlaveNodeDisk: null,
masterNodeCPUValues: [],
slaveNodeCPUValues: [],
masterNodeRAMValues: [],
slaveNodeRAMValues: [],
masterNodeDiskValues: [],
slaveNodeDiskValues: [],
minQuotasPerVM: {'cpus': 2, 'ram': 2048, 'disk': 10},
minQuotasPerProject: {
'vms': 2,
'cpus': 4,
'ram': {"bytes": 4294967296, "megaBytes": 4096},
'disk': {"bytes": 21474836480, "gigaBytes": 20},
'floatingIPs': 1,
'privateNetworks': 1
},
enoughQuotas: false,
actions: {
saveLambdaInstance: function(newLambdaInstance){
var self = this;
newLambdaInstance.save().then(function(){
self.transitionToRoute('lambda-instance', newLambdaInstance.get('id')).catch(function() {
self.transitionToRoute('lambda-instances.index').then(function(newRoute) {
newRoute.controller.set('message', 'Your lambda instance creation will begin shortly.');
newRoute.controller.set('request', true);
newRoute.controller.send('start_stop');
newLambdaInstance.set('instanceName', this.get('instanceName'));
newLambdaInstance.set('masterName', this.get('masterName'));
newLambdaInstance.set('slaves', this.$("input[name='slaves']")[0].value);
newLambdaInstance.set('projectName', this.$("select[name='okeanos_project']")[0].value);
newLambdaInstance.set('VCPUsMaster', this.$("select[name='vcpus_master']")[0].value);
newLambdaInstance.set('VCPUsSlave', this.$("select[name='vcpus_slave']")[0].value);
newLambdaInstance.set('RamMaster', this.$("select[name='ram_master']")[0].value);
newLambdaInstance.set('RamSlave', this.$("select[name='ram_slave']")[0].value);
newLambdaInstance.set('DiskMaster', this.$("select[name='disk_master']")[0].value);
newLambdaInstance.set('DiskSlave', this.$("select[name='disk_slave']")[0].value);
var requestedPublicKeys = [];
var options = this.$("select[name='public_key_name']")[0].options;
for(var i = 0;i < options.length;i++){
if(options[i].selected){
requestedPublicKeys.push(options[i].value);
}
}
newLambdaInstance.set('publicKeyName', requestedPublicKeys);
var kafkaOutputTopics, kafkaInputTopics;
var kafkaInputTopicsString = this.get('kafkaInputTopics');
if (kafkaInputTopicsString) {
kafkaInputTopics = kafkaInputTopicsString.replace(/\s+/g, '').split(',');
}
var kafkaOutputTopicsString = this.get('kafkaOutputTopics');
if (kafkaOutputTopicsString) {
kafkaOutputTopics = kafkaOutputTopicsString.replace(/\s+/g, '').split(',');
}
var duplicateTopic = false;
if (kafkaInputTopics && kafkaOutputTopics) {
kafkaInputTopics.forEach(function (inputTopic) {
if (kafkaOutputTopics.indexOf(inputTopic) !== -1) {
duplicateTopic = true;
}
});
}
if (duplicateTopic) {
this.set('duplicate_message', 'Apache Kafka input and output topics must be different!');
this.set('duplicate', true);
document.getElementById('inputTopics').focus();
}
else {
newLambdaInstance.set('kafkaInputTopics', kafkaInputTopics);
newLambdaInstance.set('kafkaOutputTopics', kafkaOutputTopics);
var self = this;
newLambdaInstance.save().then(function(){
self.transitionToRoute('lambda-instance', newLambdaInstance.get('id')).catch(function() {
self.transitionToRoute('lambda-instances.index').then(function(newRoute) {
newRoute.controller.set('message', 'Your lambda instance creation will begin shortly.');
newRoute.controller.set('request', true);
newRoute.controller.send('start_stop');
});
});
});
});
}
},
close_alert: function()
{
this.set('duplicate', false);
},
selectFromDropDownList: function(variable, event){
var value = event.target.value;
this.set(variable, value);
this.calculateDropDownListValues();
}
},
calculateDropDownListValues: function(){
}
});
......@@ -15,21 +15,44 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
// has enough quotas to create a Lambda Instance, set enoughQuotas to true.
// Delete every project that doesn't have the quotas to create the smallest Lambda
// Instance.
var controller = this.controllerFor('create-lambda-instance');
var minQuotasPerProject = controller.get('minQuotasPerProject');
for (var i = 0;i < model.userOkeanosProjects.get('length');i++){
if (model.userOkeanosProjects.objectAt(i).get('vm') >= 2 &&
model.userOkeanosProjects.objectAt(i).get('cpu') >= 4 &&
model.userOkeanosProjects.objectAt(i).get('ram') >= 4294967296 &&
model.userOkeanosProjects.objectAt(i).get('disk') >= 21474836480 &&
model.userOkeanosProjects.objectAt(i).get('floating_ip') >= 1 &&
model.userOkeanosProjects.objectAt(i).get('private_network') >= 1) {
if (model.userOkeanosProjects.objectAt(i).get('vm') >= minQuotasPerProject['vms'] &&
model.userOkeanosProjects.objectAt(i).get('cpu') >= minQuotasPerProject['cpus'] &&
model.userOkeanosProjects.objectAt(i).get('ram') >= minQuotasPerProject['ram']['bytes'] &&
model.userOkeanosProjects.objectAt(i).get('disk') >= minQuotasPerProject['disk']['bytes'] &&
model.userOkeanosProjects.objectAt(i).get('floating_ip') >= minQuotasPerProject['floatingIPs'] &&
model.userOkeanosProjects.objectAt(i).get('private_network') >= minQuotasPerProject['privateNetworks']) {
if(!this.controllerFor('create-lambda-instance').get('enoughQuotas')){
this.controllerFor('create-lambda-instance').set('enoughQuotas', true);
if(!controller.get('enoughQuotas')){
controller.set('enoughQuotas', true);
}
}
else{
model.userOkeanosProjects.objectAt(i).deleteRecord();
}
}
// If at least one project has enough quotas, set the default values for the drop down lists.
if(model.userOkeanosProjects.get('length') > 0){
controller.set('selectedProject', model.userOkeanosProjects.objectAt(0).get('name'));
controller.set('selectedNumberOfSlaves', minQuotasPerProject['vms'] - 1);
var minQuotasPerVM = controller.get('minQuotasPerVM');
controller.set('selectedMasterNodeCPUs', minQuotasPerVM['cpus']);
controller.set('selectedSlaveNodeCPUs', minQuotasPerVM['cpus']);
controller.set('selectedMasterNodeRAM', minQuotasPerVM['ram']);
controller.set('selectedSlaveNodeRAM', minQuotasPerVM['ram']);
controller.set('selectedMasterNodeDisk', minQuotasPerVM['disk']);
controller.set('selectedSlaveNodeDisk', minQuotasPerVM['disk']);
controller.set('masterNodeCPUValues', model.VMParameterValues.objectAt(0).get('vcpus'));
controller.set('slaveNodeCPUValues', model.VMParameterValues.objectAt(0).get('vcpus'));
controller.set('masterNodeRAMValues', model.VMParameterValues.objectAt(0).get('ram'));
controller.set('slaveNodeRAMValues', model.VMParameterValues.objectAt(0).get('ram'));
controller.set('masterNodeDiskValues', model.VMParameterValues.objectAt(0).get('disk'));
controller.set('slaveNodeDiskValues', model.VMParameterValues.objectAt(0).get('disk'));
}
}
});
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
Dashboard
<small>Create a Lambda Instance</small>
</h1>
</section>
<section class="content">
<div class="row">
<div class="col-xs-12">
<div class="box box-info">
<div class="box-header with-border">
<h3 class="box-title">Create a new Lambda Instance</h3>
<div class="box-tools pull-right">
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
<button class="btn btn-box-tool" data-widget="remove"><i class="fa fa-times"></i></button>
</div>
</div><!-- /.box-header -->
<div class="box-body no-padding">
<div class="row">
<div class="col-md-9 col-sm-8">
<div class="pad">
Here you can create your own Lambda Instance
</div>
</div><!-- /.col -->
</div><!-- /.row -->
</div><!--box-->
</div> <!-- box-primary -->
</div> <!--col -->
</div> <!--row-->
{{#unless enoughQuotas}}
<div class="row">
<div class="col-xs-12">
<div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-warning"></i> Alert! - No resources available to create a new lambda instance!</h4>
Based on the ~okeanos projects we found on your ~okeanos profile, you don't have the resources needed to create a lambda instance.
A lambda instance requires at least <ul><li> 1 public ip</li> <li>2 VMs</li><li>4 CPU's per VM </li> <li>4096MB of RAM per VM </li><li> 20GB of hard disk per VM</li></ul>Please join a project or create your own project and ask for resources so as to create a lambda Instance. In order to join or create an ~okeanos project follow this <a href="https://accounts.okeanos.grnet.gr/ui/projects" target="_blank">link</a>!.
</div> <!-- class="alert alert-warning alert-dismissable" -->
</div> <!-- col-xs-12 -->
</div><!-- row -->
{{/unless}}
{{#if enoughQuotas}}
<form {{action "create" newLambdaInstance on="submit"}} method="post">
<div class="row">
<div class="col-xs-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Main</h3>: Lambda Instance details
</div><!-- /.box-header -->
<div class="box-body">
<div class="row">
<div class="col-sm-12">
<p><i class="fa fa-info"></i> All inputs marked with (*) are required. </p>
</div>
</div>
<div class="row">
<div class="form-group col-sm-6">
<label for="name1"> Name of Lamdba Instance (*): </label>
{{input type="text" value=instanceName placeholder="Lambda Instance name" size="50" class="form-control" required="true"}}
{{#each newLambdaInstance.errors.instanceName as |error|}}
<div class="alert alert-danger alert-dismissable">
{{error.message}}
</div>
{{/each}}
</div>
<div class="form-group col-sm-6">
<label for="name1"> Name of Master Node (*): </label>
{{input type="text" value=masterName placeholder="Master node name" size="50" class="form-control" required="true"}}
{{#each newLambdaInstance.errors.masterName as |error|}}
<div class="alert alert-danger alert-dismissable">
{{error.message}}
</div>
{{/each}}
</div>
</div>
<div class="row">
<div class="form-group col-sm-8">
<label for="okeanos_project" class="col-sm-6">~okeanos Project (*):</label>
<select name="okeanos_project" class="form-control">
{{#each userOkeanosProjects as |project|}}
<option value={{project.name}}>{{project.name}} (VMs: {{project.vm}}, CPUs: {{project.cpu}}, RAM: {{normalize-bytes project.ram}}, Disk: {{normalize-bytes project.disk}}, Floating IPs: {{project.floating_ip}}, Private Networks: {{project.private_network}})</option>
{{/each}}
</select>
<span id="helpBlock" class="help-block">Select a project</span>
</div> <!--class="col-sm-6"-->
<div class="form-group col-sm-3">
<label for="slaves">Number of slaves:</label>
<input type="number" min="1" value="2" name="slaves" class="form-control">
<span id="helpBlock" class="help-block">Select the number of slaves</span>
</div> <!--class="form-group col-sm-3"-->
</div>
<style>.tokenfield.form-control { height: auto; }</style>
<div class="row">
<div class="form-group col-sm-6">
<label for="kafka_topics">Apache Kafka input topics:</label>
{{input-tokenfield value=kafkaInputTopics createTokensOnBlur=true
placeholder="e.g. topic1, topic2, topic3" id="inputTopics"}}
<span id="helpBlock" class="help-block">Names of Apache Kafka input topics<br>
Default input topic, if no names are given: "input"</span>
</div>
<div class="form-group col-sm-6 pull-right">
<label for="kafka_topics">Apache Kafka output topics:</label>
{{input-tokenfield value=kafkaOutputTopics createTokensOnBlur=true
placeholder="e.g. topic1, topic2, topic3"}}
<span id="helpBlock" class="help-block">Names of Apache Kafka output topics<br>
Default output topics, if no names are given: "batch-output", "stream-output"</span>
</div>
</div><!--row-->
{{#if duplicate}}
<div class="alert alert-dismissable alert-danger" id="alert">
<button type="button" class="close" {{action "close_alert"}}>×</button>
{{duplicate_message}}
</div>
{{/if}}
<div class="row">
<div class="form-group col-sm-3">
<label for="public_key_name">Public SSH keys (*):</label>
<select required="required" multiple name="public_key_name" class="form-control">
{{#each userPublicKeys as |publicKey|}}
<option value={{publicKey.name}}>{{publicKey.name}}</option>
{{/each}}
</select>
</div>
<div class="form-group col-sm-2">
<br/>
<span id="helpBlock" class="help-block">Select the public SSH keys to upload to the lamdba instance vms. By selecting ssh keys, you will get access to these vms.</span>
</div><!--class="form-group col-sm-6"-->
</div><!--row-->
</div><!--box-body-->
</div><!--box-->
</div><!--col-->
</div><!--row-->
<div class="row">
<div class="col-xs-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Master</h3>: Master Node details
</div><!-- /.box-header -->
<div class="box-body">
<div class="row">
<div class="form-group col-sm-4">
<label for="vcpus_master">Number of CPUs on Master Node:</label>
<select name="vcpus_master" class="form-control">
{{#each VMParameterValues as |valuesSet|}}
{{#each valuesSet.vcpus as |vcpusValue|}}
{{#if (compare vcpusValue "!==" 1)}}
{{#if (compare vcpusValue "!==" 4)}}
<option value={{vcpusValue}}>{{vcpusValue}}</option>
{{else}}
<option value={{vcpusValue}} selected>{{vcpusValue}}</option>
{{/if}}
{{/if}}
{{/each}}
{{/each}}
</select>
<span id="helpBlock" class="help-block">We recommend using 4 CPUs</span>
</div> <!--class="col-sm-4"-->
<div class="form-group col-sm-4">
<label for="ram_master" >Amount or RAM memory on Master Node: </label>
<select name="ram_master" class="form-control">
{{#each VMParameterValues as |valuesSet|}}
{{#each valuesSet.ram as |ramValue|}}
{{#if (compare ramValue ">=" 2048)}}
{{#if (compare ramValue "!==" 4096)}}
<option value={{ramValue}}>{{ramValue}}</option>
{{else}}
<option value={{ramValue}} selected>{{ramValue}}</option>
{{/if}}
{{/if}}
{{/each}}
{{/each}}
</select>
<span id="helpBlock" class="help-block">We recommend using 4096MB of RAM</span>
</div><!--class="form-group col-sm-6"-->
<div class="form-group col-sm-4">
<label for="disk_master"> Size of hard disk on Master Node: </label>
<select name="disk_master" class="form-control">
{{#each VMParameterValues as |valuesSet|}}
{{#each valuesSet.disk as |diskValue|}}
{{#if (compare diskValue ">=" 10)}}
{{#if (compare diskValue "!==" 20)}}
<option value={{diskValue}}>{{diskValue}}</option>
{{else}}
<option value={{diskValue}} selected>{{diskValue}}</option>
{{/if}}
{{/if}}
{{/each}}
{{/each}}
</select>
<span id="helpBlock" class="help-block">We recommend using 20GB of hard disk</span>
</div>
</div><!--row-->
</div><!--box-body-->
</div><!--box-->
</div><!--col-->
</div><!--row-->
<div class="row">
<div class="col-xs-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Slaves</h3>: Slave Nodes details
</div><!-- /.box-header -->
<div class="box-body">
<div class="row">
<div class="form-group col-sm-4">
<label for="vcpus_slave">Number of CPUs on each Slave Node:</label>
<select name="vcpus_slave" class="form-control">
{{#each VMParameterValues as |valuesSet|}}
{{#each valuesSet.vcpus as |vcpusValue|}}
{{#if (compare vcpusValue "!==" 1)}}
{{#if (compare vcpusValue "!==" 4)}}
<option value={{vcpusValue}}>{{vcpusValue}}</option>
{{else}}
<option value={{vcpusValue}} selected>{{vcpusValue}}</option>
{{/if}}
{{/if}}
{{/each}}
{{/each}}
</select>
<span id="helpBlock" class="help-block">We recommend using 4 CPUs</span>
</div> <!--class="col-sm-4"-->
<div class="form-group col-sm-4">
<label for="ram_slave" >Amount or RAM memory on each Slave Node:</label>
<select name="ram_slave" class="form-control">
{{#each VMParameterValues as |valuesSet|}}
{{#each valuesSet.ram as |ramValue|}}
{{#if (compare ramValue ">=" 2048)}}
{{#if (compare ramValue "!==" 4096)}}
<option value={{ramValue}}>{{ramValue}}</option>
{{else}}
<option value={{ramValue}} selected>{{ramValue}}</option>
{{/if}}
{{/if}}
{{/each}}
{{/each}}
</select>
<span id="helpBlock" class="help-block">We recommend using 4096MB of RAM</span>
</div><!--class="form-group col-sm-4"-->
<div class="form-group col-sm-4">
<label for="disk_slave"> Size of hard disk on each Slave Node:</label>
<select name="disk_slave" class="form-control">
{{#each VMParameterValues as |valuesSet|}}
{{#each valuesSet.disk as |diskValue|}}
{{#if (compare diskValue ">=" 10)}}
{{#if (compare diskValue "!==" 20)}}
<option value={{diskValue}}>{{diskValue}}</option>
{{else}}
<option value={{diskValue}} selected>{{diskValue}}</option>
{{/if}}
{{/if}}
{{/each}}
{{/each}}
</select>
<span id="helpBlock" class="help-block">We recommend using 20GB of hard disk</span>
</div>
</div><!--row-->
</div><!--box-body-->
</div><!--box-->
</div><!--col-->
</div><!--row-->
<button type="submit" class="btn btn-primary">Submit</button>
<div class="row">
<div class="col-xs-12">
&nbsp;
</div>
</div>
{{#if newLambdaInstance.isSaving}}
<div class="row">
<div class="col-xs-12">
<div class="alert alert-info alert-dismissable">
Your request to create a new Lambda Instance is being sent to the server...
</div>
</div><!--col-xs-12-->
</div><!--row-->
{{/if}}
</form>
{{/if}}
</section><!-- /.content -->
{{create-lambda-instance-form newLambdaInstance=model.newLambdaInstance
userPublicKeys=model.userPublicKeys
userOkeanosProjects=model.userOkeanosProjects
VMParameterValues=model.VMParameterValues
saveAction=(action "saveLambdaInstance")
enoughQuotas=enoughQuotas}}
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
Dashboard
<small>Create a Lambda Instance</small>
</h1>
</section>
<section class="content">
<div class="row">
<div class="col-xs-12">
<div class="box box-info">
<div class="box-header with-border">
<h3 class="box-title">Create a new Lambda Instance</h3>
<div class="box-tools pull-right">
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
<button class="btn btn-box-tool" data-widget="remove"><i class="fa fa-times"></i></button>
</div>
</div><!-- /.box-header -->
<div class="box-body no-padding">
<div class="row">
<div class="col-md-9 col-sm-8">