From b874396b32eecaadd3de592518100ad313dc9163 Mon Sep 17 00:00:00 2001 From: Hang Xu Date: Thu, 14 May 2015 10:48:39 -0400 Subject: [PATCH 01/10] custom VM form --- moc_ui/dicts.py | 9 ++- moc_ui/forms.py | 9 ++- moc_ui/html_helpers.py | 12 ++-- moc_ui/templates/control.html | 13 ++-- moc_ui/urls.py | 2 +- moc_ui/views.py | 122 ++++++++++++++++++---------------- 6 files changed, 89 insertions(+), 78 deletions(-) diff --git a/moc_ui/dicts.py b/moc_ui/dicts.py index fc1c8a1..9feeaec 100644 --- a/moc_ui/dicts.py +++ b/moc_ui/dicts.py @@ -10,11 +10,16 @@ login_buttons = [{'name': 'Login', 'type': 'submit', 'action': '/login/', 'class': 'btn-primary'}, {'name': 'Register', 'type': 'modal', 'data_target': '#createUser', 'class': 'btn-success'}] - login_data = {'name': 'MassOpenCloud Login', 'action': '/login', 'method': 'post', 'button_list': login_buttons} -reg_modal = {'id': 'createUser', 'action': '/register', 'method': 'post', 'title': 'Register User'} +reg_modal = {'id': 'createUser', 'action': '/register', 'method': 'post', 'title': 'Register User'} + +#CONTROL PAGE +vm_buttons = {'name': 'Create', 'type': 'modal', 'data_target': '#createVM', 'class': 'btn-success'} + +vm_data = {'name': 'Create a VM', 'action': '/createVM', 'method': 'post', 'button_list': vm_buttons} +vm_modal = {'id': 'create VM', 'action': '/createVM', 'method': 'post', 'title': 'Create a New VM'} # CLOUDS PAGE test_vm_list_1 = [{'name': 'hadoop master', 'state': '=)', 'provider': 'HU-prod', 'image': 'centOS 7'}, diff --git a/moc_ui/forms.py b/moc_ui/forms.py index 753a21b..f729895 100644 --- a/moc_ui/forms.py +++ b/moc_ui/forms.py @@ -180,11 +180,10 @@ class Meta: # vm actions class Create_VM(forms.Form): - name = forms.CharField() - cluster_projects = [] - for p in models.ClusterProject.objects.all().values('name').distinct(): #for all - cluster_projects.append((p['name'], p['name'])) - cluster_project = forms.ChoiceField(widget=forms.Select, choices=cluster_projects) + name = forms.CharField() + image = forms.CharField() + flavor = forms.CharField() + nics = forms.CharField() #nova = api.get_nova(request, project) #get nova object diff --git a/moc_ui/html_helpers.py b/moc_ui/html_helpers.py index 3a55fd6..11a40c1 100644 --- a/moc_ui/html_helpers.py +++ b/moc_ui/html_helpers.py @@ -13,8 +13,12 @@ def project_modals(request): {'id':'add_Cluster_Project', 'action':'/create/ClusterProject', 'title':'Add Cluster Project', 'form':forms.ClusterProject()}, {'id':'delete_Cluster_Project', 'action':'/delete/ClusterProject', - 'title':'Delete Cluster Project', 'form':forms.ClusterProject()}, - #{'id':'createVM', 'title':'Create VM', 'form':forms.create_VM()}, - {'id':'deleteVM', 'action':'/delete/Cluster', - 'title':'Delete VM', 'form':forms.Delete_VM()}, + 'title':'Delete Cluster Project', 'form':forms.ClusterProject()} + ] +def vm_modals(request): + return [{'id':'createVM', 'action' : '/createVM', + 'title':'Create VM', 'form':forms.Create_VM()}, + {'id':'deleteVM', 'action':'/deleteVM', + 'title':'Delete VM', 'form':forms.Delete_VM()} + ] \ No newline at end of file diff --git a/moc_ui/templates/control.html b/moc_ui/templates/control.html index 7d1752f..183e3b6 100644 --- a/moc_ui/templates/control.html +++ b/moc_ui/templates/control.html @@ -50,9 +50,10 @@

{{project}}'s VMs

- + @@ -125,12 +126,10 @@

{{project}}'s VMs

