Add default_availability_zone for VM creation

Add the LAUNCH_INSTANCE_DEFAULTS.default_availability_zone settings in
VM creation dashboard in order to let administrator select a default
availability zone instead of a random one when many are available.

Co-Authored-By: Akihiro Motoki <amotoki@gmail.com>
Change-Id: I297ff7f3c8e725c24c7f7687786c784f61f5d4e2
This commit is contained in:
David Hill 2020-09-09 13:38:43 -04:00 committed by Akihiro Motoki
parent 73f4469faa
commit fc8603a499
5 changed files with 107 additions and 5 deletions

View File

@ -2125,6 +2125,10 @@ LAUNCH_INSTANCE_DEFAULTS
Added the ``hide_create_volume`` option.
.. versionchanged:: 19.1.0(Wallaby)
Added the ``default_availability_zone`` option.
Default:
.. code-block:: python
@ -2138,6 +2142,7 @@ Default:
"disable_volume": False,
"disable_volume_snapshot": False,
"enable_scheduler_hints": True,
"default_availability_zone": "Any",
}
A dictionary of settings which can be used to provide the default values for
@ -2224,6 +2229,22 @@ Default: ``True``
This setting specifies whether or not Scheduler Hints can be provided when
launching an instance.
default_availability_zone
#########################
.. versionadded:: 19.1.0(Wallaby)
Default: ``Any``
This setting allows an administrator to specify a default availability zone
for a new server creation. The valid value is ``Any`` or availability zone
list. If ``Any`` is specified, the default availability zone is decided by
the nova scheduler. If one of availability zones is specified, the specified
availability zone is used as the default availability zone. If a value
specified in this setting is not found in the availability zone list,
the setting will be ignored and the behavior will be same as when ``Any``
is specified.
LAUNCH_INSTANCE_LEGACY_ENABLED
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -129,6 +129,7 @@
* cloud service properties, they should be READ-ONLY to all UI controllers
*/
default_availability_zone: 'Any',
availabilityZones: [],
flavors: [],
allowedBootSources: [],
@ -250,6 +251,7 @@
});
promise = $q.all([
launchInstanceDefaults.then(setDefaultValues, noop),
novaAPI.getAvailabilityZones().then(onGetAvailabilityZones)
.finally(onGetAvailabilityZonesComplete),
novaAPI.getFlavors({
@ -261,7 +263,6 @@
securityGroup.query().then(onGetSecurityGroups, noop),
serviceCatalog.ifTypeEnabled('network').then(getNetworks, noop),
launchInstanceDefaults.then(addImageSourcesIfEnabled, noop),
launchInstanceDefaults.then(setDefaultValues, noop),
launchInstanceDefaults.then(addVolumeSourcesIfEnabled, noop)
]);
@ -300,6 +301,9 @@
if ('hide_create_volume' in defaults) {
model.newInstanceSpec.hide_create_volume = defaults.hide_create_volume;
}
if ('default_availability_zone' in defaults) {
model.default_availability_zone = defaults.default_availability_zone;
}
}
/**
@ -365,13 +369,33 @@
if (model.availabilityZones.length === 1) {
model.newInstanceSpec.availability_zone = model.availabilityZones[0].value;
} else if (model.availabilityZones.length > 1) {
// There are 2 or more; allow ability for nova scheduler to pick,
// and make that the default.
// There are 2 or more; allow ability for nova scheduler to pick any AZ
model.availabilityZones.unshift({
label: gettext("Any Availability Zone"),
value: ""
});
model.newInstanceSpec.availability_zone = model.availabilityZones[0].value;
// if default_availability_zone is Any, pick the first one in the list
if (model.default_availability_zone === "Any") {
model.newInstanceSpec.availability_zone = model.availabilityZones[0].value;
} else {
var defaultZone = null;
for (var i = 0; i < model.availabilityZones.length; i++) {
if (model.availabilityZones[i].value === model.default_availability_zone) {
defaultZone = model.availabilityZones[i];
break;
}
}
if (defaultZone !== null) {
// if default_availability_zone is set, use that AZ by default.
model.newInstanceSpec.availability_zone = model.default_availability_zone;
// Add "(default)" suffix to the default AZ.
defaultZone.label = interpolate(gettext("%s (default)"), [defaultZone.value]);
} else {
// If the configured default AZ is not included in the AZ list (perhaps
// misconfiguration?), use the first one ("Any Availability Zone") by default.
model.newInstanceSpec.availability_zone = model.availabilityZones[0].value;
}
}
}
}

View File

@ -183,7 +183,8 @@
disable_image: false,
disable_instance_snapshot: false,
disable_volume: false,
disable_volume_snapshot: false
disable_volume_snapshot: false,
default_availability_zone: 'Any'
},
DEFAULT_BOOT_SOURCE: 'image'
};
@ -505,6 +506,37 @@
expect(model.newInstanceSpec.create_volume_default).toBe(false);
});
it('should default availability_zone to empty based on default', function() {
model.initialize(true);
scope.$apply();
expect(model.newInstanceSpec.availability_zone).toBe('');
});
it('should default availability_zone to empty based on setting', function() {
settings.LAUNCH_INSTANCE_DEFAULTS.default_availability_zone = 'Any';
model.initialize(true);
scope.$apply();
expect(model.newInstanceSpec.availability_zone).toBe('');
});
it('should default availability_zone based on setting', function() {
settings.LAUNCH_INSTANCE_DEFAULTS.default_availability_zone = 'zone-1';
model.initialize(true);
scope.$apply();
expect(model.newInstanceSpec.availability_zone).toEqual('zone-1');
});
it('should default AZ to empty if AZ configured is not found', function() {
settings.LAUNCH_INSTANCE_DEFAULTS.default_availability_zone = 'non-existing';
model.initialize(true);
scope.$apply();
expect(model.newInstanceSpec.availability_zone).toEqual('');
});
it('should default hide_create_volume to false if setting not provided', function() {
delete settings.LAUNCH_INSTANCE_DEFAULTS.hide_create_volume;
model.initialize(true);
@ -628,6 +660,22 @@
expect(model.allowedBootSources).toContain(INSTANCE_SNAPSHOT);
});
it('should have proper availability_zone if specific setting is missing', function() {
delete settings.LAUNCH_INSTANCE_DEFAULTS.default_availability_zone;
model.initialize(true);
scope.$apply();
expect(model.newInstanceSpec.availability_zone).toBe('');
});
it('should have proper availability_zone if settings are missing', function() {
delete settings.LAUNCH_INSTANCE_DEFAULTS;
model.initialize(true);
scope.$apply();
expect(model.newInstanceSpec.availability_zone).toBe('');
});
it('should have proper allowedBootSources if settings are missing', function() {
delete settings.LAUNCH_INSTANCE_DEFAULTS;
model.initialize(true);

View File

@ -265,6 +265,7 @@ LAUNCH_INSTANCE_DEFAULTS = {
'disable_volume': False,
'disable_volume_snapshot': False,
'enable_scheduler_hints': True,
'default_availability_zone': 'Any',
}
# The absolute path to the directory where message files are collected.

View File

@ -0,0 +1,8 @@
---
features:
- |
When multiple availability zones are available, the default behavior is to
allow the scheduler to spawn a VM in any of them.
The new setting ``LAUNCH_INSTANCE_DEFAULTS.default_availability_zone``
allows an administrator to specify a default static availability zone
for new VM creation.