Add availability zone choice to launch instance
Fixes: bug #1186075 Implements: blueprint select-zone-when-creating-instance * Updated project.instances.tests to include availability zone information where required Change-Id: I14272a94b90587575776142da82413db88f5a99c
This commit is contained in:
parent
08f8050d88
commit
b029961340
@ -344,12 +344,12 @@ def keypair_list(request):
|
||||
|
||||
def server_create(request, name, image, flavor, key_name, user_data,
|
||||
security_groups, block_device_mapping, nics=None,
|
||||
instance_count=1, admin_pass=None):
|
||||
availability_zone=None, instance_count=1, admin_pass=None):
|
||||
return Server(novaclient(request).servers.create(
|
||||
name, image, flavor, userdata=user_data,
|
||||
security_groups=security_groups,
|
||||
key_name=key_name, block_device_mapping=block_device_mapping,
|
||||
nics=nics,
|
||||
nics=nics, availability_zone=availability_zone,
|
||||
min_count=instance_count, admin_pass=admin_pass), request)
|
||||
|
||||
|
||||
@ -571,3 +571,7 @@ def tenant_absolute_limits(request, reserved=False):
|
||||
else:
|
||||
limits_dict[limit.name] = limit.value
|
||||
return limits_dict
|
||||
|
||||
|
||||
def availability_zone_list(request, detailed=False):
|
||||
return novaclient(request).availability_zones.list(detailed=detailed)
|
||||
|
@ -797,7 +797,8 @@ class InstanceTests(test.TestCase):
|
||||
|
||||
@test.create_stubs({api.nova: ('flavor_list',
|
||||
'keypair_list',
|
||||
'security_group_list',),
|
||||
'security_group_list',
|
||||
'availability_zone_list',),
|
||||
cinder: ('volume_snapshot_list',
|
||||
'volume_list',),
|
||||
quotas: ('tenant_quota_usages',),
|
||||
@ -836,6 +837,8 @@ class InstanceTests(test.TestCase):
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.availability_zone_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.availability_zones.list())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@ -862,6 +865,7 @@ class InstanceTests(test.TestCase):
|
||||
api.nova: ('flavor_list',
|
||||
'keypair_list',
|
||||
'security_group_list',
|
||||
'availability_zone_list',
|
||||
'server_create',),
|
||||
cinder: ('volume_list',
|
||||
'volume_snapshot_list',)})
|
||||
@ -871,6 +875,7 @@ class InstanceTests(test.TestCase):
|
||||
keypair = self.keypairs.first()
|
||||
server = self.servers.first()
|
||||
sec_group = self.security_groups.first()
|
||||
avail_zone = self.availability_zones.first()
|
||||
customization_script = 'user data'
|
||||
nics = [{"net-id": self.networks.first().id, "v4-fixed-ip": ''}]
|
||||
|
||||
@ -880,6 +885,8 @@ class InstanceTests(test.TestCase):
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.availability_zone_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.availability_zones.list())
|
||||
api.glance.image_list_detailed(IsA(http.HttpRequest),
|
||||
filters={'is_public': True,
|
||||
'status': 'active'}) \
|
||||
@ -907,6 +914,7 @@ class InstanceTests(test.TestCase):
|
||||
[sec_group.name],
|
||||
None,
|
||||
nics=nics,
|
||||
availability_zone=avail_zone.zoneName,
|
||||
instance_count=IsA(int),
|
||||
admin_pass=u'')
|
||||
|
||||
@ -921,6 +929,7 @@ class InstanceTests(test.TestCase):
|
||||
'project_id': self.tenants.first().id,
|
||||
'user_id': self.user.id,
|
||||
'groups': sec_group.name,
|
||||
'availability_zone': avail_zone.zoneName,
|
||||
'volume_type': '',
|
||||
'network': self.networks.first().id,
|
||||
'count': 1}
|
||||
@ -936,6 +945,7 @@ class InstanceTests(test.TestCase):
|
||||
api.nova: ('flavor_list',
|
||||
'keypair_list',
|
||||
'security_group_list',
|
||||
'availability_zone_list',
|
||||
'server_create',),
|
||||
cinder: ('volume_list',
|
||||
'volume_snapshot_list',)})
|
||||
@ -946,6 +956,7 @@ class InstanceTests(test.TestCase):
|
||||
server = self.servers.first()
|
||||
volume = self.volumes.first()
|
||||
sec_group = self.security_groups.first()
|
||||
avail_zone = self.availability_zones.first()
|
||||
customization_script = 'user data'
|
||||
device_name = u'vda'
|
||||
volume_choice = "%s:vol" % volume.id
|
||||
@ -974,6 +985,8 @@ class InstanceTests(test.TestCase):
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.availability_zone_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.availability_zones.list())
|
||||
cinder.volume_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.volumes.list())
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
||||
@ -1012,6 +1025,7 @@ class InstanceTests(test.TestCase):
|
||||
api.nova: ('flavor_list',
|
||||
'keypair_list',
|
||||
'security_group_list',
|
||||
'availability_zone_list',
|
||||
'server_create',),
|
||||
cinder: ('volume_list',
|
||||
'volume_snapshot_list',)})
|
||||
@ -1021,6 +1035,7 @@ class InstanceTests(test.TestCase):
|
||||
server = self.servers.first()
|
||||
volume = self.volumes.first()
|
||||
sec_group = self.security_groups.first()
|
||||
avail_zone = self.availability_zones.first()
|
||||
customization_script = 'user data'
|
||||
device_name = u'vda'
|
||||
volume_choice = "%s:vol" % volume.id
|
||||
@ -1033,6 +1048,8 @@ class InstanceTests(test.TestCase):
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.availability_zone_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.availability_zones.list())
|
||||
api.glance.image_list_detailed(IsA(http.HttpRequest),
|
||||
filters={'is_public': True,
|
||||
'status': 'active'}) \
|
||||
@ -1060,6 +1077,7 @@ class InstanceTests(test.TestCase):
|
||||
[sec_group.name],
|
||||
block_device_mapping,
|
||||
nics=nics,
|
||||
availability_zone=avail_zone.zoneName,
|
||||
instance_count=IsA(int),
|
||||
admin_pass=u'')
|
||||
|
||||
@ -1073,6 +1091,7 @@ class InstanceTests(test.TestCase):
|
||||
'project_id': self.tenants.first().id,
|
||||
'user_id': self.user.id,
|
||||
'groups': sec_group.name,
|
||||
'availability_zone': avail_zone.zoneName,
|
||||
'volume_type': 'volume_id',
|
||||
'volume_id': volume_choice,
|
||||
'device_name': device_name,
|
||||
@ -1090,7 +1109,8 @@ class InstanceTests(test.TestCase):
|
||||
api.nova: ('server_create',
|
||||
'flavor_list',
|
||||
'keypair_list',
|
||||
'security_group_list',),
|
||||
'security_group_list',
|
||||
'availability_zone_list',),
|
||||
cinder: ('volume_list',
|
||||
'volume_snapshot_list',)})
|
||||
def test_launch_instance_post_no_images_available_boot_from_volume(self):
|
||||
@ -1099,6 +1119,7 @@ class InstanceTests(test.TestCase):
|
||||
server = self.servers.first()
|
||||
volume = self.volumes.first()
|
||||
sec_group = self.security_groups.first()
|
||||
avail_zone = self.availability_zones.first()
|
||||
customization_script = 'user data'
|
||||
device_name = u'vda'
|
||||
volume_choice = "%s:vol" % volume.id
|
||||
@ -1111,6 +1132,8 @@ class InstanceTests(test.TestCase):
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.availability_zone_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.availability_zones.list())
|
||||
api.glance.image_list_detailed(IsA(http.HttpRequest),
|
||||
filters={'is_public': True,
|
||||
'status': 'active'}) \
|
||||
@ -1139,6 +1162,7 @@ class InstanceTests(test.TestCase):
|
||||
[sec_group.name],
|
||||
block_device_mapping,
|
||||
nics=nics,
|
||||
availability_zone=avail_zone.zoneName,
|
||||
instance_count=IsA(int),
|
||||
admin_pass=u'')
|
||||
|
||||
@ -1153,6 +1177,7 @@ class InstanceTests(test.TestCase):
|
||||
'project_id': self.tenants.first().id,
|
||||
'user_id': self.user.id,
|
||||
'groups': sec_group.name,
|
||||
'availability_zone': avail_zone.zoneName,
|
||||
'network': self.networks.first().id,
|
||||
'volume_type': 'volume_id',
|
||||
'volume_id': volume_choice,
|
||||
@ -1169,6 +1194,7 @@ class InstanceTests(test.TestCase):
|
||||
quotas: ('tenant_quota_usages',),
|
||||
api.nova: ('flavor_list',
|
||||
'keypair_list',
|
||||
'availability_zone_list',
|
||||
'security_group_list',),
|
||||
cinder: ('volume_list',
|
||||
'volume_snapshot_list',)})
|
||||
@ -1177,6 +1203,7 @@ class InstanceTests(test.TestCase):
|
||||
keypair = self.keypairs.first()
|
||||
server = self.servers.first()
|
||||
sec_group = self.security_groups.first()
|
||||
avail_zone = self.availability_zones.first()
|
||||
customization_script = 'user data'
|
||||
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
@ -1203,6 +1230,8 @@ class InstanceTests(test.TestCase):
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.availability_zone_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.availability_zones.list())
|
||||
cinder.volume_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([])
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
||||
@ -1218,6 +1247,7 @@ class InstanceTests(test.TestCase):
|
||||
'project_id': self.tenants.first().id,
|
||||
'user_id': self.user.id,
|
||||
'groups': sec_group.name,
|
||||
'availability_zone': avail_zone.zoneName,
|
||||
'volume_type': '',
|
||||
'count': 1}
|
||||
url = reverse('horizon:project:instances:launch')
|
||||
@ -1237,7 +1267,8 @@ class InstanceTests(test.TestCase):
|
||||
'volume_snapshot_list',),
|
||||
api.nova: ('flavor_list',
|
||||
'keypair_list',
|
||||
'security_group_list',)})
|
||||
'security_group_list',
|
||||
'availability_zone_list',)})
|
||||
def test_launch_flavorlist_error(self):
|
||||
cinder.volume_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.volumes.list())
|
||||
@ -1268,6 +1299,8 @@ class InstanceTests(test.TestCase):
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.availability_zone_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.availability_zones.list())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@ -1281,6 +1314,7 @@ class InstanceTests(test.TestCase):
|
||||
api.nova: ('flavor_list',
|
||||
'keypair_list',
|
||||
'security_group_list',
|
||||
'availability_zone_list',
|
||||
'server_create',),
|
||||
cinder: ('volume_list',
|
||||
'volume_snapshot_list',)})
|
||||
@ -1290,6 +1324,7 @@ class InstanceTests(test.TestCase):
|
||||
keypair = self.keypairs.first()
|
||||
server = self.servers.first()
|
||||
sec_group = self.security_groups.first()
|
||||
avail_zone = self.availability_zones.first()
|
||||
customization_script = 'userData'
|
||||
nics = [{"net-id": self.networks.first().id, "v4-fixed-ip": ''}]
|
||||
|
||||
@ -1299,6 +1334,8 @@ class InstanceTests(test.TestCase):
|
||||
api.nova.keypair_list(IgnoreArg()).AndReturn(self.keypairs.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.availability_zone_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.availability_zones.list())
|
||||
api.glance.image_list_detailed(IsA(http.HttpRequest),
|
||||
filters={'is_public': True,
|
||||
'status': 'active'}) \
|
||||
@ -1324,6 +1361,7 @@ class InstanceTests(test.TestCase):
|
||||
[sec_group.name],
|
||||
None,
|
||||
nics=nics,
|
||||
availability_zone=avail_zone.zoneName,
|
||||
instance_count=IsA(int),
|
||||
admin_pass='password') \
|
||||
.AndRaise(self.exceptions.keystone)
|
||||
@ -1333,6 +1371,7 @@ class InstanceTests(test.TestCase):
|
||||
form_data = {'flavor': flavor.id,
|
||||
'source_type': 'image_id',
|
||||
'image_id': image.id,
|
||||
'availability_zone': avail_zone.zoneName,
|
||||
'keypair': keypair.name,
|
||||
'name': server.name,
|
||||
'customization_script': customization_script,
|
||||
@ -1354,7 +1393,8 @@ class InstanceTests(test.TestCase):
|
||||
quotas: ('tenant_quota_usages',),
|
||||
api.nova: ('flavor_list',
|
||||
'keypair_list',
|
||||
'security_group_list',),
|
||||
'security_group_list',
|
||||
'availability_zone_list',),
|
||||
cinder: ('volume_list',
|
||||
'volume_snapshot_list',)})
|
||||
def test_launch_form_instance_count_error(self):
|
||||
@ -1364,6 +1404,7 @@ class InstanceTests(test.TestCase):
|
||||
server = self.servers.first()
|
||||
volume = self.volumes.first()
|
||||
sec_group = self.security_groups.first()
|
||||
avail_zone = self.availability_zones.first()
|
||||
customization_script = 'user data'
|
||||
device_name = u'vda'
|
||||
volume_choice = "%s:vol" % volume.id
|
||||
@ -1374,6 +1415,8 @@ class InstanceTests(test.TestCase):
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.availability_zone_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.availability_zones.list())
|
||||
api.glance.image_list_detailed(IsA(http.HttpRequest),
|
||||
filters={'is_public': True,
|
||||
'status': 'active'}) \
|
||||
@ -1403,6 +1446,7 @@ class InstanceTests(test.TestCase):
|
||||
form_data = {'flavor': flavor.id,
|
||||
'source_type': 'image_id',
|
||||
'image_id': image.id,
|
||||
'availability_zone': avail_zone.zoneName,
|
||||
'keypair': keypair.name,
|
||||
'name': server.name,
|
||||
'customization_script': customization_script,
|
||||
@ -1469,7 +1513,8 @@ class InstanceTests(test.TestCase):
|
||||
|
||||
@test.create_stubs({api.nova: ('flavor_list',
|
||||
'keypair_list',
|
||||
'security_group_list',),
|
||||
'security_group_list',
|
||||
'availability_zone_list',),
|
||||
cinder: ('volume_snapshot_list',
|
||||
'volume_list',),
|
||||
quotas: ('tenant_quota_usages',),
|
||||
@ -1509,6 +1554,8 @@ class InstanceTests(test.TestCase):
|
||||
.AndReturn([keypair])
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.availability_zone_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.availability_zones.list())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
|
@ -179,6 +179,8 @@ class SetInstanceDetailsAction(workflows.Action):
|
||||
image_id = forms.ChoiceField(label=_("Image"), required=False)
|
||||
instance_snapshot_id = forms.ChoiceField(label=_("Instance Snapshot"),
|
||||
required=False)
|
||||
availability_zone = forms.ChoiceField(label=_("Availability Zone"),
|
||||
required=False)
|
||||
name = forms.CharField(max_length=80, label=_("Instance Name"))
|
||||
flavor = forms.ChoiceField(label=_("Flavor"),
|
||||
help_text=_("Size of image to launch."))
|
||||
@ -271,6 +273,23 @@ class SetInstanceDetailsAction(workflows.Action):
|
||||
_('Unable to retrieve instance flavors.'))
|
||||
return sorted(flavor_list)
|
||||
|
||||
def populate_availability_zone_choices(self, request, context):
|
||||
try:
|
||||
zones = api.nova.availability_zone_list(request)
|
||||
except:
|
||||
zones = []
|
||||
exceptions.handle(request,
|
||||
_('Unable to retrieve availability zones.'))
|
||||
|
||||
zone_list = [(zone.zoneName, zone.zoneName)
|
||||
for zone in zones if zone.zoneState['available']]
|
||||
zone_list.sort()
|
||||
if zone_list:
|
||||
zone_list.insert(0, ("", _("Any Availability Zone")))
|
||||
else:
|
||||
zone_list.insert(0, ("", _("No availability zones found.")))
|
||||
return zone_list
|
||||
|
||||
def get_help_text(self):
|
||||
extra = {}
|
||||
try:
|
||||
@ -287,7 +306,8 @@ class SetInstanceDetailsAction(workflows.Action):
|
||||
|
||||
class SetInstanceDetails(workflows.Step):
|
||||
action_class = SetInstanceDetailsAction
|
||||
contributes = ("source_type", "source_id", "name", "count", "flavor")
|
||||
contributes = ("source_type", "source_id", "availability_zone",
|
||||
"name", "count", "flavor")
|
||||
|
||||
def prepare_action_context(self, request, context):
|
||||
if 'source_type' in context and 'source_id' in context:
|
||||
@ -504,6 +524,8 @@ class LaunchInstance(workflows.Workflow):
|
||||
else:
|
||||
nics = None
|
||||
|
||||
avail_zone = context.get('availability_zone', None)
|
||||
|
||||
try:
|
||||
api.nova.server_create(request,
|
||||
context['name'],
|
||||
@ -514,6 +536,7 @@ class LaunchInstance(workflows.Workflow):
|
||||
context['security_group_ids'],
|
||||
dev_mapping,
|
||||
nics=nics,
|
||||
availability_zone=avail_zone,
|
||||
instance_count=int(context['count']),
|
||||
admin_pass=context['admin_pass'])
|
||||
return True
|
||||
|
@ -21,7 +21,8 @@ from novaclient.v1_1 import (flavors, keypairs, servers, volumes,
|
||||
floating_ips, usage, certs,
|
||||
volume_snapshots as vol_snaps,
|
||||
security_group_rules as rules,
|
||||
security_groups as sec_groups)
|
||||
security_groups as sec_groups,
|
||||
availability_zones)
|
||||
|
||||
from openstack_dashboard.api.base import Quota, QuotaSet as QuotaSetWrapper
|
||||
from openstack_dashboard.api.nova import FloatingIp as NetFloatingIp
|
||||
@ -153,6 +154,7 @@ def data(TEST):
|
||||
TEST.certs = TestDataContainer()
|
||||
TEST.volume_snapshots = TestDataContainer()
|
||||
TEST.volume_types = TestDataContainer()
|
||||
TEST.availability_zones = TestDataContainer()
|
||||
|
||||
# Data return by novaclient.
|
||||
# It is used if API layer does data conversion.
|
||||
@ -448,3 +450,11 @@ def data(TEST):
|
||||
'data': 'certificate_data'}
|
||||
certificate = certs.Certificate(certs.CertificateManager(None), cert_data)
|
||||
TEST.certs.add(certificate)
|
||||
|
||||
# Availability Zones
|
||||
TEST.availability_zones.add(
|
||||
availability_zones.AvailabilityZone(
|
||||
availability_zones.AvailabilityZoneManager(None),
|
||||
{'zoneName': 'nova', 'zoneState': {'available': True}}
|
||||
)
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user