- {% for form_data in cloud_modals %} - {% include "modals/cloudModal.html" %} + {% for form_data in vm_modals %} + {% include "modals/projectModal.html" %} {% endfor %} - {% include "modals/createVM.html" %} - {% endfor %} {% endblock %} diff --git a/moc_ui/urls.py b/moc_ui/urls.py index 8a948ce..509bb19 100644 --- a/moc_ui/urls.py +++ b/moc_ui/urls.py @@ -48,7 +48,7 @@ url(r'^create/(?P.+)', create_object), url(r'^delete/(?P.+)', delete_object), # VM creatoin - url(r'^VM_add', VM_add), + url(r'^createVM\/(?P.+)?\/$', create_VM), # projects control # url(r'^createProject', createProject), # url(r'^deleteProject', deleteProject), diff --git a/moc_ui/views.py b/moc_ui/views.py index 6f444ef..f36ce1d 100644 --- a/moc_ui/views.py +++ b/moc_ui/views.py @@ -69,7 +69,9 @@ def control(request, project): return render(request, 'control.html', {'project': [project], 'vms': vms, - 'createVMform': createVMform }) + 'createVMform': createVMform, + 'vm_modals': html.vm_modals(request) + }) ## Network Page def network(request, project): createVMform = forms.Create_VM() @@ -80,65 +82,7 @@ def network(request, project): 'createVMform': createVMform }) -# VM CONTROLS -def VM_active_state_toggle (request, project, VMid): - print (project, VMid) - print VMid[len(VMid)-1] - print VMid[:len(VMid)-1] - if VMid[len(VMid)-1] == '/': - VMid = VMid[:len(VMid)-1] - nova = api.get_nova(request, project) - api.VM_active_state_toggle(nova, VMid) - return HttpResponseRedirect('/control/' + project + '/') -# VM Delete -def VM_delete(request, project, VMid): - print (project, VMid) #debugging - if VMid[len(VMid)-1] == '/': #strip ending / - VMid = VMid[:len(VMid)-1] - nova = api.get_nova(request, project) #get nova object - api.delete(nova, VMid) #delete specified Nova object - return HttpResponseRedirect('/control/' + project + '/') #back to control - -# VM start -def VM_start(request, project, VMid): - print (project, VMid) #debugging - if VMid[len(VMid)-1] == '/': #strip ending / - VMid = VMid[:len(VMid)-1] - nova = api.get_nova(request, project) #get nova object - api.startVM(nova, VMid) #start specified Nova object - return HttpResponseRedirect('/control/' + project + '/') #back to control - -# VM stop -def VM_stop(request, project, VMid): - print (project, VMid) #debugging - if VMid[len(VMid)-1] == '/': #strip ending / - VMid = VMid[:len(VMid)-1] - nova = api.get_nova(request, project) #get nova object - api.stopVM(nova, VMid) #stop specified Nova object - return HttpResponseRedirect('/control/' + project + '/') #back to control - -# VM add default -def VM_add_default(request, project): - print (project) - nova = api.get_nova(request, project) #get nova object - api.createDefault(nova) - return HttpResponseRedirect('/control/' + project + '/') #back to control - -# VM add custom -def VM_add(request, project, VMname, imageName, flavorName): - print (project, VMname, imageName, flavorName) #debugging - -# if request.method == 'POST': -# form = forms.Create_VM(request.POST) -# if form.is_valid(): -# print "form is valid." -# nameVM = form.cleaned_data['VM_name'] -# nameFlavor - - nova = api.get_nova(request, project) #get nova object - api.createVM(nova, VMname, imageName, flavorName) #add specified Nova object - return HttpResponseRedirect('/control/' + project + '/') #back to control #def login(request): # """View to Login a user @@ -447,3 +391,63 @@ def control_vm(request, action, vm_name): # check that the user has privalidge on vm # actually do the action pass + +# VM CONTROLS +def VM_active_state_toggle (request, project, VMid): + print (project, VMid) + print VMid[len(VMid)-1] + print VMid[:len(VMid)-1] + if VMid[len(VMid)-1] == '/': + VMid = VMid[:len(VMid)-1] + nova = api.get_nova(request, project) + api.VM_active_state_toggle(nova, VMid) + return HttpResponseRedirect('/control/' + project + '/') + +# VM Delete +def VM_delete(request, project, VMid): + print (project, VMid) #debugging + if VMid[len(VMid)-1] == '/': #strip ending / + VMid = VMid[:len(VMid)-1] + nova = api.get_nova(request, project) #get nova object + api.delete(nova, VMid) #delete specified Nova object + return HttpResponseRedirect('/control/' + project + '/') #back to control + +# VM start +def VM_start(request, project, VMid): + print (project, VMid) #debugging + if VMid[len(VMid)-1] == '/': #strip ending / + VMid = VMid[:len(VMid)-1] + nova = api.get_nova(request, project) #get nova object + api.startVM(nova, VMid) #start specified Nova object + return HttpResponseRedirect('/control/' + project + '/') #back to control + +# VM stop +def VM_stop(request, project, VMid): + print (project, VMid) #debugging + if VMid[len(VMid)-1] == '/': #strip ending / + VMid = VMid[:len(VMid)-1] + nova = api.get_nova(request, project) #get nova object + api.stopVM(nova, VMid) #stop specified Nova object + return HttpResponseRedirect('/control/' + project + '/') #back to control + +# VM add default +def VM_add_default(request, project): + print (project) + nova = api.get_nova(request, project) #get nova object + api.createDefault(nova) + return HttpResponseRedirect('/control/' + project + '/') #back to control + +# VM add custom +def create_VM(request, project): + if request.method == 'POST': + form = forms.Create_VM(request.POST) + if form.is_valid(): + print "form is valid." + name = form.cleaned_data['name'] + flavor = form.cleaned_data['flavor'] + image = form.cleaned_data['image'] + nics = form.cleaned_data['nics'] + + # nova = api.get_nova(request, project) #get nova object + # api.createVM(nova, VMname, imageName, flavorName) #add specified Nova object + return HttpResponseRedirect('/control/' + project + '/') #back to control \ No newline at end of file From ea9dd404319dd842a7c68219c1a839789263d1a8 Mon Sep 17 00:00:00 2001 From: Hang Xu Date: Fri, 15 May 2015 10:07:11 -0400 Subject: [PATCH 02/10] custom VM donex --- moc_ui/auth.py | 4 ++- moc_ui/fixtures/service_list.json | 28 ++++++++++++++- moc_ui/forms.py | 57 +++++++++++++++++++++---------- moc_ui/html_helpers.py | 2 +- moc_ui/models.py | 9 +++++ moc_ui/templates/control.html | 2 +- moc_ui/ui_api.py | 11 +++--- moc_ui/urls.py | 2 +- moc_ui/views.py | 36 +++++++++++-------- syncdb.sh | 2 +- 10 files changed, 107 insertions(+), 46 deletions(-) diff --git a/moc_ui/auth.py b/moc_ui/auth.py index f165cae..7ffe579 100644 --- a/moc_ui/auth.py +++ b/moc_ui/auth.py @@ -60,9 +60,11 @@ def get_nova(request, tenant_name): def get_glance(request, tenant_name): username = request.session['username'] password = request.session['password'] + keystone = get_keystone(request,tenant_name) + nova = get_nova(request,tenant_name) glance_endpoint = keystone.service_catalog.url_for(service_type='image') glance = glclient.Client(glance_endpoint, token = keystone.auth_token) - return {'keystone': keystone, 'nova': nova, 'glance': glance} + return glance diff --git a/moc_ui/fixtures/service_list.json b/moc_ui/fixtures/service_list.json index d57af1f..00f5155 100644 --- a/moc_ui/fixtures/service_list.json +++ b/moc_ui/fixtures/service_list.json @@ -115,7 +115,7 @@ "pk": 11, "fields": { "name": "Hadoop", - "service_type": "Service", + "service_type": "Compute", "description" : "Apache Hadoop", "logo_url":"/static/hadoop.jpg", "availability":"True" @@ -143,6 +143,32 @@ "availability":"True" } }, + { + "model": "moc_ui.service", + "pk": 14, + "fields": { + "name": "Ubuntu", + "service_type": "Service", + "description" : "Ubuntu vm image", + "logo_url":"/static/Ubuntu.jpg", + "availability":"True", + "image_name" : "Ubuntu 14.04.2 LTS (Trusty Tahr) x86_64", + "flavor" : "m1.medium" + } + }, + { + "model": "moc_ui.service", + "pk": 15, + "fields": { + "name": "CentOS", + "service_type": "Service", + "description" : "CentOS vm image", + "logo_url":"/static/CentOS.png", + "availability":"True", + "image_name" : "CentOS-7-x86_64-GenericCloud-1503.qcow2", + "flavor": "m1.tiny" + } + }, { "model": "moc_ui.uiproject", "pk": 1, diff --git a/moc_ui/forms.py b/moc_ui/forms.py index f729895..e5dd480 100644 --- a/moc_ui/forms.py +++ b/moc_ui/forms.py @@ -180,24 +180,45 @@ class Meta: # vm actions class Create_VM(forms.Form): - name = forms.CharField() - image = forms.CharField() - flavor = forms.CharField() - nics = forms.CharField() - - #nova = api.get_nova(request, project) #get nova object - - #image choices - #image_choices = [] - #for option in nova.images.list(): - # image_coices.append(str(option.name)) - #imageName = forms.ChoiceField(widget=forms.Select, choices=image_choices) - - #flavor choices - #flavor_choices = [] - #for option in nova.flavors.list(): - # flavor_choices.append(str(option.name)) - #flavorName = forms.ChoiceField(widget=forms.Select, choices=flavor_choices) + + # def __init__(self,request,*args,**kwargs): + # super (Create_VM, self).__init__(*args,**kwargs) + + # self.fields['name'] = forms.CharField() + name = forms.CharField() + + image_list = models.Service.objects.values('image_name') + + ubuntu = image_list[13]['image_name'] + centos = image_list[14]['image_name'] + + # self.fields['image'] = forms.ChoiceField(widget =forms.Select, choices = ([(ubuntu,ubuntu),(centos,centos)])) + image = forms.ChoiceField(widget =forms.Select, choices = ([(ubuntu,ubuntu),(centos,centos)])) + + # flavor_list = models.Service.objects.values('flavor') + + # medium = flavor_list[13]['flavor'] + # tiny = flavor_list[14]['flavor'] + + m ='m1.medium' + t = 'm1.tiny' + l = 'm1.large' + + # self.fields['flavor'] = forms.ChoiceField(widget = forms.Select, choices = ([(m,m),(t,t),(l,l)])) + flavor = forms.ChoiceField(widget = forms.Select, choices = ([(m,m),(t,t),(l,l)])) + + + def save(self, request, force_insert=False, force_update=False, commit=True): + + name = self.cleaned_data['name'] + image = self.cleaned_data['image'] + flavor = self.cleaned_data['flavor'] + nova = api.get_nova(request, 'ui') + + api.createVM(nova, name, image, flavor) + + + return 'here' class Delete_VM(forms.Form): name = forms.CharField() diff --git a/moc_ui/html_helpers.py b/moc_ui/html_helpers.py index 11a40c1..c161923 100644 --- a/moc_ui/html_helpers.py +++ b/moc_ui/html_helpers.py @@ -17,7 +17,7 @@ def project_modals(request): ] def vm_modals(request): - return [{'id':'createVM', 'action' : '/createVM', + return [{'id':'createVM', 'action' : '/createVM/ui', 'title':'Create VM', 'form':forms.Create_VM()}, {'id':'deleteVM', 'action':'/deleteVM', 'title':'Delete VM', 'form':forms.Delete_VM()} diff --git a/moc_ui/models.py b/moc_ui/models.py index 5e98aac..163f933 100644 --- a/moc_ui/models.py +++ b/moc_ui/models.py @@ -44,10 +44,19 @@ class Service(models.Model): description = models.CharField(max_length=DEFAULT_FIELD_LEN) logo_url = models.CharField(max_length=DEFAULT_FIELD_LEN) availability = models.BooleanField(default=False) + image_name = models.CharField(max_length = DEFAULT_FIELD_LEN) + flavor = models.CharField(max_length = DEFAULT_FIELD_LEN) def __unicode__(self): return self.name +# Flavor for VM +# class Flavor (models.Model): +# flavor = models.CharField(max_length=DEFAULT_FIELD_LEN) +# def __unicode__ (self): +# return self.name + + # Cluster information class Cluster(models.Model): """An openstack installation available to users.""" diff --git a/moc_ui/templates/control.html b/moc_ui/templates/control.html index 183e3b6..b950eea 100644 --- a/moc_ui/templates/control.html +++ b/moc_ui/templates/control.html @@ -57,7 +57,7 @@

{{project}}'s VMs

- + diff --git a/moc_ui/ui_api.py b/moc_ui/ui_api.py index 1d1b716..0b12f3c 100644 --- a/moc_ui/ui_api.py +++ b/moc_ui/ui_api.py @@ -101,14 +101,11 @@ def listFlavors(nova): flavors.append(flavor) return flavors -def createVM(nova, VMname, imageName, flavorName): - """ - Create VM on current tenant with specified information - """ - image = nova.images.find(name=imageName) - fl = nova.flavors.find(name=flavorName) +def createVM(nova, name, image, flavor): + imageVM = nova.images.find(name=image) + fl = nova.flavors.find(name=flavor) nics = [{"net-id": nova.networks.list()[0].id, "v4-fixed-ip": ''}] - nova.servers.create(VMname, image=image, flavor=fl, meta=None, files=None, nics=nics) + nova.servers.create(name, image=imageVM, flavor=fl, meta=None, files=None, nics=nics) def createDefault(nova): fl = nova.flavors.find(name='m1.small') diff --git a/moc_ui/urls.py b/moc_ui/urls.py index 509bb19..ecda3ce 100644 --- a/moc_ui/urls.py +++ b/moc_ui/urls.py @@ -48,7 +48,7 @@ url(r'^create/(?P.+)', create_object), url(r'^delete/(?P.+)', delete_object), # VM creatoin - url(r'^createVM\/(?P.+)?\/$', create_VM), + url(r'^createVM\/(?P.+)', create_VM), # projects control # url(r'^createProject', createProject), # url(r'^deleteProject', deleteProject), diff --git a/moc_ui/views.py b/moc_ui/views.py index f36ce1d..2a004d1 100644 --- a/moc_ui/views.py +++ b/moc_ui/views.py @@ -63,18 +63,16 @@ def projects(request): ## Project Control Page def control(request, project): - - createVMform = forms.Create_VM() + vms = api.listVMs(api.get_nova(request, project)) return render(request, 'control.html', {'project': [project], 'vms': vms, - 'createVMform': createVMform, 'vm_modals': html.vm_modals(request) }) ## Network Page def network(request, project): - createVMform = forms.Create_VM() + createVMform = forms.Create_VM(request) vms = api.listVMs(api.get_nova(request, project)) return render(request, 'network.html', @@ -439,15 +437,23 @@ def VM_add_default(request, project): # VM add custom def create_VM(request, project): + print 'lucas-test-enter-view-create_VM' if request.method == 'POST': - form = forms.Create_VM(request.POST) - if form.is_valid(): - print "form is valid." - name = form.cleaned_data['name'] - flavor = form.cleaned_data['flavor'] - image = form.cleaned_data['image'] - nics = form.cleaned_data['nics'] - - # nova = api.get_nova(request, project) #get nova object - # api.createVM(nova, VMname, imageName, flavorName) #add specified Nova object - return HttpResponseRedirect('/control/' + project + '/') #back to control \ No newline at end of file + form = forms.Create_VM(request.POST) + + if form.is_valid(): + print 'lucas-test-view-create_VM_beforeSave' + try: + form.save(request) + except Exception as e: + print "Hit exception:" + print e + + print 'lucas-test-view-create_VM_afterSave' + else: + for field in form: + print "%s: %s" % (field.label_tag(), field.value()) + + print form.errors + + return HttpResponseRedirect('/control/' + project + '/') \ No newline at end of file diff --git a/syncdb.sh b/syncdb.sh index ca1a29f..3c53c0f 100755 --- a/syncdb.sh +++ b/syncdb.sh @@ -1,6 +1,6 @@ rm db.sqlite3 python manage.py syncdb -python manage.py loaddata inital_data.json +# python manage.py loaddata initial_data.json python manage.py loaddata service_list.json python manage.py loaddata projects.json python manage.py loaddata users.json From 19c59f2a31d6d4cf676ed240b07fb77778eaa7ba Mon Sep 17 00:00:00 2001 From: Hang Xu Date: Fri, 15 May 2015 14:07:59 -0400 Subject: [PATCH 03/10] current working version. The setup for Service table in model is still not correct. I am working on it now. --- moc_ui/fixtures/projects.json | 2 +- moc_ui/fixtures/service_list.json | 12 +++++------ moc_ui/forms.py | 20 +++++++++++------- moc_ui/models.py | 7 +++--- moc_ui/templates/control.html | 12 ++--------- moc_ui/ui_api.py | 3 +-- static/CentOS.png | Bin 0 -> 53626 bytes static/Ubuntu.jpg | Bin 0 -> 14101 bytes ...UY9k1dSbJpAA&ust=1431714354270359.desktop" | 6 ++++++ 9 files changed, 31 insertions(+), 31 deletions(-) create mode 100644 static/CentOS.png create mode 100644 static/Ubuntu.jpg create mode 100644 "static/http:\\\\www.google.com\\url?sa=i&rct=j&q=&esrc=s&source=images&cd=&ved=0CAcQjRw&url=http%3A%2F%2Fwww.zazzle.com%2Fubuntu%2Blogo%2Bstickers&ei=c-pUVeiLBcOwggTC5oHIBQ&bvm=bv.93112503,d.eXY&psig=AFQjCNFHa9hfkVKppY3gtkUY9k1dSbJpAA&ust=1431714354270359.desktop" diff --git a/moc_ui/fixtures/projects.json b/moc_ui/fixtures/projects.json index cf34230..2a209f9 100644 --- a/moc_ui/fixtures/projects.json +++ b/moc_ui/fixtures/projects.json @@ -11,7 +11,7 @@ "model": "moc_ui.ClusterProject", "pk": 2, "fields": { - "name": "bit_coin_farm", + "name": "another_project", "token": "" } } diff --git a/moc_ui/fixtures/service_list.json b/moc_ui/fixtures/service_list.json index 00f5155..acb5d6b 100644 --- a/moc_ui/fixtures/service_list.json +++ b/moc_ui/fixtures/service_list.json @@ -152,8 +152,8 @@ "description" : "Ubuntu vm image", "logo_url":"/static/Ubuntu.jpg", "availability":"True", - "image_name" : "Ubuntu 14.04.2 LTS (Trusty Tahr) x86_64", - "flavor" : "m1.medium" + "image_name" : "Ubuntu 14.04.2 LTS (Trusty Tahr) x86_64" + } }, { @@ -165,22 +165,22 @@ "description" : "CentOS vm image", "logo_url":"/static/CentOS.png", "availability":"True", - "image_name" : "CentOS-7-x86_64-GenericCloud-1503.qcow2", - "flavor": "m1.tiny" + "image_name" : "CentOS-7-x86_64-GenericCloud-1503.qcow2" + } }, { "model": "moc_ui.uiproject", "pk": 1, "fields": { - "name": "big_data" + "name": "ui" } }, { "model": "moc_ui.uiproject", "pk": 2, "fields": { - "name": "webservers" + "name": "another_one" } }, { diff --git a/moc_ui/forms.py b/moc_ui/forms.py index e5dd480..92d5761 100644 --- a/moc_ui/forms.py +++ b/moc_ui/forms.py @@ -185,27 +185,31 @@ class Create_VM(forms.Form): # super (Create_VM, self).__init__(*args,**kwargs) # self.fields['name'] = forms.CharField() + try: + service = models.ClusterProject_service.objects.all().select_related('service') + except Exception as e: + print 'err' + print e + name = forms.CharField() - image_list = models.Service.objects.values('image_name') - - ubuntu = image_list[13]['image_name'] - centos = image_list[14]['image_name'] # self.fields['image'] = forms.ChoiceField(widget =forms.Select, choices = ([(ubuntu,ubuntu),(centos,centos)])) - image = forms.ChoiceField(widget =forms.Select, choices = ([(ubuntu,ubuntu),(centos,centos)])) + # image = forms.ChoiceField(widget =forms.Select, choices = ([(ubuntu,ubuntu),(centos,centos)])) + image = forms.ModelChoiceField(queryset = service, initial = 0) # flavor_list = models.Service.objects.values('flavor') # medium = flavor_list[13]['flavor'] # tiny = flavor_list[14]['flavor'] - m ='m1.medium' + m = 'm1.medium' t = 'm1.tiny' l = 'm1.large' - + s = 'm1.small' + x = 'm1.xlarge' # self.fields['flavor'] = forms.ChoiceField(widget = forms.Select, choices = ([(m,m),(t,t),(l,l)])) - flavor = forms.ChoiceField(widget = forms.Select, choices = ([(m,m),(t,t),(l,l)])) + flavor = forms.ChoiceField(widget = forms.Select, choices = ([(m,m),(x,x),(l,l),(s,s),(t,t)])) def save(self, request, force_insert=False, force_update=False, commit=True): diff --git a/moc_ui/models.py b/moc_ui/models.py index 163f933..44ff059 100644 --- a/moc_ui/models.py +++ b/moc_ui/models.py @@ -45,8 +45,7 @@ class Service(models.Model): logo_url = models.CharField(max_length=DEFAULT_FIELD_LEN) availability = models.BooleanField(default=False) image_name = models.CharField(max_length = DEFAULT_FIELD_LEN) - flavor = models.CharField(max_length = DEFAULT_FIELD_LEN) - + def __unicode__(self): return self.name @@ -87,7 +86,7 @@ class UIProject(models.Model): def __unicode__(self): return self.name -# Defining the relation. +# Joint_table for Service and Project class UIProject_service_list(models.Model): TYPE_CHOICES = (('NOR','normal'), ('DEA', 'default')) project = models.ForeignKey(UIProject) @@ -162,5 +161,5 @@ class ClusterProject_service(models.Model): service = models.ForeignKey(Service) def __unicode__(self): - return 'Project Name: ' + self.project.name + ' Servise Name: ' + self.service.name + (" default selection. " if self.default else "") + return self.service.image_name diff --git a/moc_ui/templates/control.html b/moc_ui/templates/control.html index b950eea..a9c6ac0 100644 --- a/moc_ui/templates/control.html +++ b/moc_ui/templates/control.html @@ -33,14 +33,6 @@

{{project}}'s Marketplace

-
-

{{project}}'s Network

-
-
- - - -
@@ -72,7 +64,7 @@

{{project}}'s VMs

Image Flavour Network - VNC + Actions @@ -85,7 +77,7 @@

{{project}}'s VMs

{{vm.image}} {{vm.flavor}} {{vm.network}} - {{vm.vnc}} +
{% if vm.status = 'ACTIVE' %} diff --git a/moc_ui/ui_api.py b/moc_ui/ui_api.py index 0b12f3c..9d278e9 100644 --- a/moc_ui/ui_api.py +++ b/moc_ui/ui_api.py @@ -38,8 +38,7 @@ def listVMs(nova): 'status':server.status, 'image':nova.images.get(server.image[u'id']).name, 'flavor':nova.flavors.get(server.flavor[u'id']).name, - 'network':network, - 'vnc':'-' + 'network':network } ''' if server.status != 'BUILD': diff --git a/static/CentOS.png b/static/CentOS.png new file mode 100644 index 0000000000000000000000000000000000000000..85314efd25140c0beae41d16c19a4b7d49b6007b GIT binary patch literal 53626 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 !xmAGxPEG6DJ>4mH5nm{xqC0;gKy5>lSiJ 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 literal 0 HcmV?d00001 diff --git a/static/Ubuntu.jpg b/static/Ubuntu.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a2d3008216b1e34d141194ee6606c06dd5f4862e GIT binary patch literal 14101 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�KU81ElOm%uph4urTEoO?buXkOr!s1VP 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 literal 0 HcmV?d00001 diff --git "a/static/http:\\\\www.google.com\\url?sa=i&rct=j&q=&esrc=s&source=images&cd=&ved=0CAcQjRw&url=http%3A%2F%2Fwww.zazzle.com%2Fubuntu%2Blogo%2Bstickers&ei=c-pUVeiLBcOwggTC5oHIBQ&bvm=bv.93112503,d.eXY&psig=AFQjCNFHa9hfkVKppY3gtkUY9k1dSbJpAA&ust=1431714354270359.desktop" "b/static/http:\\\\www.google.com\\url?sa=i&rct=j&q=&esrc=s&source=images&cd=&ved=0CAcQjRw&url=http%3A%2F%2Fwww.zazzle.com%2Fubuntu%2Blogo%2Bstickers&ei=c-pUVeiLBcOwggTC5oHIBQ&bvm=bv.93112503,d.eXY&psig=AFQjCNFHa9hfkVKppY3gtkUY9k1dSbJpAA&ust=1431714354270359.desktop" new file mode 100644 index 0000000..8665b75 --- /dev/null +++ "b/static/http:\\\\www.google.com\\url?sa=i&rct=j&q=&esrc=s&source=images&cd=&ved=0CAcQjRw&url=http%3A%2F%2Fwww.zazzle.com%2Fubuntu%2Blogo%2Bstickers&ei=c-pUVeiLBcOwggTC5oHIBQ&bvm=bv.93112503,d.eXY&psig=AFQjCNFHa9hfkVKppY3gtkUY9k1dSbJpAA&ust=1431714354270359.desktop" @@ -0,0 +1,6 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Link to http://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&ved=0CAcQjRw&url=http%3A%2F%2Fwww.zazzle.com%2Fubuntu%2Blogo%2Bstickers&ei=c-pUVeiLBcOwggTC5oHIBQ&bvm=bv.93112503,d.eXY&psig=AFQjCNFHa9hfkVKppY3gtkUY9k1dSbJpAA&ust=1431714354270359 +Type=Link +URL=http://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&ved=0CAcQjRw&url=http%3A%2F%2Fwww.zazzle.com%2Fubuntu%2Blogo%2Bstickers&ei=c-pUVeiLBcOwggTC5oHIBQ&bvm=bv.93112503,d.eXY&psig=AFQjCNFHa9hfkVKppY3gtkUY9k1dSbJpAA&ust=1431714354270359 +Icon=text-html From 58b289463d6fdff7c7d94c17eecd4941218fe084 Mon Sep 17 00:00:00 2001 From: Hang Xu Date: Fri, 15 May 2015 16:00:45 -0400 Subject: [PATCH 04/10] header change, html change, queryset change --- moc_ui/fixtures/service_list.json | 17 ++++++++++++++- moc_ui/forms.py | 16 ++++++++------ moc_ui/templates/control.html | 36 +++++++++++++++++++------------ moc_ui/ui_api.py | 6 +++--- 4 files changed, 50 insertions(+), 25 deletions(-) diff --git a/moc_ui/fixtures/service_list.json b/moc_ui/fixtures/service_list.json index acb5d6b..d75b752 100644 --- a/moc_ui/fixtures/service_list.json +++ b/moc_ui/fixtures/service_list.json @@ -167,9 +167,24 @@ "availability":"True", "image_name" : "CentOS-7-x86_64-GenericCloud-1503.qcow2" + } }, - { + { + "model": "moc_ui.service", + "pk": 16, + "fields": { + "name": "Fedora", + "service_type": "Service", + "description" : "Fedora VM image", + "logo_url":"/static/Fedora.jpg", + "availability":"True", + "image_name" : "Fedora-Cloud-Base-20141203-21.x86_64.qcow2" + + + } + }, + { "model": "moc_ui.uiproject", "pk": 1, "fields": { diff --git a/moc_ui/forms.py b/moc_ui/forms.py index 92d5761..c63dd65 100644 --- a/moc_ui/forms.py +++ b/moc_ui/forms.py @@ -185,19 +185,23 @@ class Create_VM(forms.Form): # super (Create_VM, self).__init__(*args,**kwargs) # self.fields['name'] = forms.CharField() + service_list = [] try: - service = models.ClusterProject_service.objects.all().select_related('service') + services = models.ClusterProject_service.objects.all() + for service in services: + print service + + print service_list except Exception as e: print 'err' print e - name = forms.CharField() # self.fields['image'] = forms.ChoiceField(widget =forms.Select, choices = ([(ubuntu,ubuntu),(centos,centos)])) # image = forms.ChoiceField(widget =forms.Select, choices = ([(ubuntu,ubuntu),(centos,centos)])) - image = forms.ModelChoiceField(queryset = service, initial = 0) - + image = forms.ModelChoiceField(queryset = services, initial = 0) + # flavor_list = models.Service.objects.values('flavor') # medium = flavor_list[13]['flavor'] @@ -215,15 +219,13 @@ class Create_VM(forms.Form): def save(self, request, force_insert=False, force_update=False, commit=True): name = self.cleaned_data['name'] - image = self.cleaned_data['image'] + image = str(self.cleaned_data['image']) flavor = self.cleaned_data['flavor'] nova = api.get_nova(request, 'ui') api.createVM(nova, name, image, flavor) - return 'here' - class Delete_VM(forms.Form): name = forms.CharField() diff --git a/moc_ui/templates/control.html b/moc_ui/templates/control.html index a9c6ac0..14bc2fa 100644 --- a/moc_ui/templates/control.html +++ b/moc_ui/templates/control.html @@ -1,4 +1,4 @@ -{% extends "base.html" %} +{% extends "control_base.html" %} {% block title %}Control Panel{% endblock %} @@ -16,7 +16,16 @@

{{project}}'s control panel

-
@@ -24,7 +33,7 @@

{{project}}'s control panel

-
+
-

{{project}}'s VMs

+ - - - - + - - + Default VM + -->
@@ -63,7 +71,7 @@

{{project}}'s VMs

Status Image Flavour - Network + Actions @@ -76,7 +84,7 @@

{{project}}'s VMs

{{vm.status}} {{vm.image}} {{vm.flavor}} - {{vm.network}} +
diff --git a/moc_ui/ui_api.py b/moc_ui/ui_api.py index 9d278e9..15bf01c 100644 --- a/moc_ui/ui_api.py +++ b/moc_ui/ui_api.py @@ -38,7 +38,7 @@ def listVMs(nova): 'status':server.status, 'image':nova.images.get(server.image[u'id']).name, 'flavor':nova.flavors.get(server.flavor[u'id']).name, - 'network':network + # 'network':network } ''' if server.status != 'BUILD': @@ -63,8 +63,8 @@ def _listVMs(): 'status':server.status, 'image':nova.images.get(server.image[u'id']).name, 'flavor':nova.flavors.get(server.flavor[u'id']).name, - 'network':'-', - 'vnc':'-' + # 'network':'-', + # 'vnc':'-' } if server.status != 'BUILD': vm['vnc'] = server.get_vnc_console('novnc')[u'console'][u'url'] From 33d8e7d5327cbac55dfbf33ff08a6409143e121f Mon Sep 17 00:00:00 2001 From: Hang Xu Date: Tue, 19 May 2015 14:17:48 -0400 Subject: [PATCH 05/10] rm the control base py html --- moc_ui/templates/control.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moc_ui/templates/control.html b/moc_ui/templates/control.html index 14bc2fa..ab2ecfa 100644 --- a/moc_ui/templates/control.html +++ b/moc_ui/templates/control.html @@ -1,4 +1,4 @@ -{% extends "control_base.html" %} +{% extends "base.html" %} {% block title %}Control Panel{% endblock %} From 8ca75e02ec4bd6c37dd649dbc934c9fa22f5d5cc Mon Sep 17 00:00:00 2001 From: Hang Xu Date: Tue, 19 May 2015 14:32:40 -0400 Subject: [PATCH 06/10] add Fedora image --- moc_ui/templates/control.html | 7 ++++++- static/Fedora.jpg | Bin 0 -> 12139 bytes 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 static/Fedora.jpg diff --git a/moc_ui/templates/control.html b/moc_ui/templates/control.html index ab2ecfa..76808ae 100644 --- a/moc_ui/templates/control.html +++ b/moc_ui/templates/control.html @@ -25,7 +25,12 @@

{{project}}'s control panel

Default VM - + + + + Market Place + +
diff --git a/static/Fedora.jpg b/static/Fedora.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2cea6007565bd31f10d4235e9bf6848a253dcf0a GIT binary patch literal 12139 zcmbWdbx<5#^fov!xO;F24DRll;KAJqF2UUc1kGTB1$TFM3l72E9fC6i*X8|v-|klJ zU%Pv|PFGj;t=s+7xpnSyo^#%o-nIZ(^3rnB02o*R0OtJyysZL00gw<75E0;!5D^iP zk&#f)@X*mvQPGHSa53@7h$+a)h)GE)L9BF?RLs<*r1X3Y%Xf5E2p7(9+Q}Fmm(o^6?7@e)=pWEh8%@udbn~rLCi@ zXJ&3;X=QC=>+0t2;pye=6Y?W8EIcAI3X+hRl$`P_H7zf{ps=X8q_nKAzM-+Hxuv!3 zcVGX&;Lz~M=*;Zg{KDeW^2+wk?%w{v;oqZU=+(dLo7=nlhsXbL!2p2&3)cJne*yb{ z;KF{#1q%lUghTuf7YwZDy8*G`;6HL8;7F(vgGKgj;y0So^Bh3x+V_J8AA0iXe4-kk@;28aRfDCq}SX#M}fNa3aCeMb=} zEXaW`$V>i?LVuwkj;tVs2T)U+m9yUh@NVrrs=!W5JJI6-8dRkKc<)B5w8NWWR>^|5 z;2y0Y1g|=m5G0O~7ex>Fe;7=IX_Ov-zGN>6bINsB8 zRuacQ9NC5Z0Iu%{-lEq9z}}+Zx?INI#61h;8$7_V-EchXp$UTc$PFFvhI@-0!Do?Y z$KOYYOkHw1-+FwZ*sDx4mI=pVx%LeJgCg2BH`7AK>Z%~+w83+qn}5%%S%0sVwL=qi&b_x0~5G}py{)smMKp?=gh zImMAYKUamqBlA3L%xPFiE=)?cf9*@pX35N_0s#DTY)OwuZ^J@tNOc% zS^^Id$4daKm71*|5-2$W)TK8(>(ZfJAlHdvGb=SHZDWPE@d|O_d`|=*C}YdSjGxqM zv$Ud44g`@C-kX+kFG!9UXisEqXxTSj+o79K&V2)*T(hA(6G90}zmhh$RS@`Cj3~r@ zG#E9f^eaY@yteFJk54!;u<(`Xjl~kaIkMt1n zKbHqJO+-hQRN3`za5X@aD(9LO{^>Wihq}du^pcXs=02Cc(n3wWjBwpOzX~^f{D9kk z^iNiw1QvoRk@2X$m%_)Ua-h}P&0H%%qQD(VYByqK0(e&RPOgNOD>So_rxqI+%2sIm zRZvTcNF&o-;UAE*LESHY-Y7S$y&i9fQZ^wn5xy4O@l0yl3p2|9V^7k)RsPa+KU+at zWSRAQ`ZR+2bb4R*Zo_qQJL)g@WOVX}4;w~>MRGRZ)@kL0*NfLooUbQmI+UX3w~xAh zFhXP&2?Rrn3awK-w6P8JTSiAn%!&We-7i|FZ8yJ;nH5KRki_yGu4Xu_#tsoxb6yVp zbXP{%M6R$D{ZzxH-^@Vy=)r$3Q2n{~UNhge?T6q%QC;2N6ddnTfby^4!1?pZYBH|X zYM#l{uZms%ZN#pl#>gimesXNV&`0b)Gs=u1cTH!g*-uB^jF-b!UWAGKlX@Fq?fyRp8^bGBvOOEe z-RekBkc+Y4f@a)>ho;9)9BCZVA5|tuT`aNWwnc*aY9%7+kW(U z^f#^4My z%rz3am49f@r1hFAp&|rFj{x~echl;gP}u#xQ6qYO(MB)x)0}o&H}ZuK+u0qClm7P^ z=F8R|hW8-H&19i>_D^Anz@2fq4PA?<0TQfL^H9xGSyBR#Nr$8n1ysRIW;?;@ptClM zqS#!$F^qUehoC*yugxZ&95>fn{_tLh1DN>eRw{A3^#|JZ` zJm2EMyxI;@vI~F5vzFmvoei%q{pt=JPWQ8Dk4H$KJ{oxL3VRfw{=;(NIMcV>G!L=e z=D)aj4HW!&3YVWKUf2V#;3VSf8_-x^G^~joKTgPhq+P{quJ%W6%L;V({HVzn^ZBCz z>28rNsUC|QN79Kg;tjg!Es-0^eX?9m%aec6YtVNT=X1eVx|xp56u9rMF^#K!v`xCt zf!3!_UpVBbz`M>X+T?ElU$Ia#T_d!a^t<>|3T%X;4Ww>j*~B%h_Ku8;t1CV;((4y4 z1F>GO#>BQcV)qt9=AoWMtRjQh_Uvzmi-$d zf05cL5Whi0-{5i$xp45`FROnvL4qy4fS^tCteXwhjWQf(2n1JKi@!Sbk+wY7OEqU+ zGan+iBD-alK#YZeStLtGezUS**}OwW-Pd#^TIo+#;TV@*r(j~fg_dxyo#BEmNhk?LW9wi#3*Pj zoSJBOz>iz9&kOR%3p!R-SDV(jQRuTUy z-qz{UnrA&Hpw|UM*fpZ)ujJ?eFe9L}aZv61F|(Jj(HXua9qK4@URb3Rb+r;2wn<4A z8pPZ;wF{t-+-Mxvs{dgSljfG-!Cu*c48=S}xIRjcW4)l#2Fv!ntR0H3`QQ}wA z$}sX3|4cMf*~pYGV5bG0nYw1S>)bH)a<8K1`dW~#6N1^VsVj9WuPycRX?F&tj8o3b zUe0>VRqUfqzX6CWaA=w%KWc%Yx5Kz_zI7Pg;roV#oBbC^%ZZ4ZILSmWf0XXY?@9fc z4j$!ql8MpRjy28WZ@RKe^p2abHg&($>wjs_kN1roD%7nC>{&oAx~G{)2=0F4S-^DJ(Pv?uDFmil(qe<1io{Ny1E zRf`{>mR}M3$jlRh$A~cpKjY1`*KiF7&^{~9b~qO4>*yRcV^w@0cgosMT&dAN_q$*{G!mD+NWqT122Uq3fp$-hnz~1V30y&1u7XFO}xBD=qOm3 zM0khzajGL7#Fl*TQ82j32(8LvU zpcI>DeA4!VfEOz~%X29x-Fk9yrYrPbf6L#v*V)#lOxcQR{Z|@KlZSnwr^CcPdHL*2 z2a4Up^|FaCgAsDvxg6GZT+A=g#-mMy4&}-dQI3x0xf_M{magA3aA|6zgo0>6Q|>$i z;1E?C5y4Cy-G4%je>I?py{dUfA6ClmgK1@9;yy2|0?}U9S0_a?TTw}97Z@bWA*|<%QdyG^FQO&z+w4V z#bi9GvIGnLl1a#bxh^P{J&<7*hkHarv3DU0Z}R)FNY^o2-B6w$mT+1~4(|#naX}*Q z33^y8T?~81^-Ae)3$BHgZg_CtvcWbmhv2!;+F}LX{_(C;OiI_K=dQ9 ztEkdFtRfTh%$|k>_Mkmtp}IUlIsc_f8`mlf)_^MDu1IV8cG6Qg)7}_r{L94#{LrgN z_U}&EmW!xbU^^S-uAf|R36xmXhj;gSI3sXi2!`@F(eKQf8ANZ!2s=ast_`XQUAc&G&TkWu>CfT z=xgTBnTy%lT?EE*_b8nI+7;pN5_}a@l09eQGE#GE`Z`ah6X5mQXgT^wCW*<5yyl^uwi9yv8`b6QaKa*x9<~ce&t!5KCk%4 z3)A;>+we(i(2ewQHH)6;LhZ~Ua~NrC*AY+v9Y8w)9Z?xB0hL|kXNE@hvX6TkS7V2K z6sJPQyN^U{amp^}avK@riz@M4iKAa8YRlG**D~+;)VZr00&z*VFqM8cTxVi;%w^rM zN4Zdm=%4&${F62wS}}-fu1ab6=d*>T1}Tn{Xm^rf<2*}Mrm5Dd0DMQDz)ByO))>9BYtzwkjfX!-`{eC-HMm z4&}7#L`HDb!|N?O*TqIX-GTa`P!`9yg}_m6CBI!M5gaLYun@7lM}Qh{u-t_2+=mYw z`i!Z_4>15BXi><9sXo`%*R$6U2Q=&Gp88eP4dRW>#YO^vOL|Or1H>$rFGhOF?0$Tm zY^u$cv1qE*i1CfkjFA1lLgH8|SExpexR!!QdgdKp2MF4$apLK^$i^%@{RWWbQeo64eg+bsY;mmqy=^bHU^H>BJw z0>sR%+E@D0mq|pGjTenqb}~miE9l2O5cw@3AsF$xG_NU)tt~{fI6+Y@ss8|cw3W6a z4Izv`6Z;8Fv$eVVi11R_zO^ubA27n_p)AA!YEBmG`hjVbms-CMhvhnmXs~ee*?xDu zQ&qEvU-UYYweOHaSDr(Qkh+qe_SD`)X-4)aswvJte)%Bw&le{d{^#TLY))y$mXU2K z^Z8~Lp%l0BBNoS;KhgWa-qvw(UiT5P5i3B2a(C*Z{Zse*)+ql46hSK8+3-IE&&1huJw~^oz%AkPAUUU;U%X zYDP>y*i5X_z@E1=20Zl=>;|$0t})IN0vFd6*1I|hwuf1A zbP&7g>`r*Au3`{(LK{t(H~8r}78KhC40et!q{cDW3z<|^_zAk-B@MB0Q+eFh&}aNMOLeGq|Jb{4803@Jx4RXn%BA$s@zE)mExgw}GsQZiXjQ zTQd1m(eVe~ieq30C*B6v)NZA}$mP=xO*q)?I!s32UyVj1`GbWzll>UCT}IN@3)8+& zXa32DM~qU8!lE^v&Nv&a@?7gNSNk8TYt2{^m$OX>>mNbAA;4d-51HF?Z80LZ#1t{(QPV`Vl;Y%8%w_ z1&p%ct06buSr^+OHDYgRojIJNZLon$egjyg+}U<~mA4{w6ChpS>)*uQJmzf^O)2SV zTAUiR>Il_g*TqDg<$sVq_1Iuq<585~l$|+mL@ioH@352}Qjh6dyRJ@Zv{&*s(`uV@ zNOxPr`QZ5N8n}dp`McfeBC}{=NJQDQYG05(uN_V5UEqW9Ra2W$dDjh9V7}<&YpvCm zn5|*hl1c2v3~EQjZNVZvf?t!O+SX^tQTX2g_JO}^OSRZN;+;bvQ-22~b}QW`sRl#$ zOmf_5J6>n?lg_a%B2nsLuFSC?7VS$*2pnVDgLtMT^AhzVL#=s0sqq2OP5BK|gxDN3 zE)B}roaVNF`D>zTxjs9UYIAZ7LiJL4b)4>~M6{i9rqMcrc&5_g{QPv+hbyU$dBV5@ zY%2(=L6j`trghucT@Eb%jV`e1D5I$=f%q*+ftyhiE3Y1Bo3v~8LxFn!`1PK0M1_`1 z6)vvdMH3TMWi1p|!$YjUm>+_o#@;D;M#2bBmpCF6p%00z1lKVPXc zL|RjVrw4qdn)0e?5?m0>E~8?L5TxgHC?g52x$)WwQQ zvos9FrYZ@B%+B(U`@7n^!tYmTYt0l)eF@r)$Iwg!2V)lcg=~$}Zt6pm6N=U&(L3&7 z%&|*BC3`V~Krrr-`E7MoMZ=S!AbjuyelVO$IgUA1&=Q-(y%vwBR8PH}f|RMQ-tFzG z(z|$YWgfiov31Y&dtUvuGTz@VD$Z!eSE1yeDJm5eh*gBZSf9?ouXd$N;}*Us-5H>d^t&|>^troL=qt7vDp|Zmtv*TmMrCl&>XRyHyj>bKyyp5c%9QUQ> z*3SYqw36{G%j%o=>Tdu`u~2V(n-gNz`a=dZw8|e8OeY zdi(ZT>z=%*skpqT#$ua0y{df2uNK(J2cFBs7>Cb*5xOb0C6x72rj>^GAitv68Ru`O z)nXGt0!FJH3}31Ny?8xp$Jr*==o~L5C*Lu-!r=-#PjrG*WYO=RoK;b3(;MUyNj(`= zrPyqz;+azC&%hrl-T=L96Bt5w__J!lHjHQS_>0qF@9ZeMAv)?utKpwjbjGEZWdAGd zt5Wn=jpHoSW-&1paGw#-F{sY_52VREbppL47O@<9s-zzKGaAMkxYSNV*dNxj=@ zo0<~e0GqPPM`;Ed12p9A;fy8cj}&6la@x#pl`g?ncZKo95&QrK#DTVdQH#FmXZIM6U*csT1JbT4{?0f5rHj87lH)#ZQ{Vd*kN0 z@yZj1`6*zE>t=eHIyBJ3PD&p%`lk-2?+^H%*f3s1p83scC>7~bc zbf*eKIJ0kSoWidP8K-~luSZKXy7rY+n?d=0S90FT3Ksvc7(p^L(e+z8q&VdOou90Q z%*HhC{=n{qqxhtW5}($Fm$%!RS~5tW={!Fq7OGasA}1G#MAUn@Qg25bHNz@ILQVuF z+YIFyZnPt`-*1W3)le!ZS!4IXoIT!2b+Jz3dYeKt28&exF@s8RuFf@7vQ{DhJ$bFat za`?AWu5;l`Q!}jlsGY22lJ<)@O4HuT*g+OdBnX6{AaI8B$Zj)_NN99Zsu_M#h9r}h zwk;)S%U_vC1pk9Cz8SS<*wvFtbB#ai#Dz?f{+XJAsC-rrt-#|OfbpL(-ZM$UxNkN3 za3S*K(!n?UH-P)3aqjcU5{XA&GfZu-2$w44mdk95U)+ zjF4$#v4D)u8=xO_I^ru7^AP5DJJKx!%Vyhv4R(VVv4G>#UZEu+>w(bW!z zg(QI3X{vM5rW~=US&Pm6^D9HxJ}cD&^5J61)&g`up^VE-+jYO~Iy<=b^DAq6d=Dp0 z!nfh06mjK;n`+VSG?Gl|179x!Bv4Wozs6;hl4NX7wdbW{#51~Rp`AsJ&5>Q8FdV7g znG;}5Gy6W4yqLeTeB?@RHD1woDE(QdyS)oKe^%HZdRCD{K-e7$BW3D*tUw+R(&#M0 z^w*f=`E&DS=Ebeuk)tQ~!iFtmOIm`tMMU}X-_R!mirzN>dT+U%wqWC$HT3AouVnPO zNNa-R6&8_vk9?l{*k!g|OV;I`Fa0s3+m4ND^mS{A8DPnCPO@tiu9JCcVHU&IbiV+2 z#r8FgyZf4w&j(!JUK~(8Wo`M!!MkU1-AC_`R0fFer|O-Yi==_(N(A_6IQ z$=Ysuj$X;`V+RDmbv7HISvFz>aD#Tja)WsMy#99#nNKlmhuoR+wFVOlrzq?W!?wzmB*)5_q#g`~|Mgf-+k>4DRYi&dqTis#W zoG-zv8o^AnSEaFPYfqi*e(HHESm4FN^I2I{#+i-^jGDRG?gwnujWCGxl7=` z^AFk`vB7O9R^HQ%wz*PQr+zbRtJ?*?!eRc-YZQXsH;{e-7g7F@+*nk7+99jB%@Ubk*w!JU{ihOt7at};p5MIX&sdNo-%+=W zEUIHjp1Extd27VfK}=g;)CZSBnP<^4TqL$e8H0S5aae2sJlw?Tpv}Tw#6IP0;; zd##c~F`sgkE2UnR=+ zI6iA|tes#e|3{y*N&FEbN+b;4H>{p$?iHRvy`?G@uHX%@$PNy?#x+8eCT5`9*w*aC z^q(oT2W~|f9_`79-TEq3Au>^4=^vv8ByGvOYj>awh;Q1haws`n?c%e5ScrQz{aSx4 zaesf1v%~T*`7X$87IBgEApcUmeP=&)Y*4!cIahiU8V_TUrA>EH}aZ8WT2W?a+%Ag3_kk21RXY5~JM4C%nA8V`4 zF15qC-vEF<^vv6QRNKdfbjh$DmneN(;0VAR;u}9psSWXSh*Te%t!WY0Tlv7@3Q^k5 zLf}Uc%(!BZF1xL){KYT&IraA^r{)hh)G&>UsP|USb|Q)8_|$PuHfFA*QM+XsGvk!W zmVRb*h1Tl}dGdc^qOxWtc2zpUCT2dQ?N}j`T65~gN*HcrUpfwGFEpQlJZ_t{T2}42 zv$uK^yFZ3h_-sTG=GC^5&!s3dY# zRpvT5p{T=W(;8?AYEi+rqpPZQX%px8$r~07RD9C-sDJX~FBkhe`T8HBGiTqbc4>%a zw1IG#Dwz0){TB#hJBAF7l{9f1I@ERI2%pQGWPwj>&L=Z%(IkC(eBnuhNyP)-%%4s< zb;EPb5@K!VE4}Be#$g5Ywc-!OkQ{l&qA?Cw6fJq3@D=z{Wxu($N{EQ}Ji46?*;Fqn zm)!fR*44#*a&-pgi7EdAyFS+&$P9>l8sM!vy0ljCYPv$;l(YU(>vvfY6hCx0S?D2( zm#&`u`xeKJLs%~;7MJNeVVo>n&{TZL{cPGBASLs+*r;D`;8)KgqcJOAV6QWF-{3A> zV7A^hW~dR~Jga-T7>=}Q%;196r;fN83nHcI80Ypbrg=Y!Z5HZ5EVkREf@wuuP8rTP z2mpg$IJlUI=;ll>O*1n&wOFdiW`KZ13JHsMr}N=XID4=ui!O~oL7ji5p~{57gW*N@!SnX+LK>~1 z`ab36_M$m4GU^Hi)_Rs9*7k1gvS)dgYrQTC6l%(J(28~QBNunJ_<#S%9d|Y(AMe72 zCEN?&0A|bm)B;g*y4mC4mqo(W#cRr#dF{Se9%yrPHTjrQ`^-0Tp0%@moL(OXl!5w? zp!=vBLj{>x_g|j{GeaBKY+draLe50gl|5XrM`{% z6a5XaJlkNNDE9<;x^Nb$}h$*S!y4>GNCkH+#>*O=>9OS~T*>h?0?mq&aUtca!zhEG)dPbZpsnkBtWz~cCnvED;aM47^~MFqM2n4 zir-41VDk`G*~-goXmRCh>E*U@Xhx_2JJB@5S3g3q4{O&8kj**eWZFu?TbG;iPPAYHF!nRuB*qe?F@2Z z(=>6xJTzAGk9tJ#B{m{OM$k=xUBx6-MOmKFdZ>5dvQPM@rz`cnQ8YYlbjM#6%^aZ{Zs8yoro z01Mu)!W@7$2~==Xuk|u{9Ls<^&z*~=%d^2t7|q3db*7zBuVgH#h_NKgh*jxzg?|g<5Mqe)v4|mOmDZ zbL{M;g;_(C3>14*|EwgrwafoX`Ua3Mywp;ZH>6hOW8>0A#yvfdlwA+$cJTFIxxvUs zETmM)Vf+sG3n;zKZr`hU@IU`Lrz&Nxqx!`g7H_n6Z8boXj>1^tLOBO*6AQXssq$Xj zDCmBKsm{=ri`9W5q@s_XtmsM`DHN;6u9u)~=1@9$^ISVd4Ek}sXX}gqGZmfScJngG z?#_krXWZ>&|6vvCUdiJb;w#W7jO3p4Mux?4XXwDG3Qx8dnIWMeK3Iyz?G^FT_kKt# zZShRZGK{ce1ccgh(*p?1O8R7Y*;K#1oa#FZQp7bxGOW zZwCZ0y8?B_WnN0RO#VtVu-5%?VY?enA3cSRpaTSDgjti&^ ze~sFJ3nQH2&sQmlV8_D%0BeeOqU3{v>l-VLSa4>9#uCl!4neN6V*63GJ+7yORsJw^ zjn?zNtNc8uBtMx7aP-%tr)9(MlfsamqX9YtgcWRPW88w?Gu0ND-o<>&%aI2fK#q|& z0PGj5mz=&v2bCTP86Wx__&i8V1E8S+g&t5rf$P;LdzpdVRmhZTF%pB6;@Tyc;Ralb z*Pq|%CaGXWC@;2!rR5z2BFA9>5$F(SDPO}H^Wg;whSP2NWbC%z08xU75j^-c63#Y4 zP{LMCl*1`3Wih?eWDOfwSUIK^EDVmDBV$Hu0?(Akm(a%G+E$y{ug2TG6Bj0eulP3} zwotrXgbGF%7rmcSc-jIvKSGH>FvqrJcVZ69d&SFs9S`lV_76|(&a1)LugS26}pGc!R27t zbX(gCM8(N9HV$fpTiQ#1@Aj|CufCkBc^lX44Io*qGTlM%M|OFq)0nkym1S+2tfe9u zvcCnBU92}W>&L+tA&R45VXI;=>16fOyJxKefot`n?6X}{Vj@GQTbsZ^Mo}kG?=#0j z@r<9H6`o0hb_Gk}7Z19Sds2!byZL9`-A&{bn?-_VPW|HQayRYpczx^RQZ+w|7rtKFaD@!4bGuiA9{z#4pfgL&@s7lNCL8xmcXDm?T2 zJMx?uq&s}2cFoG%@2XM?_Vzscb6N|~h6MR-Y&@4gN`NASp>V&C759Z}Hp#tt(ZM6! zV0^6XfH#0d+M`%soA{KUh*{x7*4L&8YEh2XHi$@_qRh5GEGGKB&*GOK4AzUBEffKt z?$ZCg04jsUiA0$GRO-%o{B@Tk&0`EDBsx~6<8CBX?-TV)%}*dD17nCWLTb2Casm!77;&2Ttr-{P@&I(%}-lFjUY$fj?po`kUl2TKgQI9 z1Url4RdD-rDXhP|?;$;cr$Ho5uA83nIn_^|Yq0M^_{rvav@!_u zMAZuivH8*{1HzzXVbyzWWhy4gl%G#nDN=m?Abc)E*FC-`p3U@D)c-1- z_LIl1FM!P}@5zoA+||f3*Y~`n>N1 z|J&QJaaiJ%!I+Zt)RZAJCDzUbg7`n2sq&bS@HI?eVt&6fy$=t=hcUZ&I0*c7bfhSH zs^PyBX@!;Vxc}426r?G~m_s1IPo{|108sm{xhb*Xz3DjZlbkrk H+w%Vbp+zz& literal 0 HcmV?d00001 From c4f24b89844afda526636c3c2895d3fbde0fdada Mon Sep 17 00:00:00 2001 From: Hang Xu Date: Thu, 21 May 2015 12:16:25 -0400 Subject: [PATCH 07/10] add new html templates --- moc_ui/templates/control.html | 16 +++++-- moc_ui/templates/network.html | 87 +---------------------------------- moc_ui/urls.py | 4 +- moc_ui/views.py | 13 ++++-- 4 files changed, 26 insertions(+), 94 deletions(-) diff --git a/moc_ui/templates/control.html b/moc_ui/templates/control.html index 76808ae..a5021f9 100644 --- a/moc_ui/templates/control.html +++ b/moc_ui/templates/control.html @@ -19,16 +19,24 @@

{{project}}'s control panel

diff --git a/moc_ui/templates/network.html b/moc_ui/templates/network.html index 56a92c4..22070e6 100644 --- a/moc_ui/templates/network.html +++ b/moc_ui/templates/network.html @@ -18,92 +18,9 @@

{{request.session.user_name}}'s network<

-
-
-

{{project}}'s Virtual Machine

-
-
- - - -
-
-
- -
-
-

{{project}}'s VMs

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - {% for vm in vms %} - - - - - - - - - - - {% endfor %} - -
NameIDStatusImageFlavourNetworkVNCActions
{{vm.name}}{{vm.id}}{{vm.status}}{{vm.image}}{{vm.flavor}}{{vm.network}}{{vm.vnc}} -
- {% if vm.status = 'ACTIVE' %} - - - - {% else %} - - - - {% endif %} - - - - {% if vm.status = 'SHUTOFF' %} - - - - {% else %} - - - - {% endif %} -
-
-
- +
+ diff --git a/moc_ui/urls.py b/moc_ui/urls.py index ecda3ce..25ebd2c 100644 --- a/moc_ui/urls.py +++ b/moc_ui/urls.py @@ -22,8 +22,10 @@ url(r'^market\/(?P.+)\/(?P.+)\/(?Ptoggle_active|toggle_default)\/?$', market), # project control page url(r'^control\/(?P.+)?\/$', control), - # + # network page url(r'^network\/(?P.+)?\/$', network), + # storage page + url(r'^storage\/(?P.+)?\/$', storage), #VM pause/unpause url(r'^VM_active_state_toggle\/(?P.+)?\/(?P.+)\/?$', VM_active_state_toggle), #VM default add diff --git a/moc_ui/views.py b/moc_ui/views.py index 2a004d1..09ea5a0 100644 --- a/moc_ui/views.py +++ b/moc_ui/views.py @@ -72,12 +72,17 @@ def control(request, project): }) ## Network Page def network(request, project): - createVMform = forms.Create_VM(request) - vms = api.listVMs(api.get_nova(request, project)) + return render(request, 'network.html', - {'project': [project] , 'vms': vms, - 'createVMform': createVMform }) + {'project': [project]}) + +## Network Page +def storage(request, project): + + + return render(request, 'storage.html', + {'project': [project]}) From ffa53a19119c6dc63b2f841b63dc64df405af8cf Mon Sep 17 00:00:00 2001 From: Hang Xu Date: Thu, 21 May 2015 12:20:03 -0400 Subject: [PATCH 08/10] storage --- moc_ui/templates/storage.html | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 moc_ui/templates/storage.html diff --git a/moc_ui/templates/storage.html b/moc_ui/templates/storage.html new file mode 100644 index 0000000..e94757e --- /dev/null +++ b/moc_ui/templates/storage.html @@ -0,0 +1,32 @@ +{% extends "base.html" %} + +{% block title %}{{request.session.user_name}}'s Storage{% endblock %} + +{% block content %} +{% for project in project %} +
+ +
+
+
+
+
+
+
+

{{request.session.user_name}}'s storage

+
+
+
+
+ +
+ + +
+
+
+
+{% endfor %} +{% endblock %} + From 8016773ad6586faad767fbe082fff0e41aa849cd Mon Sep 17 00:00:00 2001 From: "Lucas H. Xu" Date: Thu, 21 May 2015 15:51:02 -0400 Subject: [PATCH 09/10] change hardcoded project name from ui to admin --- moc_ui/fixtures/projects.json | 2 +- moc_ui/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/moc_ui/fixtures/projects.json b/moc_ui/fixtures/projects.json index 2a209f9..be7ec5d 100644 --- a/moc_ui/fixtures/projects.json +++ b/moc_ui/fixtures/projects.json @@ -3,7 +3,7 @@ "model": "moc_ui.ClusterProject", "pk": 1, "fields": { - "name": "ui", + "name": "admin", "token": "" } }, diff --git a/moc_ui/views.py b/moc_ui/views.py index 09ea5a0..2b3dda8 100644 --- a/moc_ui/views.py +++ b/moc_ui/views.py @@ -51,7 +51,7 @@ def helps(request): def projects(request): - tenant = api.joinTenant(request, 'ui') + tenant = api.joinTenant(request, 'admin') project_name = models.ClusterProject.objects.all() project_list = [] for project in project_name: From ea4c2a79ebe6d91714ab896274df162c651a9bdf Mon Sep 17 00:00:00 2001 From: "Lucas H. Xu" Date: Mon, 9 Jan 2017 16:05:40 -0500 Subject: [PATCH 10/10] update outdataed python client libs --- .DS_Store | Bin 6148 -> 8196 bytes moc_ui/.DS_Store | Bin 8196 -> 8196 bytes moc_ui/auth.py | 106 ++++++++++++++++++++++++---------- moc_ui/fixtures/projects.json | 4 +- moc_ui/fixtures/users.json | 2 +- moc_ui/forms.py | 6 +- moc_ui/views.py | 2 +- 7 files changed, 81 insertions(+), 39 deletions(-) diff --git a/.DS_Store b/.DS_Store index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..32f4520b79f93df91083be726051b640995e3ec2 100644 GIT binary patch literal 8196 zcmeHMO;6lL7=C9%!49Dq0s*x>tb!^<3W`Vw{ZJHjSwQWoA0QT`AV@Y|dswV`JzLug z*-)yz^f&b5+EdR}e?X7Dw8tKM=pTqw^_)C2_HMl1q?brlq|8X3cRcev^UgeGUhiv& zh?U#!b)tD9GH^+2jiY)-k>m0jDuuLX8kT`i^d@t8Wig)f-cLq#trgG;ypjsY_)x?pZ7H?g#H!GNN~Hj>Bj{EIZR7!pQ%r3swcW%j zD&|bG2bNM9CZme7f%o>`iqFy$S*qJk4EC05s30jxA=?Dz;=<)~)OpPnu+-&`!-Sb6Vkv3UCa^2%cI zotsN%XQnat_VwG9`_0b7)346H{vI1bVQI{y$>hFY|A5wjAf9uaZj$}n+vH!C)!*j% z@e32LPg+yc7pG>XW@l$F&CSkFzwu_xx>&cJFB+j-@S5;NSoYhzW=%#Aq~eHRE9A%6 z?rzK<#8vMhhNg3bZSLNC+O^YZ0WuJqu9!uPjC_V?F1s=7~D$w7D^wdg9crtRs4M);KX(5Tl$fH zph zGzTLBUQjTImMdaLCVm;fam?Dr+|SqnlW`_H`zY`+_7G!sXK-#N<4hK70^5N~PCpLk z^ij_x%fJM>Xa!zSfpZCeUgrNB&;S1af?hOTE1(s4nH69o>(%u#R@nPtkzcILwTrm! z&$8TF~!*C55hDJq4Zs D!TisL delta 105 zcmZp1XfcprU|?W$DortDU=RQ@Ie-{MGpJ516q~502;ws^0>w5KPGg_gAhnpCgF}!R pBnTAa1`@77th%xAJM(0I8AV3M$)+;eJWLRCKt?lcj^~-f3;-`E4{!hg diff --git a/moc_ui/.DS_Store b/moc_ui/.DS_Store index 632839911dbe0b91deb63dd65a69fae594ede3fe..19a7c0613998018ba3371111b14c48d86330da56 100644 GIT binary patch delta 191 zcmZp1XmQwZU10KZ0bb>#^5TM|octsP28NSK1v#0;B?bo98JU<_SlQS)I5{~uc{wNZ z3(HTo5;l*C4$jCg4@fM@NJ=aM%f$;wR973BTk0s77+KWnC{$aTndvB)T3FQ9a&m~P z8rpg$R8GDiaDB6`P#x38 V;+ssH*(JWQOs*0!+*o{#2>@bPFnIs~ delta 129 zcmZp1XmQwZU10J9!3(lt4EYQ>3@Hq{3}phAg1cWQG!;Vm*coAf3yQ