Force user to generate ssh key in order to create a VM #3147. As user I want to terminate a VM using web interface #3148. Change password in opennebula when user change his password on hosting app #3149
This commit is contained in:
		
					parent
					
						
							
								1a6e1a44d8
							
						
					
				
			
			
				commit
				
					
						3873540849
					
				
			
		
					 7 changed files with 214 additions and 43 deletions
				
			
		|  | @ -101,7 +101,9 @@ class UserHostingKeyForm(forms.ModelForm): | ||||||
|         # print(self.fields) |         # print(self.fields) | ||||||
| 
 | 
 | ||||||
|     def clean_name(self): |     def clean_name(self): | ||||||
|         return ''.join(random.choice(string.ascii_lowercase) for i in range(7)) |         return "dcl-priv-key-%s" % ( | ||||||
|  |             ''.join(random.choice(string.ascii_lowercase) for i in range(7)) | ||||||
|  |         ) | ||||||
| 
 | 
 | ||||||
|     def clean_user(self): |     def clean_user(self): | ||||||
|         return self.request.user |         return self.request.user | ||||||
|  | @ -109,8 +111,6 @@ class UserHostingKeyForm(forms.ModelForm): | ||||||
|     def clean(self): |     def clean(self): | ||||||
|         cleaned_data = self.cleaned_data |         cleaned_data = self.cleaned_data | ||||||
| 
 | 
 | ||||||
|         print(cleaned_data) |  | ||||||
| 
 |  | ||||||
|         if not cleaned_data.get('public_key'): |         if not cleaned_data.get('public_key'): | ||||||
|             private_key, public_key = UserHostingKey.generate_keys() |             private_key, public_key = UserHostingKey.generate_keys() | ||||||
|             cleaned_data.update({ |             cleaned_data.update({ | ||||||
|  |  | ||||||
|  | @ -185,18 +185,31 @@ class VirtualMachinePlan(AssignPermissionsMixin, models.Model): | ||||||
|         instance.assign_permissions(user) |         instance.assign_permissions(user) | ||||||
|         return instance |         return instance | ||||||
| 
 | 
 | ||||||
|     def cancel_plan(self): |     def cancel_plan(self, vm_id): | ||||||
|         self.status = self.CANCELED_STATUS |         self.status = self.CANCELED_STATUS | ||||||
|         self.save(update_fields=['status']) |         self.save(update_fields=['status']) | ||||||
| 
 | 
 | ||||||
|  |     @classmethod | ||||||
|  |     def terminate_opennebula_vm(self, user, vm_id): | ||||||
|  | 
 | ||||||
|  |         opennebula_client = OpenNebulaManager( | ||||||
|  |             user.email, | ||||||
|  |             user.password, | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         return opennebula_client.terminate_vm(vm_id) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def create_opennebula_vm(self, user, specs): |     def create_opennebula_vm(self, user, specs): | ||||||
|  |         # import pdb | ||||||
|  |         # pdb.set_trace() | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
|         # Init opennebula manager using given user |         # Init opennebula manager using given user | ||||||
|         opennebula_client = OpenNebulaManager( |         opennebula_client = OpenNebulaManager( | ||||||
|             user.email, |             user.email, | ||||||
|             user.password[0:20], |             user.password, | ||||||
|             create_user=True |  | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         # Create a vm in opennebula using given specs |         # Create a vm in opennebula using given specs | ||||||
|  |  | ||||||
|  | @ -35,7 +35,7 @@ class OpenNebulaManager: | ||||||
|         '11': 'CLONING_FAILURE', |         '11': 'CLONING_FAILURE', | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     def __init__(self, email=None, password=None, create_user=True): |     def __init__(self, email=None, password=None): | ||||||
| 
 | 
 | ||||||
|         # Get oneadmin client |         # Get oneadmin client | ||||||
|         self.oneadmin_client = self._get_opennebula_client( |         self.oneadmin_client = self._get_opennebula_client( | ||||||
|  | @ -43,9 +43,6 @@ class OpenNebulaManager: | ||||||
|             settings.OPENNEBULA_PASSWORD |             settings.OPENNEBULA_PASSWORD | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         if not create_user: |  | ||||||
|             return |  | ||||||
| 
 |  | ||||||
|         # Get or create oppenebula user using given credentials |         # Get or create oppenebula user using given credentials | ||||||
|         self.opennebula_user = self._get_or_create_user( |         self.opennebula_user = self._get_or_create_user( | ||||||
|             email, |             email, | ||||||
|  | @ -121,9 +118,17 @@ class OpenNebulaManager: | ||||||
| 
 | 
 | ||||||
|         return vm_data |         return vm_data | ||||||
| 
 | 
 | ||||||
|  |     def change_user_password(self, new_password): | ||||||
|  |         self.oneadmin_client.call( | ||||||
|  |             oca.User.METHODS['passwd'], | ||||||
|  |             self.opennebula_user.id, | ||||||
|  |             new_password | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|     def create_vm(self, specs): |     def create_vm(self, specs): | ||||||
|         vm_id = None |         vm_id = None | ||||||
|         try: |         try: | ||||||
|  | 
 | ||||||
|             # We do have the vm_template param set. Get and parse it |             # We do have the vm_template param set. Get and parse it | ||||||
|             # and check it to be in the desired range. |             # and check it to be in the desired range. | ||||||
|             # We have 8 possible VM templates for the moment which are 1x, 2x, 4x ... |             # We have 8 possible VM templates for the moment which are 1x, 2x, 4x ... | ||||||
|  | @ -136,6 +141,9 @@ class OpenNebulaManager: | ||||||
|                                         <TYPE>{disk_type}</TYPE> |                                         <TYPE>{disk_type}</TYPE> | ||||||
|                                         <SIZE>{size}</SIZE> |                                         <SIZE>{size}</SIZE> | ||||||
|                                       </DISK> |                                       </DISK> | ||||||
|  |                                       <CONTEXT> | ||||||
|  |                                         <SSH_PUBLIC_KEY>{ssh_key}</SSH_PUBLIC_KEY> | ||||||
|  |                                       </CONTEXT> | ||||||
|                                     </VM> |                                     </VM> | ||||||
|                                     """ |                                     """ | ||||||
|             vm_id = oca.VirtualMachine.allocate( |             vm_id = oca.VirtualMachine.allocate( | ||||||
|  | @ -145,7 +153,8 @@ class OpenNebulaManager: | ||||||
|                     vcpu=specs.get('cores'), |                     vcpu=specs.get('cores'), | ||||||
|                     cpu=0.1 * specs.get('cores'), |                     cpu=0.1 * specs.get('cores'), | ||||||
|                     disk_type='fs', |                     disk_type='fs', | ||||||
|                     size=10000 * specs.get('disk_size') |                     size=10000 * specs.get('disk_size'), | ||||||
|  |                     ssh_key=specs.get('ssh_key') | ||||||
|                 ) |                 ) | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|  | @ -155,10 +164,6 @@ class OpenNebulaManager: | ||||||
|                 self.opennebula_user.id, |                 self.opennebula_user.id, | ||||||
|                 self.opennebula_user.group_ids[0] |                 self.opennebula_user.group_ids[0] | ||||||
|             ) |             ) | ||||||
|             # oca.VirtualMachine.chown( |  | ||||||
|             #     vm_id, |  | ||||||
|                 |  | ||||||
|             # ) |  | ||||||
| 
 | 
 | ||||||
|         except socket.timeout as socket_err: |         except socket.timeout as socket_err: | ||||||
|             logger.error("Socket timeout error: {0}".format(socket_err)) |             logger.error("Socket timeout error: {0}".format(socket_err)) | ||||||
|  | @ -171,6 +176,29 @@ class OpenNebulaManager: | ||||||
| 
 | 
 | ||||||
|         return vm_id |         return vm_id | ||||||
| 
 | 
 | ||||||
|  |     def terminate_vm(self, vm_id): | ||||||
|  | 
 | ||||||
|  |         TERMINATE_ACTION = 'terminate' | ||||||
|  |         vm_terminated = False | ||||||
|  | 
 | ||||||
|  |         try: | ||||||
|  |             self.oneadmin_client.call( | ||||||
|  |                 oca.VirtualMachine.METHODS['action'], | ||||||
|  |                 TERMINATE_ACTION, | ||||||
|  |                 int(vm_id), | ||||||
|  |             ) | ||||||
|  |             vm_terminated = True | ||||||
|  |         except socket.timeout as socket_err: | ||||||
|  |             logger.error("Socket timeout error: {0}".format(socket_err)) | ||||||
|  |         except OpenNebulaException as opennebula_err: | ||||||
|  |             logger.error("OpenNebulaException error: {0}".format(opennebula_err)) | ||||||
|  |         except OSError as os_err: | ||||||
|  |             logger.error("OSError : {0}".format(os_err)) | ||||||
|  |         except ValueError as value_err: | ||||||
|  |             logger.error("ValueError : {0}".format(value_err)) | ||||||
|  | 
 | ||||||
|  |         return vm_terminated | ||||||
|  | 
 | ||||||
|     def get_vm_templates(self): |     def get_vm_templates(self): | ||||||
|         template_pool = oca.VmTemplatePool(self.oneadmin_client) |         template_pool = oca.VmTemplatePool(self.oneadmin_client) | ||||||
|         template_pool.info() |         template_pool.info() | ||||||
|  |  | ||||||
|  | @ -170,16 +170,28 @@ | ||||||
| 											{% csrf_token %}  | 											{% csrf_token %}  | ||||||
| 											</form>	 | 											</form>	 | ||||||
| 												 | 												 | ||||||
| 												<button type="text" data-href="{% url 'hosting:virtual_machines' virtual_machine.id %}" data-toggle="modal" data-target="#confirm-cancel" class="btn btn-danger">{% trans "Cancel Virtual Machine"%}</button> | 												<button type="text" data-href="{% url 'hosting:virtual_machines' virtual_machine.id %}" data-toggle="modal" data-target="#confirm-cancel" class="btn btn-danger">{% trans "Terminate Virtual Machine"%}</button> | ||||||
| 																						 | 																						 | ||||||
| 										</div> | 										</div> | ||||||
|  |      | ||||||
| 									</div> | 									</div> | ||||||
|  |                                     <div class="col-md-12"> | ||||||
|  |                                         <br/> | ||||||
|  |                                         {% if messages %} | ||||||
|  |                                             <div class="alert alert-warning"> | ||||||
|  |                                                 {% for message in messages %} | ||||||
|  |                                                 <span>{{ message }}</span> | ||||||
|  |                                                 {% endfor %} | ||||||
|  |                                             </div> | ||||||
|  |                                         {% endif %} | ||||||
|  |                                     </div> | ||||||
|  | 
 | ||||||
| 									<!-- Cancel Modal --> | 									<!-- Cancel Modal --> | ||||||
| 									<div class="modal fade" id="confirm-cancel" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> | 									<div class="modal fade" id="confirm-cancel" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> | ||||||
| 									    <div class="modal-dialog"> | 									    <div class="modal-dialog"> | ||||||
| 									        <div class="modal-content"> | 									        <div class="modal-content"> | ||||||
| 									            <div class="modal-header"> | 									            <div class="modal-header"> | ||||||
| 									                {% trans "Cancel your Virtual Machine"%} | 									                {% trans "Terminate your Virtual Machine"%} | ||||||
| 									            </div> | 									            </div> | ||||||
| 									            <div class="modal-body"> | 									            <div class="modal-body"> | ||||||
| 									                {% trans "Are you sure do you want to cancel your Virtual Machine "%} {{vm.virtual_machine}}  {% trans "plan?"%} | 									                {% trans "Are you sure do you want to cancel your Virtual Machine "%} {{vm.virtual_machine}}  {% trans "plan?"%} | ||||||
|  |  | ||||||
|  | @ -9,11 +9,18 @@ | ||||||
|                     <form method="POST" action="" > |                     <form method="POST" action="" > | ||||||
|                         {% csrf_token %} |                         {% csrf_token %} | ||||||
| 				        <h3><i class="fa fa-key" aria-hidden="true"></i>{% trans "Access Key"%} </h3> | 				        <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 %} | ||||||
| 				        <hr/>	 | 				        <hr/>	 | ||||||
|                         {% if not user_key %} |                         {% if not user_key %} | ||||||
|                             <div class="alert alert-warning"> |                             <h3> | ||||||
|                                 {% trans "Upload your own key. "%}  |                                 {% trans "Upload your own key. "%}  | ||||||
|                             </div> |                             </h3> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                               <label for="comment">Paste here your public key</label> |                               <label for="comment">Paste here your public key</label> | ||||||
|                               <textarea class="form-control" rows="6" name="public_key"></textarea> |                               <textarea class="form-control" rows="6" name="public_key"></textarea> | ||||||
|  | @ -22,10 +29,10 @@ | ||||||
|                                 <button class="btn btn-success">{% trans "Upload Key"%} </a> |                                 <button class="btn btn-success">{% trans "Upload Key"%} </a> | ||||||
|                             </div> |                             </div> | ||||||
|                          |                          | ||||||
|                             <div class="alert alert-warning"> |                             <h3> | ||||||
|                                 {% trans "Or generate a new key pair."%}  |                                 {% trans "Or generate a new key pair."%}  | ||||||
| 
 | 
 | ||||||
|                             </div> |                             </h3> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <button class="btn btn-success">{% trans "Generate Key Pair"%} </a> |                                 <button class="btn btn-success">{% trans "Generate Key Pair"%} </a> | ||||||
|                             </div> |                             </div> | ||||||
|  | @ -58,7 +65,7 @@ | ||||||
| 				        {% if private_key %} | 				        {% if private_key %} | ||||||
| 				 		<div class="alert alert-warning"> | 				 		<div class="alert alert-warning"> | ||||||
| 				 			  | 				 			  | ||||||
|   							<strong>{% trans "Warning!"%}</strong>{% trans "You can view your SSH  private key once. Don't lost your key"%}   |   							<strong>{% trans "Warning!"%}</strong>{% trans "You can download your SSH  private key once. Don't lost your key"%}   | ||||||
| 						</div> | 						</div> | ||||||
| 						<div class="form-group"> | 						<div class="form-group"> | ||||||
| 						  <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> | ||||||
|  |  | ||||||
|  | @ -11,6 +11,16 @@ | ||||||
|                     <a class="btn btn-success" href="{% url 'hosting:create-virtual-machine' %}" >{% trans "Create VM"%} </a>                     |                     <a class="btn btn-success" href="{% url 'hosting:create-virtual-machine' %}" >{% trans "Create VM"%} </a>                     | ||||||
|                 </p> |                 </p> | ||||||
| 				<br/> | 				<br/> | ||||||
|  |                 <div class="col-md-12"> | ||||||
|  |                     <br/> | ||||||
|  |                     {% if messages %} | ||||||
|  |                         <div class="alert alert-warning"> | ||||||
|  |                             {% for message in messages %} | ||||||
|  |                             <span>{{ message }}</span> | ||||||
|  |                             {% endfor %} | ||||||
|  |                         </div> | ||||||
|  |                     {% endif %} | ||||||
|  |                 </div> | ||||||
| 				<thead>  | 				<thead>  | ||||||
| 				<tr>  | 				<tr>  | ||||||
| 					<th>{% trans "ID"%}</th> | 					<th>{% trans "ID"%}</th> | ||||||
|  |  | ||||||
							
								
								
									
										141
									
								
								hosting/views.py
									
										
									
									
									
								
							
							
						
						
									
										141
									
								
								hosting/views.py
									
										
									
									
									
								
							|  | @ -11,7 +11,8 @@ from django.contrib.auth import authenticate, login | ||||||
| from django.contrib import messages | from django.contrib import messages | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.shortcuts import redirect | from django.shortcuts import redirect | ||||||
| 
 | from django.utils.http import urlsafe_base64_decode | ||||||
|  | from django.contrib.auth.tokens import default_token_generator | ||||||
| 
 | 
 | ||||||
| from guardian.mixins import PermissionRequiredMixin | from guardian.mixins import PermissionRequiredMixin | ||||||
| from stored_messages.settings import stored_messages_settings | from stored_messages.settings import stored_messages_settings | ||||||
|  | @ -186,6 +187,43 @@ class PasswordResetConfirmView(PasswordResetConfirmViewMixin): | ||||||
|     template_name = 'hosting/confirm_reset_password.html' |     template_name = 'hosting/confirm_reset_password.html' | ||||||
|     success_url = reverse_lazy('hosting:login') |     success_url = reverse_lazy('hosting:login') | ||||||
| 
 | 
 | ||||||
|  |     def post(self, request, uidb64=None, token=None, *arg, **kwargs): | ||||||
|  |         try: | ||||||
|  |             uid = urlsafe_base64_decode(uidb64) | ||||||
|  |             user = CustomUser.objects.get(pk=uid) | ||||||
|  | 
 | ||||||
|  |             opennebula_client = OpenNebulaManager( | ||||||
|  |                 email=user.email, | ||||||
|  |                 password=user.password, | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  |         except (TypeError, ValueError, OverflowError, CustomUser.DoesNotExist): | ||||||
|  |             user = None | ||||||
|  |             opennebula_client = None | ||||||
|  | 
 | ||||||
|  |         form = self.form_class(request.POST) | ||||||
|  | 
 | ||||||
|  |         if user is not None and default_token_generator.check_token(user, token): | ||||||
|  |             if form.is_valid(): | ||||||
|  |                 new_password = form.cleaned_data['new_password2'] | ||||||
|  |                 user.set_password(new_password) | ||||||
|  |                 user.save() | ||||||
|  |                 messages.success(request, 'Password has been reset.') | ||||||
|  | 
 | ||||||
|  |                 # Change opennebula password | ||||||
|  |                 opennebula_client.change_user_password(new_password) | ||||||
|  | 
 | ||||||
|  |                 return self.form_valid(form) | ||||||
|  |             else: | ||||||
|  |                 messages.error(request, 'Password reset has not been successful.') | ||||||
|  |                 form.add_error(None, 'Password reset has not been successful.') | ||||||
|  |                 return self.form_invalid(form) | ||||||
|  | 
 | ||||||
|  |         else: | ||||||
|  |             messages.error(request, 'The reset password link is no longer valid.') | ||||||
|  |             form.add_error(None, 'The reset password link is no longer valid.') | ||||||
|  |             return self.form_invalid(form) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class NotificationsView(LoginRequiredMixin, TemplateView): | class NotificationsView(LoginRequiredMixin, TemplateView): | ||||||
|     template_name = 'hosting/notifications.html' |     template_name = 'hosting/notifications.html' | ||||||
|  | @ -261,14 +299,6 @@ class GenerateVMSSHKeysView(LoginRequiredMixin, FormView): | ||||||
|                 'form': UserHostingKeyForm(request=self.request) |                 'form': UserHostingKeyForm(request=self.request) | ||||||
|             }) |             }) | ||||||
| 
 | 
 | ||||||
|         del(context['form']) |  | ||||||
|         context.update({ |  | ||||||
|             'form': form |  | ||||||
|         }) |  | ||||||
|         form = UserHostingKeyForm(request=self.request) |  | ||||||
| 
 |  | ||||||
|         print("context", context) |  | ||||||
| 
 |  | ||||||
|         # return HttpResponseRedirect(reverse('hosting:key_pair')) |         # return HttpResponseRedirect(reverse('hosting:key_pair')) | ||||||
|         return render(self.request, self.template_name, context) |         return render(self.request, self.template_name, context) | ||||||
| 
 | 
 | ||||||
|  | @ -332,6 +362,21 @@ class PaymentVMView(LoginRequiredMixin, FormView): | ||||||
| 
 | 
 | ||||||
|         return context |         return context | ||||||
| 
 | 
 | ||||||
|  |     def get(self, request, *args, **kwargs): | ||||||
|  | 
 | ||||||
|  |         try: | ||||||
|  |             UserHostingKey.objects.get( | ||||||
|  |                 user=self.request.user | ||||||
|  |             ) | ||||||
|  |         except UserHostingKey.DoesNotExist: | ||||||
|  |             messages.success( | ||||||
|  |                 request, | ||||||
|  |                 'In order to create a VM, you create/upload your SSH KEY first.' | ||||||
|  |             ) | ||||||
|  |             return HttpResponseRedirect(reverse('hosting:key_pair')) | ||||||
|  | 
 | ||||||
|  |         return self.render_to_response(self.get_context_data()) | ||||||
|  | 
 | ||||||
|     def post(self, request, *args, **kwargs): |     def post(self, request, *args, **kwargs): | ||||||
|         form = self.get_form() |         form = self.get_form() | ||||||
| 
 | 
 | ||||||
|  | @ -415,13 +460,27 @@ class PaymentVMView(LoginRequiredMixin, FormView): | ||||||
|             # If the Stripe payment was successed, set order status approved |             # If the Stripe payment was successed, set order status approved | ||||||
|             order.set_approved() |             order.set_approved() | ||||||
| 
 | 
 | ||||||
|  |             # Get user ssh key | ||||||
|  |             try: | ||||||
|  |                 user_key = UserHostingKey.objects.get( | ||||||
|  |                     user=self.request.user | ||||||
|  |                 ) | ||||||
|  | 
 | ||||||
|  |                 # Add ssh_key to specs | ||||||
|  |                 specs.update({ | ||||||
|  |                     'ssh_key': user_key.public_key | ||||||
|  |                 }) | ||||||
|  | 
 | ||||||
|  |             except UserHostingKey.DoesNotExist: | ||||||
|  |                 pass | ||||||
|  | 
 | ||||||
|             # Create a vm using logged user |             # Create a vm using logged user | ||||||
|             oppennebula_vm_id = VirtualMachinePlan.create_opennebula_vm( |             opennebula_vm_id = VirtualMachinePlan.create_opennebula_vm( | ||||||
|                 self.request.user, |                 self.request.user, | ||||||
|                 specs |                 specs | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|             plan.oppenebula_id = oppennebula_vm_id |             plan.opennebula_id = opennebula_vm_id | ||||||
|             plan.save() |             plan.save() | ||||||
| 
 | 
 | ||||||
|             # Send notification to ungleich as soon as VM has been booked |             # Send notification to ungleich as soon as VM has been booked | ||||||
|  | @ -503,6 +562,18 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View): | ||||||
|     login_url = reverse_lazy('hosting:login') |     login_url = reverse_lazy('hosting:login') | ||||||
| 
 | 
 | ||||||
|     def get(self, request, *args, **kwargs): |     def get(self, request, *args, **kwargs): | ||||||
|  | 
 | ||||||
|  |         try: | ||||||
|  |             UserHostingKey.objects.get( | ||||||
|  |                 user=self.request.user | ||||||
|  |             ) | ||||||
|  |         except UserHostingKey.DoesNotExist: | ||||||
|  |             messages.success( | ||||||
|  |                 request, | ||||||
|  |                 'In order to create a VM, you need to create/upload your SSH KEY first.' | ||||||
|  |             ) | ||||||
|  |             return HttpResponseRedirect(reverse('hosting:key_pair')) | ||||||
|  | 
 | ||||||
|         context = { |         context = { | ||||||
|             'vm_types': VirtualMachineType.get_serialized_vm_types(), |             'vm_types': VirtualMachineType.get_serialized_vm_types(), | ||||||
|             'configuration_options': VirtualMachinePlan.VM_CONFIGURATION |             'configuration_options': VirtualMachinePlan.VM_CONFIGURATION | ||||||
|  | @ -565,18 +636,26 @@ class VirtualMachineView(PermissionRequiredMixin, LoginRequiredMixin, View): | ||||||
|     #     except Exception as error: |     #     except Exception as error: | ||||||
|     #         raise Http404() |     #         raise Http404() | ||||||
| 
 | 
 | ||||||
|     # def get_success_url(self): |     def get_object(self): | ||||||
|     #     vm = self.get_object() |         opennebula_vm_id = self.kwargs.get('pk') | ||||||
|     #     final_url = "%s%s" % (reverse('hosting:virtual_machines', kwargs={'pk': vm.id}), |         opennebula_vm = None | ||||||
|     #                           '#status-v') |         try: | ||||||
|     #     return final_url |             opennebula_vm = VirtualMachinePlan.objects.get(opennebula_id=opennebula_vm_id) | ||||||
|  |         except Exception as error: | ||||||
|  |             print(error) | ||||||
|  |             raise Http404() | ||||||
|  |         return opennebula_vm | ||||||
|  | 
 | ||||||
|  |     def get_success_url(self): | ||||||
|  |         final_url = reverse('hosting:virtual_machines') | ||||||
|  |         return final_url | ||||||
| 
 | 
 | ||||||
|     def get(self, request, *args, **kwargs): |     def get(self, request, *args, **kwargs): | ||||||
|         vm_id = self.kwargs.get('pk') |         opennebula_vm_id = self.kwargs.get('pk') | ||||||
|         try: |         try: | ||||||
|             opennebula_vm = VirtualMachinePlan.get_vm( |             opennebula_vm = VirtualMachinePlan.get_vm( | ||||||
|                 self.request.user, |                 self.request.user, | ||||||
|                 vm_id |                 opennebula_vm_id | ||||||
|             ) |             ) | ||||||
|         except Exception as error: |         except Exception as error: | ||||||
|             print(error) |             print(error) | ||||||
|  | @ -588,9 +667,24 @@ class VirtualMachineView(PermissionRequiredMixin, LoginRequiredMixin, View): | ||||||
|         # context = {} |         # context = {} | ||||||
|         return render(request, self.template_name, context) |         return render(request, self.template_name, context) | ||||||
| 
 | 
 | ||||||
|     def post(self, *args, **kwargs): |     def post(self, request, *args, **kwargs): | ||||||
|         vm = self.get_object() |         vm = self.get_object() | ||||||
|         vm.cancel_plan() | 
 | ||||||
|  |         opennebula_vm_id = self.kwargs.get('pk') | ||||||
|  | 
 | ||||||
|  |         terminated = VirtualMachinePlan.terminate_opennebula_vm( | ||||||
|  |             self.request.user, | ||||||
|  |             opennebula_vm_id | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         if not terminated: | ||||||
|  |             messages.error( | ||||||
|  |                 request, | ||||||
|  |                 'Error terminating VM %s' % (opennebula_vm_id) | ||||||
|  |             ) | ||||||
|  |             return HttpResponseRedirect(self.get_success_url()) | ||||||
|  | 
 | ||||||
|  |         #vm.cancel_plan() | ||||||
| 
 | 
 | ||||||
|         context = { |         context = { | ||||||
|             'vm': vm, |             'vm': vm, | ||||||
|  | @ -606,8 +700,14 @@ class VirtualMachineView(PermissionRequiredMixin, LoginRequiredMixin, View): | ||||||
|         email = BaseEmail(**email_data) |         email = BaseEmail(**email_data) | ||||||
|         email.send() |         email.send() | ||||||
| 
 | 
 | ||||||
|  |         messages.error( | ||||||
|  |             request, | ||||||
|  |             'VM %s terminated successfully' % (opennebula_vm_id) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|         return HttpResponseRedirect(self.get_success_url()) |         return HttpResponseRedirect(self.get_success_url()) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class HostingBillListView(LoginRequiredMixin, ListView): | class HostingBillListView(LoginRequiredMixin, ListView): | ||||||
|     template_name = "hosting/bills.html" |     template_name = "hosting/bills.html" | ||||||
|     login_url = reverse_lazy('hosting:login') |     login_url = reverse_lazy('hosting:login') | ||||||
|  | @ -616,6 +716,7 @@ class HostingBillListView(LoginRequiredMixin, ListView): | ||||||
|     paginate_by = 10 |     paginate_by = 10 | ||||||
|     ordering = '-id' |     ordering = '-id' | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class HostingBillDetailView(PermissionRequiredMixin, LoginRequiredMixin, DetailView): | class HostingBillDetailView(PermissionRequiredMixin, LoginRequiredMixin, DetailView): | ||||||
|     template_name = "hosting/bill_detail.html" |     template_name = "hosting/bill_detail.html" | ||||||
|     login_url = reverse_lazy('hosting:login') |     login_url = reverse_lazy('hosting:login') | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue