Add support for locking and unlocking servers
Partially implements: blueprint lock-unlock-server Change-Id: I6d261cc7fb314bda60f0732f7a7bb3b23ba7c179
This commit is contained in:
parent
ff09b75886
commit
5840d041db
|
@ -656,6 +656,14 @@ def server_stop(request, instance_id):
|
|||
novaclient(request).servers.stop(instance_id)
|
||||
|
||||
|
||||
def server_lock(request, instance_id):
|
||||
novaclient(request).servers.lock(instance_id)
|
||||
|
||||
|
||||
def server_unlock(request, instance_id):
|
||||
novaclient(request).servers.unlock(instance_id)
|
||||
|
||||
|
||||
def tenant_quota_get(request, tenant_id):
|
||||
return base.QuotaSet(novaclient(request).quotas.get(tenant_id))
|
||||
|
||||
|
|
|
@ -709,6 +709,68 @@ class StopInstance(policy.PolicyTargetMixin, tables.BatchAction):
|
|||
api.nova.server_stop(request, obj_id)
|
||||
|
||||
|
||||
class LockInstance(policy.PolicyTargetMixin, tables.BatchAction):
|
||||
name = "lock"
|
||||
policy_rules = (("compute", "compute_extension:admin_actions:lock"),)
|
||||
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
return ungettext_lazy(
|
||||
u"Lock Instance",
|
||||
u"Lock Instances",
|
||||
count
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def action_past(count):
|
||||
return ungettext_lazy(
|
||||
u"Locked Instance",
|
||||
u"Locked Instances",
|
||||
count
|
||||
)
|
||||
|
||||
# TODO(akrivoka): When the lock status is added to nova, revisit this
|
||||
# to only allow unlocked instances to be locked
|
||||
def allowed(self, request, instance):
|
||||
if not api.nova.extension_supported('AdminActions', request):
|
||||
return False
|
||||
return True
|
||||
|
||||
def action(self, request, obj_id):
|
||||
api.nova.server_lock(request, obj_id)
|
||||
|
||||
|
||||
class UnlockInstance(policy.PolicyTargetMixin, tables.BatchAction):
|
||||
name = "unlock"
|
||||
policy_rules = (("compute", "compute_extension:admin_actions:unlock"),)
|
||||
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
return ungettext_lazy(
|
||||
u"Unlock Instance",
|
||||
u"Unlock Instances",
|
||||
count
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def action_past(count):
|
||||
return ungettext_lazy(
|
||||
u"Unlocked Instance",
|
||||
u"Unlocked Instances",
|
||||
count
|
||||
)
|
||||
|
||||
# TODO(akrivoka): When the lock status is added to nova, revisit this
|
||||
# to only allow locked instances to be unlocked
|
||||
def allowed(self, request, instance):
|
||||
if not api.nova.extension_supported('AdminActions', request):
|
||||
return False
|
||||
return True
|
||||
|
||||
def action(self, request, obj_id):
|
||||
api.nova.server_unlock(request, obj_id)
|
||||
|
||||
|
||||
def get_ips(instance):
|
||||
template_name = 'project/instances/_instance_ips.html'
|
||||
context = {"instance": instance}
|
||||
|
@ -930,5 +992,6 @@ class InstancesTable(tables.DataTable):
|
|||
SimpleDisassociateIP, EditInstance,
|
||||
DecryptInstancePassword, EditInstanceSecurityGroups,
|
||||
ConsoleLink, LogLink, TogglePause, ToggleSuspend,
|
||||
ResizeLink, SoftRebootInstance, RebootInstance,
|
||||
ResizeLink, LockInstance, UnlockInstance,
|
||||
SoftRebootInstance, RebootInstance,
|
||||
StopInstance, RebuildInstance, TerminateInstance)
|
||||
|
|
|
@ -653,6 +653,115 @@ class InstanceTests(helpers.TestCase):
|
|||
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@helpers.create_stubs({api.nova: ('server_lock',
|
||||
'server_list',
|
||||
'extension_supported',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: ('servers_update_addresses',)})
|
||||
def test_lock_instance(self):
|
||||
servers = self.servers.list()
|
||||
server = servers[0]
|
||||
|
||||
api.nova.extension_supported('AdminActions', IsA(
|
||||
http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
api.glance.image_list_detailed(IgnoreArg()).AndReturn((
|
||||
self.images.list(), False, False))
|
||||
search_opts = {'marker': None, 'paginate': True}
|
||||
api.nova.server_list(
|
||||
IsA(http.HttpRequest),
|
||||
search_opts=search_opts).AndReturn([servers, False])
|
||||
api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
|
||||
api.nova.server_lock(IsA(http.HttpRequest), server.id)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
formData = {'action': 'instances__lock__%s' % server.id}
|
||||
res = self.client.post(INDEX_URL, formData)
|
||||
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@helpers.create_stubs({api.nova: ('server_lock',
|
||||
'server_list',
|
||||
'extension_supported',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: ('servers_update_addresses',)})
|
||||
def test_lock_instance_exception(self):
|
||||
servers = self.servers.list()
|
||||
server = servers[0]
|
||||
|
||||
api.nova.extension_supported('AdminActions', IsA(
|
||||
http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
api.glance.image_list_detailed(IgnoreArg()).AndReturn((
|
||||
self.images.list(), False, False))
|
||||
search_opts = {'marker': None, 'paginate': True}
|
||||
api.nova.server_list(
|
||||
IsA(http.HttpRequest),
|
||||
search_opts=search_opts).AndReturn([servers, False])
|
||||
api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
|
||||
api.nova.server_lock(IsA(http.HttpRequest), server.id).AndRaise(
|
||||
self.exceptions.nova)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
formData = {'action': 'instances__lock__%s' % server.id}
|
||||
res = self.client.post(INDEX_URL, formData)
|
||||
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@helpers.create_stubs({api.nova: ('server_unlock',
|
||||
'server_list',
|
||||
'extension_supported',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: ('servers_update_addresses',)})
|
||||
def test_unlock_instance(self):
|
||||
servers = self.servers.list()
|
||||
server = servers[0]
|
||||
api.nova.extension_supported('AdminActions', IsA(
|
||||
http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
api.glance.image_list_detailed(IgnoreArg()).AndReturn((
|
||||
self.images.list(), False, False))
|
||||
search_opts = {'marker': None, 'paginate': True}
|
||||
api.nova.server_list(
|
||||
IsA(http.HttpRequest),
|
||||
search_opts=search_opts).AndReturn([servers, False])
|
||||
api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
|
||||
api.nova.server_unlock(IsA(http.HttpRequest), server.id)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
formData = {'action': 'instances__unlock__%s' % server.id}
|
||||
res = self.client.post(INDEX_URL, formData)
|
||||
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@helpers.create_stubs({api.nova: ('server_unlock',
|
||||
'server_list',
|
||||
'extension_supported',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: ('servers_update_addresses',)})
|
||||
def test_unlock_instance_exception(self):
|
||||
servers = self.servers.list()
|
||||
server = servers[0]
|
||||
|
||||
api.nova.extension_supported('AdminActions', IsA(
|
||||
http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
api.glance.image_list_detailed(IgnoreArg()).AndReturn((
|
||||
self.images.list(), False, False))
|
||||
search_opts = {'marker': None, 'paginate': True}
|
||||
api.nova.server_list(
|
||||
IsA(http.HttpRequest),
|
||||
search_opts=search_opts).AndReturn([servers, False])
|
||||
api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
|
||||
api.nova.server_unlock(IsA(http.HttpRequest), server.id).AndRaise(
|
||||
self.exceptions.nova)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
formData = {'action': 'instances__unlock__%s' % server.id}
|
||||
res = self.client.post(INDEX_URL, formData)
|
||||
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@helpers.create_stubs({
|
||||
api.nova: (
|
||||
"server_get",
|
||||
|
|
Loading…
Reference in New Issue