Commit 126c44bc by Bach Dániel

Merge branch 'featura-mount-store-op'

Conflicts:
	circle/dashboard/templates/dashboard/vm-detail/home.html
parents d88a749d 3f86ff11
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
$(function() { $(function() {
/* vm operations */ /* vm operations */
$('#ops, #vm-details-resources-disk, #vm-details-renew-op, #vm-details-pw-reset, #vm-details-add-interface').on('click', '.operation', function(e) { $('#ops, #vm-details-resources-disk, #vm-details-renew-op, #vm-details-pw-reset, #vm-details-add-interface, .operation-wrapper').on('click', '.operation', function(e) {
var icon = $(this).children("i").addClass('fa-spinner fa-spin'); var icon = $(this).children("i").addClass('fa-spinner fa-spin');
$.ajax({ $.ajax({
......
...@@ -100,6 +100,20 @@ ...@@ -100,6 +100,20 @@
{% endif %} {% endif %}
</dd> </dd>
</dl> </dl>
{% if op.mount_store %}
<strong>{% trans "Store" %}</strong>
<p>
{{ op.mount_store.description }}
</p>
<div class="operation-wrapper">
<a href="{{ op.mount_store.get_url }}" class="btn btn-info btn-xs operation"
{% if op.mount_store.disabled %}disabled{% endif %}>
<i class="fa fa-{{op.mount_store.icon}}"></i>
{{ op.mount_store.name }}
</a>
</div>
{% endif %}
</div> </div>
<div class="col-md-8"> <div class="col-md-8">
{% if graphite_enabled %} {% if graphite_enabled %}
......
...@@ -966,6 +966,10 @@ vm_ops = OrderedDict([ ...@@ -966,6 +966,10 @@ vm_ops = OrderedDict([
('password_reset', VmOperationView.factory( ('password_reset', VmOperationView.factory(
op='password_reset', icon='unlock', effect='warning', op='password_reset', icon='unlock', effect='warning',
show_in_toolbar=False, wait_for_result=0.5, with_reload=True)), show_in_toolbar=False, wait_for_result=0.5, with_reload=True)),
('mount_store', VmOperationView.factory(
op='mount_store', icon='briefcase', effect='info',
show_in_toolbar=False,
)),
]) ])
......
...@@ -293,6 +293,10 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin, ...@@ -293,6 +293,10 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
message = ugettext_noop( message = ugettext_noop(
"Instance %(instance)s has already been destroyed.") "Instance %(instance)s has already been destroyed.")
class NoAgentError(InstanceError):
message = ugettext_noop(
"No agent software is running on instance %(instance)s.")
class WrongStateError(InstanceError): class WrongStateError(InstanceError):
message = ugettext_noop( message = ugettext_noop(
"Current state (%(state)s) of instance %(instance)s is " "Current state (%(state)s) of instance %(instance)s is "
......
...@@ -19,10 +19,12 @@ from __future__ import absolute_import, unicode_literals ...@@ -19,10 +19,12 @@ from __future__ import absolute_import, unicode_literals
from logging import getLogger from logging import getLogger
from re import search from re import search
from string import ascii_lowercase from string import ascii_lowercase
from urlparse import urlsplit
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _, ugettext_noop from django.utils.translation import ugettext_lazy as _, ugettext_noop
from django.conf import settings
from sizefield.utils import filesizeformat from sizefield.utils import filesizeformat
...@@ -41,6 +43,8 @@ from .models import ( ...@@ -41,6 +43,8 @@ from .models import (
) )
from .tasks import agent_tasks from .tasks import agent_tasks
from dashboard.store_api import Store, NoStoreException
logger = getLogger(__name__) logger = getLogger(__name__)
...@@ -934,8 +938,27 @@ class ResourcesOperation(InstanceOperation): ...@@ -934,8 +938,27 @@ class ResourcesOperation(InstanceOperation):
register_operation(ResourcesOperation) register_operation(ResourcesOperation)
class PasswordResetOperation(InstanceOperation): class EnsureAgentMixin(object):
activity_code_suffix = 'Password reset' accept_states = ('RUNNING', )
def check_precond(self):
super(EnsureAgentMixin, self).check_precond()
last_boot_time = self.instance.activity_log.filter(
succeeded=True, activity_code__in=(
"vm.Instance.deploy", "vm.Instance.reset",
"vm.Instance.reboot")).latest("finished").finished
try:
InstanceActivity.objects.filter(
activity_code="vm.Instance.agent.starting",
started__gt=last_boot_time).latest("started")
except InstanceActivity.DoesNotExist: # no agent since last boot
raise self.instance.NoAgentError(self.instance)
class PasswordResetOperation(EnsureAgentMixin, InstanceOperation):
activity_code_suffix = 'password_reset'
id = 'password_reset' id = 'password_reset'
name = _("password reset") name = _("password reset")
description = _("Generate and set a new login password on the virtual " description = _("Generate and set a new login password on the virtual "
...@@ -945,7 +968,6 @@ class PasswordResetOperation(InstanceOperation): ...@@ -945,7 +968,6 @@ class PasswordResetOperation(InstanceOperation):
"it.") "it.")
acl_level = "owner" acl_level = "owner"
required_perms = () required_perms = ()
accept_states = ('RUNNING', )
def _operation(self): def _operation(self):
self.instance.pw = pwgen() self.instance.pw = pwgen()
...@@ -956,3 +978,34 @@ class PasswordResetOperation(InstanceOperation): ...@@ -956,3 +978,34 @@ class PasswordResetOperation(InstanceOperation):
register_operation(PasswordResetOperation) register_operation(PasswordResetOperation)
class MountStoreOperation(EnsureAgentMixin, InstanceOperation):
activity_code_suffix = 'mount_store'
id = 'mount_store'
name = _("mount store")
description = _(
"This operation attaches your personal file store. Other users who "
"have access to this machine can see these files as well."
)
acl_level = "owner"
required_perms = ()
def check_auth(self, user):
super(MountStoreOperation, self).check_auth(user)
try:
Store(user)
except NoStoreException:
raise PermissionDenied # not show the button at all
def _operation(self):
inst = self.instance
queue = self.instance.get_remote_queue_name("agent")
host = urlsplit(settings.STORE_URL).hostname
username = Store(inst.owner).username
password = inst.owner.profile.smb_password
agent_tasks.mount_store.apply_async(
queue=queue, args=(inst.vm_name, host, username, password))
register_operation(MountStoreOperation)
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