Commit f9f4c6a3 by Bach Dániel

Merge branch 'feature-pass-reset-op-merged'

Conflicts:
	circle/dashboard/views.py
parents eaea5499 83f9b7ce
......@@ -98,17 +98,12 @@
</div>
</dd>
<dd style="font-size: 10px; text-align: right; padding-top: 8px;">
<a id="vm-details-pw-change" href="#">{% trans "Generate new password!" %}</a>
<div id="vm-details-pw-reset">
{% with op=op.password_reset %}{% if op %}
<a href="{{op.get_url}}" class="btn operation btn-default btn-xs" {% if op.disabled %}disabled{% endif %}>{% trans "Generate new password!" %}</a>
{% endif %}{% endwith %}
</div>
</dd>
<div id="vm-details-pw-confirm"> {% comment %} TODO Couldn't this use a modal? {% endcomment%}
<dt>
{% trans "Are you sure?" %}
</dt>
<dd>
<a href="#" class="vm-details-pw-confirm-choice label label-success" data-choice="1" data-vm="{{ instance.pk }}">{% trans "Yes" %}</a> /
<a href="#" class="vm-details-pw-confirm-choice label label-danger" data-choice="0">{% trans "No" %}</a>
</dd>
</div>
</dl>
<div class="input-group" id="dashboard-vm-details-connect-command">
......
......@@ -143,26 +143,13 @@ class VmDetailTest(LoginMixin, TestCase):
response = c.post('/dashboard/vm/mass-delete/', {'vms': [1]})
self.assertEqual(response.status_code, 302)
def test_permitted_password_change(self):
c = Client()
self.login(c, "user2")
inst = Instance.objects.get(pk=1)
inst.set_level(self.u2, 'owner')
inst.node = Node.objects.all()[0]
inst.save()
password = inst.pw
response = c.post("/dashboard/vm/1/", {'change_password': True})
self.assertTrue(Instance.get_remote_queue_name.called)
self.assertEqual(response.status_code, 302)
self.assertNotEqual(password, Instance.objects.get(pk=1).pw)
def test_unpermitted_password_change(self):
c = Client()
self.login(c, "user2")
inst = Instance.objects.get(pk=1)
inst.set_level(self.u1, 'owner')
password = inst.pw
response = c.post("/dashboard/vm/1/", {'change_password': True})
response = c.post("/dashboard/vm/1/op/password_reset/")
self.assertEqual(response.status_code, 403)
self.assertEqual(password, Instance.objects.get(pk=1).pw)
......
......@@ -306,7 +306,6 @@ class VmDetailView(CheckedDetailView):
def post(self, request, *args, **kwargs):
options = {
'change_password': self.__change_password,
'new_name': self.__set_name,
'new_description': self.__set_description,
'new_tag': self.__add_tag,
......@@ -321,19 +320,6 @@ class VmDetailView(CheckedDetailView):
raise Http404()
def __change_password(self, request):
self.object = self.get_object()
if not self.object.has_level(request.user, 'owner'):
raise PermissionDenied()
self.object.change_password(user=request.user)
messages.success(request, _("Password changed."))
if request.is_ajax():
return HttpResponse("Success.")
else:
return redirect(reverse_lazy("dashboard.views.detail",
kwargs={'pk': self.object.pk}))
def __set_name(self, request):
self.object = self.get_object()
if not self.object.has_level(request.user, 'owner'):
......@@ -627,6 +613,7 @@ class AjaxOperationMixin(object):
store.used = True
return HttpResponse(
json.dumps({'success': True,
'with_reload': getattr(self, 'with_reload', False),
'messages': [unicode(m) for m in store]}),
content_type="application=json"
)
......@@ -909,6 +896,9 @@ vm_ops = OrderedDict([
('add_interface', VmAddInterfaceView),
('renew', VmRenewView),
('resources_change', VmResourcesChangeView),
('password_reset', VmOperationView.factory(
op='password_reset', icon='unlock', effect='warning',
show_in_toolbar=False, wait_for_result=0.5, with_reload=True)),
])
......
......@@ -13,6 +13,7 @@ from .instance import InstanceTemplate
from .instance import Instance
from .instance import post_state_changed
from .instance import pre_state_changed
from .instance import pwgen
from .network import InterfaceTemplate
from .network import Interface
from .node import Node
......@@ -22,5 +23,5 @@ __all__ = [
'NamedBaseResourceConfig', 'VirtualMachineDescModel', 'InstanceTemplate',
'Instance', 'instance_activity', 'post_state_changed', 'pre_state_changed',
'InterfaceTemplate', 'Interface', 'Trait', 'Node', 'NodeActivity', 'Lease',
'node_activity',
'node_activity', 'pwgen'
]
......@@ -731,24 +731,6 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
timezone.now() + lease.suspend_interval,
timezone.now() + lease.delete_interval)
def change_password(self, user=None):
"""Generate new password for the vm
:param self: The virtual machine.
:param user: The user who's issuing the command.
"""
self.pw = pwgen()
with instance_activity(code_suffix='change_password', instance=self,
readable_name=ugettext_noop("change password"),
user=user):
queue = self.get_remote_queue_name("agent")
agent_tasks.change_password.apply_async(queue=queue,
args=(self.vm_name,
self.pw))
self.save()
def select_node(self):
"""Returns the node the VM should be deployed or migrated to.
"""
......
......@@ -33,8 +33,9 @@ from .tasks.local_tasks import (
)
from .models import (
Instance, InstanceActivity, InstanceTemplate, Interface, Node,
NodeActivity,
NodeActivity, pwgen
)
from .tasks import agent_tasks
logger = getLogger(__name__)
......@@ -879,3 +880,27 @@ class ResourcesOperation(InstanceOperation):
register_operation(ResourcesOperation)
class PasswordResetOperation(InstanceOperation):
activity_code_suffix = 'Password reset'
id = 'password_reset'
name = _("password reset")
description = _("Password reset")
acl_level = "owner"
required_perms = ()
def check_precond(self):
super(PasswordResetOperation, self).check_precond()
if self.instance.status not in ["RUNNING"]:
raise self.instance.WrongStateError(self.instance)
def _operation(self):
self.instance.pw = pwgen()
queue = self.instance.get_remote_queue_name("agent")
agent_tasks.change_password.apply_async(
queue=queue, args=(self.instance.vm_name, self.instance.pw))
self.instance.save()
register_operation(PasswordResetOperation)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment