Allow setting default value for config_drive

This adds a setting that can be used to specify the default value
for the Configuration Drive option when launching an instance.

Closes-Bug: #1537106
Change-Id: If402d3331158b462bece27fa6fce2bdb7f6a4a2e
This commit is contained in:
Justin Pomeroy 2016-01-22 12:28:10 -06:00
parent bbf163cb2b
commit 73bb9a5943
10 changed files with 101 additions and 39 deletions

View File

@ -508,6 +508,22 @@ This setting can be used in the case where a separate panel is used for
managing a custom property or if a certain custom property should never be managing a custom property or if a certain custom property should never be
edited. edited.
``LAUNCH_INSTANCE_DEFAULTS``
----------------------------
.. versionadded:: 9.0.0(Mitaka)
Default::
{
"config_drive": False
}
A dictionary of settings which can be used to provide the default values for
properties found in the Launch Instance modal.
The ``config_drive`` setting specifies the default value for the Configuration
Drive property.
``MESSAGES_PATH`` ``MESSAGES_PATH``
----------------- -----------------
@ -529,7 +545,6 @@ data and must have a .json file extension. For example::
Possible values for level are: success, info, warning and error. Possible values for level are: success, info, warning and error.
``OPENSTACK_API_VERSIONS`` ``OPENSTACK_API_VERSIONS``
-------------------------- --------------------------

View File

@ -256,7 +256,7 @@ setup.py
pbr=True) pbr=True)
setup.cfg setup.cfg
-------- ---------
:: ::
[metadata] [metadata]

View File

@ -1477,6 +1477,7 @@ class InstanceTests(helpers.TestCase):
only_one_network=False, only_one_network=False,
disk_config=True, disk_config=True,
config_drive=True, config_drive=True,
config_drive_default=False,
test_with_profile=False): test_with_profile=False):
image = self.images.first() image = self.images.first()
@ -1619,6 +1620,10 @@ class InstanceTests(helpers.TestCase):
else: else:
self.assertNotContains(res, config_drive_field_label) self.assertNotContains(res, config_drive_field_label)
step = workflow.get_step("setadvancedaction")
self.assertEqual(step.action.initial['config_drive'],
config_drive_default)
@django.test.utils.override_settings( @django.test.utils.override_settings(
OPENSTACK_HYPERVISOR_FEATURES={'can_set_password': False}) OPENSTACK_HYPERVISOR_FEATURES={'can_set_password': False})
def test_launch_instance_get_without_password(self): def test_launch_instance_get_without_password(self):
@ -1634,6 +1639,11 @@ class InstanceTests(helpers.TestCase):
self._test_launch_form_instance_requirement_error(image, flavor, self._test_launch_form_instance_requirement_error(image, flavor,
keypair_require=True) keypair_require=True)
@django.test.utils.override_settings(
LAUNCH_INSTANCE_DEFAULTS={'config_drive': True})
def test_launch_instance_get_with_config_drive_default(self):
self.test_launch_instance_get(config_drive_default=True)
def test_launch_instance_get_no_block_device_mapping_v2_supported(self): def test_launch_instance_get_no_block_device_mapping_v2_supported(self):
self.test_launch_instance_get(block_device_mapping_v2=False) self.test_launch_instance_get(block_device_mapping_v2=False)

View File

@ -22,6 +22,7 @@ Views for managing instances.
from collections import OrderedDict from collections import OrderedDict
import logging import logging
from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse_lazy
from django import http from django import http
@ -147,6 +148,8 @@ class LaunchInstanceView(workflows.WorkflowView):
initial = super(LaunchInstanceView, self).get_initial() initial = super(LaunchInstanceView, self).get_initial()
initial['project_id'] = self.request.user.tenant_id initial['project_id'] = self.request.user.tenant_id
initial['user_id'] = self.request.user.id initial['user_id'] = self.request.user.id
defaults = getattr(settings, 'LAUNCH_INSTANCE_DEFAULTS', {})
initial['config_drive'] = defaults.get('config_drive', False)
return initial return initial

View File

@ -15,18 +15,11 @@
'use strict'; 'use strict';
var MAX_SCRIPT_SIZE = 16 * 1024; var MAX_SCRIPT_SIZE = 16 * 1024;
var DEFAULT_CONFIG_DRIVE = false;
var DEFAULT_USER_DATA = '';
var DEFAULT_DISK_CONFIG = 'AUTO';
angular angular
.module('horizon.dashboard.project.workflow.launch-instance') .module('horizon.dashboard.project.workflow.launch-instance')
.controller('LaunchInstanceConfigurationController', LaunchInstanceConfigurationController); .controller('LaunchInstanceConfigurationController', LaunchInstanceConfigurationController);
LaunchInstanceConfigurationController.$inject = [
'$scope'
];
/** /**
* @ngdoc controller * @ngdoc controller
* @name LaunchInstanceConfigurationController * @name LaunchInstanceConfigurationController
@ -39,15 +32,9 @@
* @property {string} disk_config, default to `AUTO`. * @property {string} disk_config, default to `AUTO`.
* @property {boolean} config_drive, default to false. * @property {boolean} config_drive, default to false.
*/ */
function LaunchInstanceConfigurationController($scope) { function LaunchInstanceConfigurationController() {
var ctrl = this; var ctrl = this;
var newInstanceSpec = $scope.model.newInstanceSpec;
newInstanceSpec.user_data = DEFAULT_USER_DATA;
newInstanceSpec.disk_config = DEFAULT_DISK_CONFIG;
newInstanceSpec.config_drive = DEFAULT_CONFIG_DRIVE;
ctrl.MAX_SCRIPT_SIZE = MAX_SCRIPT_SIZE; ctrl.MAX_SCRIPT_SIZE = MAX_SCRIPT_SIZE;
ctrl.diskConfigOptions = [ ctrl.diskConfigOptions = [

View File

@ -19,20 +19,12 @@
describe('Launch Instance Configuration Step', function() { describe('Launch Instance Configuration Step', function() {
describe('LaunchInstanceConfigurationController', function() { describe('LaunchInstanceConfigurationController', function() {
var scope, ctrl; var ctrl;
beforeEach(module('horizon.dashboard.project.workflow.launch-instance')); beforeEach(module('horizon.dashboard.project.workflow.launch-instance'));
beforeEach(inject(function($controller) { beforeEach(inject(function($controller) {
scope = { ctrl = $controller('LaunchInstanceConfigurationController');
model: {
newInstanceSpec: {}
}
};
ctrl = $controller('LaunchInstanceConfigurationController', {
$scope: scope
});
})); }));
it('has correct disk configuration options', function() { it('has correct disk configuration options', function() {
@ -43,16 +35,8 @@
expect(vals).toContain('MANUAL'); expect(vals).toContain('MANUAL');
}); });
it('defaults the disk configuration to "AUTO"', function() { it('sets the user data max script size', function() {
expect(scope.model.newInstanceSpec.disk_config).toBe('AUTO'); expect(ctrl.MAX_SCRIPT_SIZE).toBe(16 * 1024);
});
it('defaults the config_drive configuration to false', function() {
expect(scope.model.newInstanceSpec.config_drive).toBe(false);
});
it('defaults the user_data configuration to ""', function() {
expect(scope.model.newInstanceSpec.user_data).toBe('');
}); });
}); });

View File

@ -26,6 +26,7 @@
'horizon.app.core.openstack-service-api.novaExtensions', 'horizon.app.core.openstack-service-api.novaExtensions',
'horizon.app.core.openstack-service-api.security-group', 'horizon.app.core.openstack-service-api.security-group',
'horizon.app.core.openstack-service-api.serviceCatalog', 'horizon.app.core.openstack-service-api.serviceCatalog',
'horizon.app.core.openstack-service-api.settings',
'horizon.framework.widgets.toast.service' 'horizon.framework.widgets.toast.service'
]; ];
@ -51,6 +52,7 @@
novaExtensions, novaExtensions,
securityGroup, securityGroup,
serviceCatalog, serviceCatalog,
settings,
toast toast
) { ) {
@ -204,7 +206,8 @@
novaAPI.getLimits().then(onGetNovaLimits, noop), novaAPI.getLimits().then(onGetNovaLimits, noop),
securityGroup.query().then(onGetSecurityGroups, noop), securityGroup.query().then(onGetSecurityGroups, noop),
serviceCatalog.ifTypeEnabled('network').then(getNetworks, noop), serviceCatalog.ifTypeEnabled('network').then(getNetworks, noop),
serviceCatalog.ifTypeEnabled('volume').then(getVolumes, noop) serviceCatalog.ifTypeEnabled('volume').then(getVolumes, noop),
settings.getSetting('LAUNCH_INSTANCE_DEFAULTS').then(setDefaultValues, noop)
]); ]);
promise.then(onInitSuccess, onInitFail); promise.then(onInitSuccess, onInitFail);
@ -227,6 +230,13 @@
model.initialized = false; model.initialized = false;
} }
function setDefaultValues(defaults) {
if (!defaults) { return; }
if ('config_drive' in defaults) {
model.newInstanceSpec.config_drive = defaults.config_drive;
}
}
/** /**
* @ngdoc method * @ngdoc method
* @name launchInstanceModel.createInstance * @name launchInstanceModel.createInstance

View File

@ -19,7 +19,7 @@
describe('Launch Instance Model', function() { describe('Launch Instance Model', function() {
describe('launchInstanceModel Factory', function() { describe('launchInstanceModel Factory', function() {
var model, scope, $q; var model, scope, settings, $q;
var cinderEnabled = false; var cinderEnabled = false;
var neutronEnabled = false; var neutronEnabled = false;
var novaExtensionsEnabled = false; var novaExtensionsEnabled = false;
@ -53,6 +53,14 @@
} }
}); });
beforeEach(function() {
settings = {
LAUNCH_INSTANCE_DEFAULTS: {
config_drive: false
}
};
});
$provide.value('horizon.app.core.openstack-service-api.nova', { $provide.value('horizon.app.core.openstack-service-api.nova', {
createServer: function(finalSpec) { createServer: function(finalSpec) {
return { return {
@ -175,6 +183,16 @@
} }
}); });
$provide.value('horizon.app.core.openstack-service-api.settings', {
getSetting: function(setting) {
var deferred = $q.defer();
deferred.resolve(settings[setting]);
return deferred.promise;
}
});
$provide.value('horizon.framework.widgets.toast.service', { $provide.value('horizon.framework.widgets.toast.service', {
add: function() {} add: function() {}
}); });
@ -310,6 +328,29 @@
expect(model.allowCreateVolumeFromImage).toBe(false); expect(model.allowCreateVolumeFromImage).toBe(false);
}); });
it('should default config_drive to false', function() {
model.initialize(true);
scope.$apply();
expect(model.newInstanceSpec.config_drive).toBe(false);
});
it('should default config_drive to false if setting not provided', function() {
delete settings.LAUNCH_INSTANCE_DEFAULTS;
model.initialize(true);
scope.$apply();
expect(model.newInstanceSpec.config_drive).toBe(false);
});
it('should default config_drive to true based on setting', function() {
settings.LAUNCH_INSTANCE_DEFAULTS.config_drive = true;
model.initialize(true);
scope.$apply();
expect(model.newInstanceSpec.config_drive).toBe(true);
});
}); });
describe('Post Initialization Model - Initializing', function() { describe('Post Initialization Model - Initializing', function() {

View File

@ -228,6 +228,12 @@ OPENSTACK_KEYSTONE_BACKEND = {
#LAUNCH_INSTANCE_LEGACY_ENABLED = True #LAUNCH_INSTANCE_LEGACY_ENABLED = True
#LAUNCH_INSTANCE_NG_ENABLED = False #LAUNCH_INSTANCE_NG_ENABLED = False
# A dictionary of settings which can be used to provide the default values for
# properties found in the Launch Instance modal.
#LAUNCH_INSTANCE_DEFAULTS = {
# 'config_drive': False
#}
# The Xen Hypervisor has the ability to set the mount point for volumes # The Xen Hypervisor has the ability to set the mount point for volumes
# attached to instances (other Hypervisors currently do not). Setting # attached to instances (other Hypervisors currently do not). Setting
# can_set_mount_point to True will add the option to set the mount point # can_set_mount_point to True will add the option to set the mount point
@ -687,7 +693,8 @@ SECURITY_GROUP_RULES = {
# the enabled panel configuration. # the enabled panel configuration.
# You should not add settings to this list for out of tree extensions. # You should not add settings to this list for out of tree extensions.
# See: https://wiki.openstack.org/wiki/Horizon/RESTAPI # See: https://wiki.openstack.org/wiki/Horizon/RESTAPI
REST_API_REQUIRED_SETTINGS = ['OPENSTACK_HYPERVISOR_FEATURES'] REST_API_REQUIRED_SETTINGS = ['OPENSTACK_HYPERVISOR_FEATURES',
'LAUNCH_INSTANCE_DEFAULTS']
# Additional settings can be made available to the client side for # Additional settings can be made available to the client side for
# extensibility by specifying them in REST_API_ADDITIONAL_SETTINGS # extensibility by specifying them in REST_API_ADDITIONAL_SETTINGS

View File

@ -0,0 +1,5 @@
---
features:
- Added the LAUNCH_INSTANCE_DEFAULTS setting which allows specifying default
values for the Launch Instance workflow. Initially only the Configuration
Drive property is supported.