...
 
Commits (11)
...@@ -162,7 +162,7 @@ class ConnectCommand(Model): ...@@ -162,7 +162,7 @@ class ConnectCommand(Model):
validators=[connect_command_template_validator]) validators=[connect_command_template_validator])
class Meta: class Meta:
ordering = ('id', ) ordering = ('id',)
def __unicode__(self): def __unicode__(self):
return self.template return self.template
...@@ -218,7 +218,7 @@ class Profile(Model): ...@@ -218,7 +218,7 @@ class Profile(Model):
'id': command.id, 'id': command.id,
'cmd': command.template % { 'cmd': command.template % {
'port': instance.get_connect_port(use_ipv6=use_ipv6), 'port': instance.get_connect_port(use_ipv6=use_ipv6),
'host': instance.get_connect_host(use_ipv6=use_ipv6), 'host': instance.get_connect_host(use_ipv6=use_ipv6),
'password': instance.pw, 'password': instance.pw,
'username': 'cloud', 'username': 'cloud',
}} for command in commands] }} for command in commands]
...@@ -263,7 +263,7 @@ class Profile(Model): ...@@ -263,7 +263,7 @@ class Profile(Model):
super(Profile, self).save(*args, **kwargs) super(Profile, self).save(*args, **kwargs)
class Meta: class Meta:
ordering = ('id', ) ordering = ('id',)
permissions = ( permissions = (
('use_autocomplete', _('Can use autocomplete.')), ('use_autocomplete', _('Can use autocomplete.')),
) )
...@@ -275,7 +275,7 @@ class FutureMember(Model): ...@@ -275,7 +275,7 @@ class FutureMember(Model):
group = ForeignKey(Group) group = ForeignKey(Group)
class Meta: class Meta:
ordering = ('id', ) ordering = ('id',)
unique_together = ('org_id', 'group') unique_together = ('org_id', 'group')
def __unicode__(self): def __unicode__(self):
...@@ -295,7 +295,7 @@ class GroupProfile(AclBase): ...@@ -295,7 +295,7 @@ class GroupProfile(AclBase):
description = TextField(blank=True) description = TextField(blank=True)
class Meta: class Meta:
ordering = ('id', ) ordering = ('id',)
def __unicode__(self): def __unicode__(self):
return self.group.name return self.group.name
...@@ -331,7 +331,11 @@ def create_profile(user): ...@@ -331,7 +331,11 @@ def create_profile(user):
profile, created = Profile.objects.get_or_create(user=user) profile, created = Profile.objects.get_or_create(user=user)
try: try:
Store(user).create_user(profile.smb_password, None, profile.disk_quota) store = Store(user)
if store.user_exist():
profile.disk_quota = store.get_quota()['soft']
profile.save()
store.create_user(profile.smb_password, None, profile.disk_quota)
except: except:
logger.exception("Can't create user %s", unicode(user)) logger.exception("Can't create user %s", unicode(user))
return created return created
......
...@@ -44,9 +44,19 @@ class NoStoreException(StoreApiException): ...@@ -44,9 +44,19 @@ class NoStoreException(StoreApiException):
pass pass
class NoOrgIdException(StoreApiException):
pass
class Store(object): class Store(object):
def __init__(self, user, default_timeout=0.5): def __init__(self, user, default_timeout=0.5):
self.store_url = settings.STORE_URL
if not self.store_url:
raise NoStoreException
if not user.profile.org_id:
raise NoOrgIdException
self.username = 'u-%s' % user.profile.org_id
self.request_args = {'verify': settings.STORE_VERIFY_SSL} self.request_args = {'verify': settings.STORE_VERIFY_SSL}
if settings.STORE_SSL_AUTH: if settings.STORE_SSL_AUTH:
self.request_args['cert'] = (settings.STORE_CLIENT_CERT, self.request_args['cert'] = (settings.STORE_CLIENT_CERT,
...@@ -54,18 +64,15 @@ class Store(object): ...@@ -54,18 +64,15 @@ class Store(object):
if settings.STORE_BASIC_AUTH: if settings.STORE_BASIC_AUTH:
self.request_args['auth'] = (settings.STORE_CLIENT_USER, self.request_args['auth'] = (settings.STORE_CLIENT_USER,
settings.STORE_CLIENT_PASSWORD) settings.STORE_CLIENT_PASSWORD)
self.username = "u-%d" % user.pk
self.default_timeout = default_timeout self.default_timeout = default_timeout
self.store_url = settings.STORE_URL
if not self.store_url:
raise NoStoreException
def _request(self, url, method=get, timeout=None, def _request(self, url, method=get, timeout=None,
raise_status_code=True, **kwargs): raise_status_code=True, **kwargs):
url = urljoin(self.store_url, url) url = urljoin(self.store_url, url)
if timeout is None: if timeout is None:
timeout = self.default_timeout timeout = self.default_timeout
payload = json.dumps(kwargs) if kwargs else None kwargs['USER'] = self.username
payload = json.dumps(kwargs)
try: try:
headers = {'content-type': 'application/json'} headers = {'content-type': 'application/json'}
response = method(url, data=payload, headers=headers, response = method(url, data=payload, headers=headers,
...@@ -83,7 +90,7 @@ class Store(object): ...@@ -83,7 +90,7 @@ class Store(object):
return response return response
def _request_cmd(self, cmd, **kwargs): def _request_cmd(self, cmd, **kwargs):
return self._request(self.username, post, CMD=cmd, **kwargs) return self._request("/user/", post, CMD=cmd, **kwargs)
def list(self, path, process=True): def list(self, path, process=True):
r = self._request_cmd("LIST", PATH=path) r = self._request_cmd("LIST", PATH=path)
...@@ -119,7 +126,7 @@ class Store(object): ...@@ -119,7 +126,7 @@ class Store(object):
self._request_cmd("RENAME", PATH=old_path, NEW_NAME=new_name) self._request_cmd("RENAME", PATH=old_path, NEW_NAME=new_name)
def get_quota(self): # no CMD? :o def get_quota(self): # no CMD? :o
r = self._request(self.username) r = self._request("/user/")
quota = r.json() quota = r.json()
quota.update({ quota.update({
'readable_used': filesizeformat(float(quota['used'])), 'readable_used': filesizeformat(float(quota['used'])),
...@@ -129,17 +136,17 @@ class Store(object): ...@@ -129,17 +136,17 @@ class Store(object):
return quota return quota
def set_quota(self, quota): def set_quota(self, quota):
self._request("/quota/" + self.username, post, QUOTA=quota) self._request("/quota/", post, QUOTA=quota)
def user_exist(self): def user_exist(self):
try: try:
self._request(self.username) self._request("/user/")
return True return True
except NotOkException: except NotOkException:
return False return False
def create_user(self, password, keys, quota): def create_user(self, password, keys, quota):
self._request("/new/" + self.username, method=post, self._request("/new/", method=post,
SMBPASSWD=password, KEYS=keys, QUOTA=quota) SMBPASSWD=password, KEYS=keys, QUOTA=quota)
@staticmethod @staticmethod
......
...@@ -35,7 +35,8 @@ from django.views.generic import TemplateView ...@@ -35,7 +35,8 @@ from django.views.generic import TemplateView
from braces.views import LoginRequiredMixin from braces.views import LoginRequiredMixin
from ..store_api import Store, NoStoreException, NotOkException from ..store_api import (Store, NoStoreException,
NotOkException, NoOrgIdException)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -70,6 +71,11 @@ class StoreList(LoginRequiredMixin, TemplateView): ...@@ -70,6 +71,11 @@ class StoreList(LoginRequiredMixin, TemplateView):
return super(StoreList, self).get(*args, **kwargs) return super(StoreList, self).get(*args, **kwargs)
except NoStoreException: except NoStoreException:
messages.warning(self.request, _("No store.")) messages.warning(self.request, _("No store."))
except NoOrgIdException:
messages.warning(self.request,
_("Your organization ID is not set."
" To use the store, you need a"
" unique organization ID."))
except NotOkException: except NotOkException:
messages.warning(self.request, _("Store has some problems now." messages.warning(self.request, _("Store has some problems now."
" Try again later.")) " Try again later."))
......
...@@ -39,7 +39,7 @@ def _apply_once(name, tasks, queues, task, data): ...@@ -39,7 +39,7 @@ def _apply_once(name, tasks, queues, task, data):
data = data() data = data()
for queue in queues: for queue in queues:
try: try:
task.apply_async(args=data, queue=queue, expires=60).get(timeout=2) task.apply_async(args=data, queue=queue, expires=60).get(timeout=5)
logger.info("%s configuration is reloaded. (queue: %s)", logger.info("%s configuration is reloaded. (queue: %s)",
name, queue) name, queue)
except TimeoutError as e: except TimeoutError as e:
...@@ -76,8 +76,14 @@ def reloadtask_worker(): ...@@ -76,8 +76,14 @@ def reloadtask_worker():
logger.info("reloadtask_worker: Reload %s", ", ".join(tasks)) logger.info("reloadtask_worker: Reload %s", ", ".join(tasks))
firewall_queues = get_firewall_queues() firewall_queues = get_firewall_queues()
dns_queues = [("%s.dns" % i) for i in
settings.get('dns_queues', [gethostname()])] dns_queues = settings.get('dns_queues', [gethostname()])
if isinstance(dns_queues, (str, unicode)):
dns_queues = [dns_queues]
dns_queues = [("%s.dns" % i) for i in dns_queues]
# dns_queues = [("%s.dns" % i) for i in
# settings.get('dns_queues', [gethostname()])]
_apply_once('dns', tasks, dns_queues, reload_dns, _apply_once('dns', tasks, dns_queues, reload_dns,
lambda: (dns(), )) lambda: (dns(), ))
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
from celery import Celery from celery import Celery
from celery.signals import worker_ready from celery.signals import worker_ready
from datetime import timedelta from datetime import timedelta
from celery.schedules import crontab
from kombu import Queue, Exchange from kombu import Queue, Exchange
from os import getenv from os import getenv
...@@ -52,7 +53,7 @@ celery.conf.update( ...@@ -52,7 +53,7 @@ celery.conf.update(
'dashboard.send_email_notifications': { 'dashboard.send_email_notifications': {
'task': 'dashboard.tasks.local_periodic_tasks.' 'task': 'dashboard.tasks.local_periodic_tasks.'
'send_email_notifications', 'send_email_notifications',
'schedule': timedelta(hours=24), 'schedule': crontab(minute=10, hour=1),
'options': {'queue': 'localhost.man'} 'options': {'queue': 'localhost.man'}
}, },
} }
......
...@@ -86,7 +86,7 @@ class DataStore(Model): ...@@ -86,7 +86,7 @@ class DataStore(Model):
args=[self.path], queue=q).get(timeout=timeout) args=[self.path], queue=q).get(timeout=timeout)
@method_cache(30) @method_cache(30)
def get_orphan_disks(self, timeout=15): def get_orphan_disks(self, timeout=25):
"""Disk image files without Disk object in the database. """Disk image files without Disk object in the database.
""" """
queue_name = self.get_remote_queue_name('storage', "slow") queue_name = self.get_remote_queue_name('storage', "slow")
...@@ -101,7 +101,7 @@ class DataStore(Model): ...@@ -101,7 +101,7 @@ class DataStore(Model):
return orphans return orphans
@method_cache(30) @method_cache(30)
def get_missing_disks(self, timeout=15): def get_missing_disks(self, timeout=25):
"""Disk objects without disk image files. """Disk objects without disk image files.
""" """
queue_name = self.get_remote_queue_name('storage', "slow") queue_name = self.get_remote_queue_name('storage', "slow")
...@@ -111,7 +111,7 @@ class DataStore(Model): ...@@ -111,7 +111,7 @@ class DataStore(Model):
return disks.exclude(filename__in=files) return disks.exclude(filename__in=files)
@method_cache(120) @method_cache(120)
def get_file_statistics(self, timeout=30): def get_file_statistics(self, timeout=90):
queue_name = self.get_remote_queue_name('storage', "slow") queue_name = self.get_remote_queue_name('storage', "slow")
data = storage_tasks.get_file_statistics.apply_async( data = storage_tasks.get_file_statistics.apply_async(
args=[self.path], queue=queue_name).get(timeout=timeout) args=[self.path], queue=queue_name).get(timeout=timeout)
......
...@@ -349,7 +349,7 @@ class Node(OperatedMixin, TimeStampedModel): ...@@ -349,7 +349,7 @@ class Node(OperatedMixin, TimeStampedModel):
continue continue
value = target['datapoints'][-2][0] value = target['datapoints'][-2][0]
retval[metric] = float(value) retval[metric] = float(value)
except (KeyError, IndexError, ValueError): except (KeyError, IndexError, ValueError, TypeError):
continue continue
return retval return retval
......
...@@ -62,7 +62,6 @@ logger = getLogger(__name__) ...@@ -62,7 +62,6 @@ logger = getLogger(__name__)
class RemoteOperationMixin(object): class RemoteOperationMixin(object):
remote_timeout = 30 remote_timeout = 30
def _operation(self, **kwargs): def _operation(self, **kwargs):
...@@ -167,7 +166,6 @@ class InstanceOperation(Operation): ...@@ -167,7 +166,6 @@ class InstanceOperation(Operation):
class RemoteInstanceOperation(RemoteOperationMixin, InstanceOperation): class RemoteInstanceOperation(RemoteOperationMixin, InstanceOperation):
remote_queue = ('vm', 'fast') remote_queue = ('vm', 'fast')
def _get_remote_queue(self): def _get_remote_queue(self):
...@@ -178,7 +176,7 @@ class RemoteInstanceOperation(RemoteOperationMixin, InstanceOperation): ...@@ -178,7 +176,7 @@ class RemoteInstanceOperation(RemoteOperationMixin, InstanceOperation):
class EnsureAgentMixin(object): class EnsureAgentMixin(object):
accept_states = ('RUNNING', ) accept_states = ('RUNNING',)
def check_precond(self): def check_precond(self):
super(EnsureAgentMixin, self).check_precond() super(EnsureAgentMixin, self).check_precond()
...@@ -198,7 +196,7 @@ class EnsureAgentMixin(object): ...@@ -198,7 +196,7 @@ class EnsureAgentMixin(object):
class RemoteAgentOperation(EnsureAgentMixin, RemoteInstanceOperation): class RemoteAgentOperation(EnsureAgentMixin, RemoteInstanceOperation):
remote_queue = ('agent', ) remote_queue = ('agent',)
concurrency_check = False concurrency_check = False
...@@ -213,7 +211,7 @@ class AddInterfaceOperation(InstanceOperation): ...@@ -213,7 +211,7 @@ class AddInterfaceOperation(InstanceOperation):
def rollback(self, net, activity): def rollback(self, net, activity):
with activity.sub_activity( with activity.sub_activity(
'destroying_net', 'destroying_net',
readable_name=ugettext_noop("destroy network (rollback)")): readable_name=ugettext_noop("destroy network (rollback)")):
net.destroy() net.destroy()
net.delete() net.delete()
...@@ -248,11 +246,10 @@ class AddInterfaceOperation(InstanceOperation): ...@@ -248,11 +246,10 @@ class AddInterfaceOperation(InstanceOperation):
@register_operation @register_operation
class CreateDiskOperation(InstanceOperation): class CreateDiskOperation(InstanceOperation):
id = 'create_disk' id = 'create_disk'
name = _("create disk") name = _("create disk")
description = _("Create and attach empty disk to the virtual machine.") description = _("Create and attach empty disk to the virtual machine.")
required_perms = ('storage.create_empty_disk', ) required_perms = ('storage.create_empty_disk',)
accept_states = ('STOPPED', 'PENDING', 'RUNNING') accept_states = ('STOPPED', 'PENDING', 'RUNNING')
def _operation(self, user, size, activity, name=None): def _operation(self, user, size, activity, name=None):
...@@ -271,8 +268,8 @@ class CreateDiskOperation(InstanceOperation): ...@@ -271,8 +268,8 @@ class CreateDiskOperation(InstanceOperation):
if self.instance.is_running: if self.instance.is_running:
with activity.sub_activity( with activity.sub_activity(
'deploying_disk', 'deploying_disk',
readable_name=ugettext_noop("deploying disk") readable_name=ugettext_noop("deploying disk")
): ):
disk.deploy() disk.deploy()
self.instance._attach_disk(parent_activity=activity, disk=disk) self.instance._attach_disk(parent_activity=activity, disk=disk)
...@@ -285,13 +282,12 @@ class CreateDiskOperation(InstanceOperation): ...@@ -285,13 +282,12 @@ class CreateDiskOperation(InstanceOperation):
@register_operation @register_operation
class ResizeDiskOperation(RemoteInstanceOperation): class ResizeDiskOperation(RemoteInstanceOperation):
id = 'resize_disk' id = 'resize_disk'
name = _("resize disk") name = _("resize disk")
description = _("Resize the virtual disk image. " description = _("Resize the virtual disk image. "
"Size must be greater value than the actual size.") "Size must be greater value than the actual size.")
required_perms = ('storage.resize_disk', ) required_perms = ('storage.resize_disk',)
accept_states = ('RUNNING', ) accept_states = ('RUNNING',)
async_queue = "localhost.man.slow" async_queue = "localhost.man.slow"
remote_queue = ('vm', 'slow') remote_queue = ('vm', 'slow')
task = vm_tasks.resize_disk task = vm_tasks.resize_disk
...@@ -324,7 +320,7 @@ class DownloadDiskOperation(InstanceOperation): ...@@ -324,7 +320,7 @@ class DownloadDiskOperation(InstanceOperation):
"machine.") "machine.")
abortable = True abortable = True
has_percentage = True has_percentage = True
required_perms = ('storage.download_disk', ) required_perms = ('storage.download_disk',)
accept_states = ('STOPPED', 'PENDING', 'RUNNING') accept_states = ('STOPPED', 'PENDING', 'RUNNING')
async_queue = "localhost.man.slow" async_queue = "localhost.man.slow"
...@@ -376,7 +372,6 @@ class ExportDiskOperation(InstanceOperation): ...@@ -376,7 +372,6 @@ class ExportDiskOperation(InstanceOperation):
@register_operation @register_operation
class ImportDiskOperation(InstanceOperation): class ImportDiskOperation(InstanceOperation):
id = 'import_disk' id = 'import_disk'
name = _('import disk') name = _('import disk')
description = _('Import and attach a disk image to the virtual machine.') description = _('Import and attach a disk image to the virtual machine.')
...@@ -438,8 +433,8 @@ class DeployOperation(InstanceOperation): ...@@ -438,8 +433,8 @@ class DeployOperation(InstanceOperation):
# Establish network connection (vmdriver) # Establish network connection (vmdriver)
with activity.sub_activity( with activity.sub_activity(
'deploying_net', readable_name=ugettext_noop( 'deploying_net', readable_name=ugettext_noop(
"deploy network")): "deploy network")):
self.instance.deploy_net() self.instance.deploy_net()
try: try:
...@@ -460,6 +455,7 @@ class DeployOperation(InstanceOperation): ...@@ -460,6 +455,7 @@ class DeployOperation(InstanceOperation):
description = _("Deploy virtual machine.") description = _("Deploy virtual machine.")
remote_queue = ("vm", "slow") remote_queue = ("vm", "slow")
task = vm_tasks.deploy task = vm_tasks.deploy
remote_timeout = 120
def _get_remote_args(self, **kwargs): def _get_remote_args(self, **kwargs):
return [self.instance.get_vm_desc()] return [self.instance.get_vm_desc()]
...@@ -569,7 +565,7 @@ class MigrateOperation(RemoteInstanceOperation): ...@@ -569,7 +565,7 @@ class MigrateOperation(RemoteInstanceOperation):
"keeping its full state.") "keeping its full state.")
required_perms = () required_perms = ()
superuser_required = True superuser_required = True
accept_states = ('RUNNING', ) accept_states = ('RUNNING',)
async_queue = "localhost.man.slow" async_queue = "localhost.man.slow"
task = vm_tasks.migrate task = vm_tasks.migrate
remote_queue = ("vm", "slow") remote_queue = ("vm", "slow")
...@@ -581,8 +577,8 @@ class MigrateOperation(RemoteInstanceOperation): ...@@ -581,8 +577,8 @@ class MigrateOperation(RemoteInstanceOperation):
def rollback(self, activity): def rollback(self, activity):
with activity.sub_activity( with activity.sub_activity(
'rollback_net', readable_name=ugettext_noop( 'rollback_net', readable_name=ugettext_noop(
"redeploy network (rollback)")): "redeploy network (rollback)")):
self.instance.deploy_net() self.instance.deploy_net()
def _operation(self, activity, to_node=None, live_migration=True): def _operation(self, activity, to_node=None, live_migration=True):
...@@ -595,8 +591,8 @@ class MigrateOperation(RemoteInstanceOperation): ...@@ -595,8 +591,8 @@ class MigrateOperation(RemoteInstanceOperation):
try: try:
with activity.sub_activity( with activity.sub_activity(
'migrate_vm', readable_name=create_readable( 'migrate_vm', readable_name=create_readable(
ugettext_noop("migrate to %(node)s"), node=to_node)): ugettext_noop("migrate to %(node)s"), node=to_node)):
super(MigrateOperation, self)._operation( super(MigrateOperation, self)._operation(
to_node=to_node, live_migration=live_migration) to_node=to_node, live_migration=live_migration)
except Exception as e: except Exception as e:
...@@ -606,8 +602,8 @@ class MigrateOperation(RemoteInstanceOperation): ...@@ -606,8 +602,8 @@ class MigrateOperation(RemoteInstanceOperation):
# Shutdown networks # Shutdown networks
with activity.sub_activity( with activity.sub_activity(
'shutdown_net', readable_name=ugettext_noop( 'shutdown_net', readable_name=ugettext_noop(
"shutdown network")): "shutdown network")):
self.instance.shutdown_net() self.instance.shutdown_net()
# Refresh node information # Refresh node information
...@@ -616,8 +612,8 @@ class MigrateOperation(RemoteInstanceOperation): ...@@ -616,8 +612,8 @@ class MigrateOperation(RemoteInstanceOperation):
# Estabilish network connection (vmdriver) # Estabilish network connection (vmdriver)
with activity.sub_activity( with activity.sub_activity(
'deploying_net', readable_name=ugettext_noop( 'deploying_net', readable_name=ugettext_noop(
"deploy network")): "deploy network")):
self.instance.deploy_net() self.instance.deploy_net()
...@@ -628,7 +624,7 @@ class RebootOperation(RemoteInstanceOperation): ...@@ -628,7 +624,7 @@ class RebootOperation(RemoteInstanceOperation):
description = _("Warm reboot virtual machine by sending Ctrl+Alt+Del " description = _("Warm reboot virtual machine by sending Ctrl+Alt+Del "
"signal to its console.") "signal to its console.")
required_perms = () required_perms = ()
accept_states = ('RUNNING', ) accept_states = ('RUNNING',)
task = vm_tasks.reboot task = vm_tasks.reboot
def _operation(self, activity): def _operation(self, activity):
...@@ -669,7 +665,7 @@ class RemovePortOperation(InstanceOperation): ...@@ -669,7 +665,7 @@ class RemovePortOperation(InstanceOperation):
description = _("Close the specified port.") description = _("Close the specified port.")
concurrency_check = False concurrency_check = False
acl_level = "operator" acl_level = "operator"
required_perms = ('vm.config_ports', ) required_perms = ('vm.config_ports',)
def _operation(self, activity, rule): def _operation(self, activity, rule):
interface = rule.host.interface_set.get() interface = rule.host.interface_set.get()
...@@ -688,7 +684,7 @@ class AddPortOperation(InstanceOperation): ...@@ -688,7 +684,7 @@ class AddPortOperation(InstanceOperation):
description = _("Open the specified port.") description = _("Open the specified port.")
concurrency_check = False concurrency_check = False
acl_level = "operator" acl_level = "operator"
required_perms = ('vm.config_ports', ) required_perms = ('vm.config_ports',)
def _operation(self, activity, host, proto, port): def _operation(self, activity, host, proto, port):
if host.interface_set.get().instance != self.instance: if host.interface_set.get().instance != self.instance:
...@@ -712,8 +708,8 @@ class RemoveDiskOperation(InstanceOperation): ...@@ -712,8 +708,8 @@ class RemoveDiskOperation(InstanceOperation):
if self.instance.is_running and disk.type not in ["iso"]: if self.instance.is_running and disk.type not in ["iso"]:
self.instance._detach_disk(disk=disk, parent_activity=activity) self.instance._detach_disk(disk=disk, parent_activity=activity)
with activity.sub_activity( with activity.sub_activity(
'destroy_disk', 'destroy_disk',
readable_name=ugettext_noop('destroy disk') readable_name=ugettext_noop('destroy disk')
): ):
disk.destroy() disk.destroy()
return self.instance.disks.remove(disk) return self.instance.disks.remove(disk)
...@@ -729,7 +725,7 @@ class ResetOperation(RemoteInstanceOperation): ...@@ -729,7 +725,7 @@ class ResetOperation(RemoteInstanceOperation):
name = _("reset") name = _("reset")
description = _("Cold reboot virtual machine (power cycle).") description = _("Cold reboot virtual machine (power cycle).")
required_perms = () required_perms = ()
accept_states = ('RUNNING', ) accept_states = ('RUNNING',)
task = vm_tasks.reset task = vm_tasks.reset
def _operation(self, activity): def _operation(self, activity):
...@@ -749,7 +745,7 @@ class SaveAsTemplateOperation(InstanceOperation): ...@@ -749,7 +745,7 @@ class SaveAsTemplateOperation(InstanceOperation):
"start an instance of it.") "start an instance of it.")
has_percentage = True has_percentage = True
abortable = True abortable = True
required_perms = ('vm.create_template', ) required_perms = ('vm.create_template',)
accept_states = ('RUNNING', 'STOPPED') accept_states = ('RUNNING', 'STOPPED')
async_queue = "localhost.man.slow" async_queue = "localhost.man.slow"
...@@ -817,10 +813,10 @@ class SaveAsTemplateOperation(InstanceOperation): ...@@ -817,10 +813,10 @@ class SaveAsTemplateOperation(InstanceOperation):
self.disks = [] self.disks = []
for disk in self.instance.disks.all(): for disk in self.instance.disks.all():
with activity.sub_activity( with activity.sub_activity(
'saving_disk', 'saving_disk',
readable_name=create_readable( readable_name=create_readable(
ugettext_noop("saving disk %(name)s"), ugettext_noop("saving disk %(name)s"),
name=disk.name) name=disk.name)
): ):
self.disks.append(__try_save_disk(disk)) self.disks.append(__try_save_disk(disk))
...@@ -861,7 +857,7 @@ class ShutdownOperation(AbortableRemoteOperationMixin, ...@@ -861,7 +857,7 @@ class ShutdownOperation(AbortableRemoteOperationMixin,
"turn itself off in a period.") "turn itself off in a period.")
abortable = True abortable = True
required_perms = () required_perms = ()
accept_states = ('RUNNING', ) accept_states = ('RUNNING',)
resultant_state = 'STOPPED' resultant_state = 'STOPPED'
task = vm_tasks.shutdown task = vm_tasks.shutdown
remote_queue = ("vm", "slow") remote_queue = ("vm", "slow")
...@@ -922,7 +918,7 @@ class SleepOperation(InstanceOperation): ...@@ -922,7 +918,7 @@ class SleepOperation(InstanceOperation):
"resumed. In the meantime, the machine will only use " "resumed. In the meantime, the machine will only use "
"storage resources, and keep network resources allocated.") "storage resources, and keep network resources allocated.")
required_perms = () required_perms = ()
accept_states = ('RUNNING', ) accept_states = ('RUNNING',)
resultant_state = 'SUSPENDED' resultant_state = 'SUSPENDED'
async_queue = "localhost.man.slow" async_queue = "localhost.man.slow"
...@@ -966,7 +962,7 @@ class WakeUpOperation(InstanceOperation): ...@@ -966,7 +962,7 @@ class WakeUpOperation(InstanceOperation):
"load the saved memory of the system and start the " "load the saved memory of the system and start the "
"virtual machine from this state.") "virtual machine from this state.")
required_perms = () required_perms = ()
accept_states = ('SUSPENDED', ) accept_states = ('SUSPENDED',)
resultant_state = 'RUNNING' resultant_state = 'RUNNING'
async_queue = "localhost.man.slow" async_queue = "localhost.man.slow"
...@@ -989,8 +985,8 @@ class WakeUpOperation(InstanceOperation): ...@@ -989,8 +985,8 @@ class WakeUpOperation(InstanceOperation):
# Estabilish network connection (vmdriver) # Estabilish network connection (vmdriver)
with activity.sub_activity( with activity.sub_activity(
'deploying_net', readable_name=ugettext_noop( 'deploying_net', readable_name=ugettext_noop(
"deploy network")): "deploy network")):
self.instance.deploy_net() self.instance.deploy_net()
try: try:
...@@ -1026,7 +1022,7 @@ class RenewOperation(InstanceOperation): ...@@ -1026,7 +1022,7 @@ class RenewOperation(InstanceOperation):
def set_time_of_suspend(self, activity, suspend, force): def set_time_of_suspend(self, activity, suspend, force):
with activity.sub_activity( with activity.sub_activity(
'renew_suspend', concurrency_check=False, 'renew_suspend', concurrency_check=False,
readable_name=ugettext_noop('set time of suspend')): readable_name=ugettext_noop('set time of suspend')):
if (not force and suspend and self.instance.time_of_suspend and if (not force and suspend and self.instance.time_of_suspend and
suspend < self.instance.time_of_suspend): suspend < self.instance.time_of_suspend):
...@@ -1037,7 +1033,7 @@ class RenewOperation(InstanceOperation): ...@@ -1037,7 +1033,7 @@ class RenewOperation(InstanceOperation):
def set_time_of_delete(self, activity, delete, force): def set_time_of_delete(self, activity, delete, force):
with activity.sub_activity( with activity.sub_activity(
'renew_delete', concurrency_check=False, 'renew_delete', concurrency_check=False,
readable_name=ugettext_noop('set time of delete')): readable_name=ugettext_noop('set time of delete')):
if (not force and delete and self.instance.time_of_delete and if (not force and delete and self.instance.time_of_delete and
delete < self.instance.time_of_delete): delete < self.instance.time_of_delete):
...@@ -1078,7 +1074,7 @@ class ChangeStateOperation(InstanceOperation): ...@@ -1078,7 +1074,7 @@ class ChangeStateOperation(InstanceOperation):
"redeployed without losing its storage and network " "redeployed without losing its storage and network "
"resources.") "resources.")
acl_level = "owner" acl_level = "owner"
required_perms = ('vm.emergency_change_state', ) required_perms = ('vm.emergency_change_state',)
concurrency_check = False concurrency_check = False
def _operation(self, user, activity, new_state="NOSTATE", interrupt=False, def _operation(self, user, activity, new_state="NOSTATE", interrupt=False,
...@@ -1105,7 +1101,7 @@ class RedeployOperation(InstanceOperation): ...@@ -1105,7 +1101,7 @@ class RedeployOperation(InstanceOperation):
"and redeploy the VM. This operation allows starting " "and redeploy the VM. This operation allows starting "
"machines formerly running on a failed node.") "machines formerly running on a failed node.")
acl_level = "owner" acl_level = "owner"
required_perms = ('vm.redeploy', ) required_perms = ('vm.redeploy',)
concurrency_check = False concurrency_check = False
def _operation(self, user, activity, with_emergency_change_state=True): def _operation(self, user, activity, with_emergency_change_state=True):
...@@ -1359,7 +1355,7 @@ class ScreenshotOperation(RemoteInstanceOperation): ...@@ -1359,7 +1355,7 @@ class ScreenshotOperation(RemoteInstanceOperation):
"screensaver.") "screensaver.")
acl_level = "owner" acl_level = "owner"
required_perms = () required_perms = ()
accept_states = ('RUNNING', ) accept_states = ('RUNNING',)
task = vm_tasks.screenshot task = vm_tasks.screenshot
...@@ -1371,8 +1367,8 @@ class RecoverOperation(InstanceOperation): ...@@ -1371,8 +1367,8 @@ class RecoverOperation(InstanceOperation):
"state. Network resources (allocations) are already lost, " "state. Network resources (allocations) are already lost, "
"so you will have to manually add interfaces afterwards.") "so you will have to manually add interfaces afterwards.")
acl_level = "owner" acl_level = "owner"
required_perms = ('vm.recover', ) required_perms = ('vm.recover',)
accept_states = ('DESTROYED', ) accept_states = ('DESTROYED',)
resultant_state = 'PENDING' resultant_state = 'PENDING'
def check_precond(self): def check_precond(self):
...@@ -1383,7 +1379,7 @@ class RecoverOperation(InstanceOperation): ...@@ -1383,7 +1379,7 @@ class RecoverOperation(InstanceOperation):
def _operation(self, user, activity): def _operation(self, user, activity):
with activity.sub_activity( with activity.sub_activity(
'recover_instance', 'recover_instance',
readable_name=ugettext_noop("recover instance")): readable_name=ugettext_noop("recover instance")):
self.instance.destroyed_at = None self.instance.destroyed_at = None
for disk in self.instance.disks.all(): for disk in self.instance.disks.all():
...@@ -1410,7 +1406,7 @@ class ResourcesOperation(InstanceOperation): ...@@ -1410,7 +1406,7 @@ class ResourcesOperation(InstanceOperation):
name = _("resources change") name = _("resources change")
description = _("Change resources of a stopped virtual machine.") description = _("Change resources of a stopped virtual machine.")
acl_level = "owner" acl_level = "owner"
required_perms = ('vm.change_resources', ) required_perms = ('vm.change_resources',)
accept_states = ('STOPPED', 'PENDING', 'RUNNING') accept_states = ('STOPPED', 'PENDING', 'RUNNING')
def _operation(self, user, activity, def _operation(self, user, activity,
...@@ -1716,7 +1712,7 @@ class UpdateAgentOperation(RemoteAgentOperation): ...@@ -1716,7 +1712,7 @@ class UpdateAgentOperation(RemoteAgentOperation):
index = 0 index = 0
filename = settings.AGENT_VERSION + ".tar" filename = settings.AGENT_VERSION + ".tar"
while True: while True:
chunk = data[index:index+chunk_size] chunk = data[index:index + chunk_size]
if chunk: if chunk:
agent_tasks.append.apply_async( agent_tasks.append.apply_async(
queue=queue, queue=queue,
......
...@@ -58,9 +58,9 @@ def garbage_collector(timeout=15): ...@@ -58,9 +58,9 @@ def garbage_collector(timeout=15):
i.pk, unicode(e)) i.pk, unicode(e))
elif (i.time_of_suspend and now > i.time_of_suspend and elif (i.time_of_suspend and now > i.time_of_suspend and
i.state == 'RUNNING'): i.state == 'RUNNING'):
i.sleep.async(system=True)
logger.info("Expired instance %d suspended." % i.pk) logger.info("Expired instance %d suspended." % i.pk)
try: try:
i.sleep.async(system=True)
i.owner.profile.notify( i.owner.profile.notify(
ugettext_noop('%(instance)s suspended'), ugettext_noop('%(instance)s suspended'),
ugettext_noop( ugettext_noop(
...@@ -68,8 +68,10 @@ def garbage_collector(timeout=15): ...@@ -68,8 +68,10 @@ def garbage_collector(timeout=15):
'has been suspended due to expiration. ' 'has been suspended due to expiration. '
'You can resume or destroy it.'), 'You can resume or destroy it.'),
instance=i.name, url=i.get_absolute_url()) instance=i.name, url=i.get_absolute_url())
except ActivityInProgressError:
logger.error("Expired instance %d can't be destroyed due the AtctivityInPorgressError.", i.pk)
except Exception as e: except Exception as e:
logger.debug('Could not notify owner of instance %d .%s', logger.info('Could not notify owner of instance %d .%s',
i.pk, unicode(e)) i.pk, unicode(e))
elif i.is_expiring(): elif i.is_expiring():
logger.debug("Instance %d expires soon." % i.pk) logger.debug("Instance %d expires soon." % i.pk)
......