Merge pull request #308 from levivm/develop
Merging ssh fix from modulos
This commit is contained in:
		
				commit
				
					
						c38b36a8a5
					
				
			
		
					 7 changed files with 171 additions and 80 deletions
				
			
		|  | @ -85,7 +85,7 @@ | ||||||
|                           <ul id="g-account-menu" class="dropdown-menu" role="menu"> |                           <ul id="g-account-menu" class="dropdown-menu" role="menu"> | ||||||
|                             <li><a href="{% url 'hosting:logout' %}"><i class="glyphicon glyphicon-lock"></i>{% trans "Logout"%} </a></li> |                             <li><a href="{% url 'hosting:logout' %}"><i class="glyphicon glyphicon-lock"></i>{% trans "Logout"%} </a></li> | ||||||
| 							<li> | 							<li> | ||||||
|                             <a href="{% url 'hosting:key_pair' %}"> |                             <a href="{% url 'hosting:ssh_keys' %}"> | ||||||
|                                 <i class="fa fa-key"></i> {% trans "Keys"%} |                                 <i class="fa fa-key"></i> {% trans "Keys"%} | ||||||
|                             </a> |                             </a> | ||||||
|                         	</li> |                         	</li> | ||||||
|  | @ -149,7 +149,7 @@ | ||||||
|                         <li>⋅</li> |                         <li>⋅</li> | ||||||
|                         <li> |                         <li> | ||||||
|                         <li> |                         <li> | ||||||
|                             <a href="{% url 'hosting:key_pair' %}"> |                             <a href="{% url 'hosting:ssh_keys' %}"> | ||||||
|                                 {% trans "Keys"%} |                                 {% trans "Keys"%} | ||||||
|                             </a> |                             </a> | ||||||
|                         </li> |                         </li> | ||||||
|  |  | ||||||
|  | @ -53,7 +53,7 @@ | ||||||
|                                             </button> |                                             </button> | ||||||
|                                         </div> |                                         </div> | ||||||
|                                         <div class="modal-body"> |                                         <div class="modal-body"> | ||||||
|                                             <h4 class="modal-title" id="ModalLabel">{% trans "Do You want do delete your order?"%}</h4> |                                             <h4 class="modal-title" id="ModalLabel">{% trans "Do You want to delete your order?"%}</h4> | ||||||
| 
 | 
 | ||||||
|                                             <form method="post" |                                             <form method="post" | ||||||
|                                                   action="{% url 'hosting:delete_order' order.id %}"> |                                                   action="{% url 'hosting:delete_order' order.id %}"> | ||||||
|  |  | ||||||
|  | @ -17,7 +17,6 @@ | ||||||
|                         </div> |                         </div> | ||||||
| 						{% endif %} | 						{% endif %} | ||||||
|                         {% for field in form %} |                         {% for field in form %} | ||||||
| 							 |  | ||||||
|                             {% bootstrap_field field %} |                             {% bootstrap_field field %} | ||||||
|                         {% endfor %} |                         {% endfor %} | ||||||
|                         {% buttons %} |                         {% buttons %} | ||||||
|  | @ -32,34 +31,8 @@ | ||||||
|                             </button> |                             </button> | ||||||
| 
 | 
 | ||||||
|                         {% endbuttons %}  |                         {% endbuttons %}  | ||||||
|                             <div class="form-group"> |                         </form> | ||||||
|                             </div> |                         <h5> Use your created key to access to the machine. If you lost it, contact us. </h5> | ||||||
|                         {% else %} |  | ||||||
| 						<h5> {% trans "Use your created key to access to the machine. If you lost it, contact us." %} </h5> |  | ||||||
|                             <table class="table borderless table-hover">  |  | ||||||
|                                 <br/> |  | ||||||
|                                 <thead>  |  | ||||||
|                                 <tr>  |  | ||||||
|                                     <th>{% trans "Name"%}</th> |  | ||||||
|                                     <th>{% trans "Created at"%} </th> |  | ||||||
|                                     <th>{% trans "Status"%} </th> |  | ||||||
|                                     <th></th> |  | ||||||
|                                 </tr> |  | ||||||
|                                 </thead> |  | ||||||
|                                 <tbody>  |  | ||||||
| 									{% for user_key in keys %} |  | ||||||
|                                     <tr>  |  | ||||||
|                                         <td scope="row">{{user_key.name}}</td>  |  | ||||||
|                                         <td>{{user_key.created_at}}</td>  |  | ||||||
|                                         <td> |  | ||||||
|                                             <span class="h3 label label-success"><strong>Active</strong></span> |  | ||||||
| 
 |  | ||||||
|                                         </td>  |  | ||||||
|                                     </tr> |  | ||||||
| 									{% endfor %} |  | ||||||
|                                 </tbody>  |  | ||||||
|                             </table> |  | ||||||
|                     </form> |  | ||||||
| 
 | 
 | ||||||
| 				        {% if private_key %} | 				        {% if private_key %} | ||||||
| 				 		<div class="alert alert-warning"> | 				 		<div class="alert alert-warning"> | ||||||
|  | @ -70,17 +43,7 @@ | ||||||
| 						  <textarea class="form-control" rows="6" id="ssh_key" type="hidden" style="display:none">{{private_key}}</textarea> | 						  <textarea class="form-control" rows="6" id="ssh_key" type="hidden" style="display:none">{{private_key}}</textarea> | ||||||
| 
 | 
 | ||||||
| 						</div> | 						</div> | ||||||
| <!-- 							<div  class="form-group pull-right"> | 						{% endif %} | ||||||
| 								<button type="button" id="copy_to_clipboard" data-clipboard-target="#ssh_key" class="btn btn-warning" |  | ||||||
| 									data-toggle="tooltip"  data-placement="bottom" title="Copied"  data-trigger="click">{% trans "Copy to Clipboard"%}</button> |  | ||||||
| 								<button type="button" id="download_ssh_key" class="btn btn-warning">{% trans "Download"%}</button>   |  | ||||||
| 							</div> -->				         |  | ||||||
| 						{% else %} |  | ||||||
| <!-- 					 		<div class="alert alert-warning"> |  | ||||||
| 	  							<strong>{% trans "Warning!"%}</strong>{% trans "Your SSH private key was already generated and downloaded, if you lost it, contact us. "%}  |  | ||||||
| 							</div> |  | ||||||
|  -->						{% endif %} |  | ||||||
| 						<!-- <a class="btn btn-success" href="{% url 'hosting:virtual_machines' %}">{% trans "Generate my key"%} </a> --> |  | ||||||
| 						<div class="clearfix"></div> | 						<div class="clearfix"></div> | ||||||
| 				</div> | 				</div> | ||||||
| 			</div> | 			</div> | ||||||
							
								
								
									
										96
									
								
								hosting/templates/hosting/user_keys.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								hosting/templates/hosting/user_keys.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,96 @@ | ||||||
|  | {% extends "hosting/base_short.html" %} | ||||||
|  | {% load staticfiles bootstrap3 i18n %} | ||||||
|  | {% block content %}  | ||||||
|  | <div> | ||||||
|  | 	<div class="container virtual-machine-container dashboard-container "> | ||||||
|  | 		<div class="row"> | ||||||
|  | 			<div class="col-md-9 col-md-offset-2"> | ||||||
|  | 				 <div  class="col-sm-12"> | ||||||
|  |                     <h3><i class="fa fa-key" aria-hidden="true"></i>{% trans "Access Key"%} </h3> | ||||||
|  |                     {% if messages %} | ||||||
|  |                     <div class="alert alert-warning"> | ||||||
|  |                         {% for message in messages %} | ||||||
|  |                         <span>{{ message }}</span> | ||||||
|  |                         {% endfor %} | ||||||
|  |                     </div> | ||||||
|  |                     {% endif %} | ||||||
|  |                     <p class="pull-right"> | ||||||
|  |                         <a class="btn btn-success" href="{% url 'hosting:create_ssh_key' %}" >{% trans "Add Key"%} </a> | ||||||
|  |                     </p> | ||||||
|  |                     <h5> Use your created key to access to the machine. If you lost it, contact us. </h5> | ||||||
|  |                     <table class="table borderless table-hover">  | ||||||
|  |                         <br/> | ||||||
|  |                         <thead>  | ||||||
|  |                         <tr>  | ||||||
|  |                             <th>{% trans "Name"%}</th> | ||||||
|  |                             <th>{% trans "Created at"%} </th> | ||||||
|  |                             <th>{% trans "Status"%} </th> | ||||||
|  |                             <th></th> | ||||||
|  |                         </tr> | ||||||
|  |                         </thead> | ||||||
|  |                         <tbody>  | ||||||
|  |                             {% for user_key in keys %} | ||||||
|  |                             <tr>  | ||||||
|  |                                 <td scope="row">{{user_key.name}}</td>  | ||||||
|  |                                 <td>{{user_key.created_at}}</td>  | ||||||
|  |                                 <td> | ||||||
|  |                                     <span class="h3 label label-success"><strong>Active</strong></span> | ||||||
|  |                                 </td>  | ||||||
|  |                                 <td>  | ||||||
|  |                                 <button type="button" class="btn btn-default" data-toggle="modal" | ||||||
|  |                                         data-target="#Modal{{ user_key.id }}"><a | ||||||
|  |                                         href="#">{% trans "Delete Key"%}</a> | ||||||
|  |                                 </button> | ||||||
|  | 
 | ||||||
|  |     <div class="modal fade" id="Modal{{user_key.id }}" tabindex="-1" role="dialog"> | ||||||
|  |         <div class="modal-dialog" role="document"> | ||||||
|  |             <div class="modal-content"> | ||||||
|  |                 <div class="modal-header"> | ||||||
|  |                     <button type="button" class="close" data-dismiss="modal" | ||||||
|  |                             aria-label="Confirm"><span | ||||||
|  |                             aria-hidden="true">×</span> | ||||||
|  |                     </button> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="modal-body"> | ||||||
|  |                     <h4 class="modal-title" id="ModalLabel">{% trans "Do You want to delete this key?"%}</h4> | ||||||
|  | 
 | ||||||
|  |                     <form method="post" action="{% url 'hosting:delete_ssh_key' user_key.id %}"> | ||||||
|  |                         {% csrf_token %} | ||||||
|  |                         <div class="modal-footer"> | ||||||
|  |                             <button type="button" class="btn btn-default" | ||||||
|  |                                     data-dismiss="modal"> | ||||||
|  |                                 {% trans "Close"%} | ||||||
|  |                             </button> | ||||||
|  |                             <button type="submit" class="btn btn-primary">{% trans "Delete"%} | ||||||
|  |                             </button> | ||||||
|  |                         </div> | ||||||
|  |                     </form> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  |                                  </td> | ||||||
|  |                             </tr> | ||||||
|  |                             {% endfor %} | ||||||
|  |                                 </tbody>  | ||||||
|  |                             </table> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 						<div class="clearfix"></div> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 
 | ||||||
|  | 	    </div> | ||||||
|  | 	</div> | ||||||
|  |      | ||||||
|  | </div> | ||||||
|  | 
 | ||||||
|  | {% if next_url %} | ||||||
|  |     <script type="text/javascript">  | ||||||
|  |         window.location.href = '{{next_url}}'; | ||||||
|  |     </script> | ||||||
|  | {% endif %} | ||||||
|  | 
 | ||||||
|  | {%endblock%} | ||||||
|  | 
 | ||||||
|  | @ -2,4 +2,6 @@ from django.test import TestCase | ||||||
| 
 | 
 | ||||||
| # Create your tests here. | # Create your tests here. | ||||||
| 
 | 
 | ||||||
| test_user_can_add_key() | test_user_can_add_ssh_key() | ||||||
|  | 
 | ||||||
|  | test_user_can_delete_ssh_ke() | ||||||
|  |  | ||||||
|  | @ -3,9 +3,10 @@ from django.conf.urls import url | ||||||
| from .views import DjangoHostingView, RailsHostingView, PaymentVMView,\ | from .views import DjangoHostingView, RailsHostingView, PaymentVMView,\ | ||||||
|     NodeJSHostingView, LoginView, SignupView, IndexView, \ |     NodeJSHostingView, LoginView, SignupView, IndexView, \ | ||||||
|     OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\ |     OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\ | ||||||
|     VirtualMachineView, GenerateVMSSHKeysView, OrdersHostingDeleteView, NotificationsView, \ |     VirtualMachineView, OrdersHostingDeleteView, NotificationsView, \ | ||||||
|     MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView,\ |     MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView,\ | ||||||
|     CreateVirtualMachinesView, HostingBillListView, HostingBillDetailView |     CreateVirtualMachinesView, HostingBillListView, HostingBillDetailView, \ | ||||||
|  |     SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView | ||||||
| 
 | 
 | ||||||
| urlpatterns = [ | urlpatterns = [ | ||||||
|     url(r'index/?$', IndexView.as_view(), name='index'), |     url(r'index/?$', IndexView.as_view(), name='index'), | ||||||
|  | @ -23,10 +24,12 @@ urlpatterns = [ | ||||||
|     url(r'my-virtual-machines/?$', VirtualMachinesPlanListView.as_view(), name='virtual_machines'), |     url(r'my-virtual-machines/?$', VirtualMachinesPlanListView.as_view(), name='virtual_machines'), | ||||||
|     url(r'my-virtual-machines/(?P<pk>\d+)/?$', VirtualMachineView.as_view(), |     url(r'my-virtual-machines/(?P<pk>\d+)/?$', VirtualMachineView.as_view(), | ||||||
|         name='virtual_machines'), |         name='virtual_machines'), | ||||||
|     # url(r'my-virtual-machines/(?P<pk>\d+)/delete/?$', VirtualMachineCancelView.as_view(), |     url(r'ssh_keys/?$', SSHKeyListView.as_view(), | ||||||
|         # name='virtual_machines_cancel'), |         name='ssh_keys'), | ||||||
|     url(r'vm-key-pair/?$', GenerateVMSSHKeysView.as_view(), |     url(r'delete_ssh_key/(?P<pk>\d+)/?$', SSHKeyDeleteView.as_view(), | ||||||
|         name='key_pair'), |         name='delete_ssh_key'), | ||||||
|  |     url(r'create_ssh_key/?$', SSHKeyCreateView.as_view(), | ||||||
|  |         name='create_ssh_key'), | ||||||
|     url(r'^notifications/$', NotificationsView.as_view(), name='notifications'), |     url(r'^notifications/$', NotificationsView.as_view(), name='notifications'), | ||||||
|     url(r'^notifications/(?P<pk>\d+)/?$', MarkAsReadNotificationView.as_view(), |     url(r'^notifications/(?P<pk>\d+)/?$', MarkAsReadNotificationView.as_view(), | ||||||
|         name='read_notification'), |         name='read_notification'), | ||||||
|  |  | ||||||
|  | @ -188,7 +188,7 @@ class SignupView(CreateView): | ||||||
|     template_name = 'hosting/signup.html' |     template_name = 'hosting/signup.html' | ||||||
|     form_class = HostingUserSignupForm |     form_class = HostingUserSignupForm | ||||||
|     model = CustomUser |     model = CustomUser | ||||||
|     success_url = reverse_lazy('hosting:key_pair') |     success_url = reverse_lazy('hosting:ssh_keys') | ||||||
| 
 | 
 | ||||||
|     def get_success_url(self): |     def get_success_url(self): | ||||||
|         next_url = self.request.session.get( |         next_url = self.request.session.get( | ||||||
|  | @ -288,31 +288,58 @@ class MarkAsReadNotificationView(LoginRequiredMixin, UpdateView): | ||||||
|         return HttpResponseRedirect(reverse('hosting:notifications')) |         return HttpResponseRedirect(reverse('hosting:notifications')) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class GenerateVMSSHKeysView(LoginRequiredMixin, FormView): | class SSHKeyDeleteView(LoginRequiredMixin, DeleteView): | ||||||
|  |     login_url = reverse_lazy('hosting:login') | ||||||
|  |     success_url = reverse_lazy('hosting:ssh_keys') | ||||||
|  |     model = UserHostingKey | ||||||
|  | 
 | ||||||
|  |     def delete(self, request, *args, **kwargs): | ||||||
|  |         owner = self.request.user | ||||||
|  |         manager = OpenNebulaManager() | ||||||
|  |         pk = self.kwargs.get('pk') | ||||||
|  |         # Get user ssh key | ||||||
|  |         public_key = UserHostingKey.objects.get(pk=pk) | ||||||
|  |         # Add ssh key to user | ||||||
|  |         try: | ||||||
|  |             manager.remove_public_key(user=owner, public_key=public_key) | ||||||
|  |         except ConnectionError: | ||||||
|  |             pass | ||||||
|  |         except WrongNameError: | ||||||
|  |             pass | ||||||
|  | 
 | ||||||
|  |         return super(SSHKeyDeleteView, self).delete(request, *args, **kwargs) | ||||||
|  | 
 | ||||||
|  | class SSHKeyListView(LoginRequiredMixin, ListView): | ||||||
|  |     template_name = "hosting/user_keys.html" | ||||||
|  |     login_url = reverse_lazy('hosting:login') | ||||||
|  |     context_object_name = "keys" | ||||||
|  |     model = UserHostingKey | ||||||
|  |     paginate_by = 10 | ||||||
|  |     ordering = '-id' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def get_queryset(self): | ||||||
|  |         user = self.request.user | ||||||
|  |         self.queryset = UserHostingKey.objects.filter(user=user) | ||||||
|  |         return super(SSHKeyListView, self).get_queryset() | ||||||
|  | 
 | ||||||
|  |     def render_to_response(self, context, **response_kwargs): | ||||||
|  |         if not self.queryset: | ||||||
|  |             return HttpResponseRedirect(reverse('hosting:create_ssh_key')) | ||||||
|  |         return super(SSHKeyListView, self).render_to_response(context, **response_kwargs) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class SSHKeyCreateView(LoginRequiredMixin, FormView): | ||||||
|     form_class = UserHostingKeyForm |     form_class = UserHostingKeyForm | ||||||
|     model = UserHostingKey |     model = UserHostingKey | ||||||
|     template_name = 'hosting/virtual_machine_key.html' |     template_name = 'hosting/user_key.html' | ||||||
|     login_url = reverse_lazy('hosting:login') |     login_url = reverse_lazy('hosting:login') | ||||||
|     context_object_name = "virtual_machine" |     context_object_name = "virtual_machine" | ||||||
|  |     success_url = reverse_lazy('hosting:ssh_keys') | ||||||
| 
 | 
 | ||||||
|     def get_context_data(self, **kwargs): |  | ||||||
|         context = super( |  | ||||||
|             GenerateVMSSHKeysView, |  | ||||||
|             self |  | ||||||
|         ).get_context_data(**kwargs) |  | ||||||
| 
 |  | ||||||
|         user_keys = UserHostingKey.objects.filter( |  | ||||||
|             user=self.request.user |  | ||||||
|         ) |  | ||||||
| 
 |  | ||||||
|         context.update({ |  | ||||||
|             'keys': user_keys |  | ||||||
|         }) |  | ||||||
| 
 |  | ||||||
|         return context |  | ||||||
| 
 | 
 | ||||||
|     def get_form_kwargs(self): |     def get_form_kwargs(self): | ||||||
|         kwargs = super(GenerateVMSSHKeysView, self).get_form_kwargs() |         kwargs = super(SSHKeyCreateView, self).get_form_kwargs() | ||||||
|         kwargs.update({'request': self.request}) |         kwargs.update({'request': self.request}) | ||||||
|         return kwargs |         return kwargs | ||||||
| 
 | 
 | ||||||
|  | @ -339,22 +366,22 @@ class GenerateVMSSHKeysView(LoginRequiredMixin, FormView): | ||||||
|             }) |             }) | ||||||
| 
 | 
 | ||||||
|         owner = self.request.user |         owner = self.request.user | ||||||
|         # Create OpenNebulaManager |         manager = OpenNebulaManager() | ||||||
|         manager = OpenNebulaManager(email=owner.email, |  | ||||||
|                                     password=owner.password) |  | ||||||
|         # Get OpenNebula user id |  | ||||||
|         user_pool = manager._get_user_pool() |  | ||||||
|         opennebula_user = user_pool.get_by_name(owner.email) |  | ||||||
| 
 | 
 | ||||||
|         # Get user ssh key |         # Get user ssh key | ||||||
|         public_key = form.cleaned_data.get('public_key') |         public_key = form.cleaned_data.get('public_key') | ||||||
|         # Add ssh key to user |         # Add ssh key to user | ||||||
|         manager.oneadmin_client.call('user.update', opennebula_user.id, |         try: | ||||||
|                                      '<CONTEXT><SSH_PUBLIC_KEY>{key}</SSH_PUBLIC_KEY></CONTEXT>'.format(key=public_key)) |             manager.add_public_key(user=owner, public_key=public_key, merge=True) | ||||||
|  |         except ConnectionError: | ||||||
|  |             pass | ||||||
|  |         except WrongNameError: | ||||||
|  |             pass | ||||||
| 
 | 
 | ||||||
|         return render(self.request, self.template_name, context) |         return HttpResponseRedirect(self.success_url) | ||||||
| 
 | 
 | ||||||
|     def post(self, request, *args, **kwargs): |     def post(self, request, *args, **kwargs): | ||||||
|  |         print(self.request.POST.dict()) | ||||||
|         form = self.get_form() |         form = self.get_form() | ||||||
|         if form.is_valid(): |         if form.is_valid(): | ||||||
|             return self.form_valid(form) |             return self.form_valid(form) | ||||||
|  | @ -412,7 +439,7 @@ class PaymentVMView(LoginRequiredMixin, FormView): | ||||||
|                 request, |                 request, | ||||||
|                 'In order to create a VM, you create/upload your SSH KEY first.' |                 'In order to create a VM, you create/upload your SSH KEY first.' | ||||||
|             ) |             ) | ||||||
|             return HttpResponseRedirect(reverse('hosting:key_pair')) |             return HttpResponseRedirect(reverse('hosting:ssh_keys')) | ||||||
| 
 | 
 | ||||||
|         if 'next' in request.session: |         if 'next' in request.session: | ||||||
|             del request.session['next'] |             del request.session['next'] | ||||||
|  | @ -628,7 +655,7 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View): | ||||||
|                 request, |                 request, | ||||||
|                 'In order to create a VM, you need to create/upload your SSH KEY first.' |                 'In order to create a VM, you need to create/upload your SSH KEY first.' | ||||||
|             ) |             ) | ||||||
|             return HttpResponseRedirect(reverse('hosting:key_pair')) |             return HttpResponseRedirect(reverse('hosting:ssh_keys')) | ||||||
| 
 | 
 | ||||||
|         try: |         try: | ||||||
|             manager = OpenNebulaManager() |             manager = OpenNebulaManager() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue