Merge "[Launch Instance Fix] Conditionally enable UI"
This commit is contained in:
commit
c6b2bc7e22
@ -284,7 +284,6 @@ limitations under the License.
|
|||||||
* this saved between 30 - 100 ms per request.
|
* this saved between 30 - 100 ms per request.
|
||||||
*/
|
*/
|
||||||
function NovaExtensions($cacheFactory, $q, novaAPI) {
|
function NovaExtensions($cacheFactory, $q, novaAPI) {
|
||||||
|
|
||||||
var service = {};
|
var service = {};
|
||||||
service.cache = $cacheFactory('hz.api.novaExtensions', {capacity: 1});
|
service.cache = $cacheFactory('hz.api.novaExtensions', {capacity: 1});
|
||||||
|
|
||||||
@ -292,19 +291,35 @@ limitations under the License.
|
|||||||
return novaAPI.getExtensions({cache: service.cache})
|
return novaAPI.getExtensions({cache: service.cache})
|
||||||
.then(function (data) {
|
.then(function (data) {
|
||||||
return data.data.items;
|
return data.data.items;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
service.ifNameEnabled = function(desired, doThis) {
|
service.ifNameEnabled = function(desired) {
|
||||||
return service.get().then(function(extensions){
|
var deferred = $q.defer();
|
||||||
|
|
||||||
|
service.get().then(onDataLoaded, onDataFailure);
|
||||||
|
|
||||||
|
function onDataLoaded(extensions) {
|
||||||
if (enabled(extensions, 'name', desired)) {
|
if (enabled(extensions, 'name', desired)) {
|
||||||
return $q.when(doThis());
|
deferred.resolve();
|
||||||
|
} else {
|
||||||
|
deferred.reject(interpolate(
|
||||||
|
gettext('Extension is not enabled: %(extension)s'),
|
||||||
|
{extension: desired},
|
||||||
|
true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
function onDataFailure() {
|
||||||
|
deferred.reject(gettext('Cannot get nova extension list.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This is an alias to support the extension directive default interface
|
||||||
|
service.ifEnabled = service.ifNameEnabled;
|
||||||
|
|
||||||
function enabled(resources, key, desired) {
|
function enabled(resources, key, desired) {
|
||||||
if(resources) {
|
if(resources) {
|
||||||
return resources.some(function (resource) {
|
return resources.some(function (resource) {
|
||||||
|
@ -28,6 +28,7 @@ LAUNCH_INST = 'dashboard/launch-instance/'
|
|||||||
ADD_JS_FILES = [
|
ADD_JS_FILES = [
|
||||||
'dashboard/dashboard.module.js',
|
'dashboard/dashboard.module.js',
|
||||||
'dashboard/workflow/workflow.js',
|
'dashboard/workflow/workflow.js',
|
||||||
|
'dashboard/cloud-services/cloud-services.js',
|
||||||
LAUNCH_INST + 'launch-instance.js',
|
LAUNCH_INST + 'launch-instance.js',
|
||||||
LAUNCH_INST + 'launch-instance.model.js',
|
LAUNCH_INST + 'launch-instance.model.js',
|
||||||
LAUNCH_INST + 'source/source.js',
|
LAUNCH_INST + 'source/source.js',
|
||||||
@ -43,6 +44,7 @@ ADD_JS_FILES = [
|
|||||||
ADD_JS_SPEC_FILES = [
|
ADD_JS_SPEC_FILES = [
|
||||||
'dashboard/dashboard.module.spec.js',
|
'dashboard/dashboard.module.spec.js',
|
||||||
'dashboard/workflow/workflow.spec.js',
|
'dashboard/workflow/workflow.spec.js',
|
||||||
|
'dashboard/cloud-services/cloud-services.spec.js',
|
||||||
LAUNCH_INST + 'launch-instance.spec.js',
|
LAUNCH_INST + 'launch-instance.spec.js',
|
||||||
LAUNCH_INST + 'launch-instance.model.spec.js',
|
LAUNCH_INST + 'launch-instance.model.spec.js',
|
||||||
LAUNCH_INST + 'source/source.spec.js',
|
LAUNCH_INST + 'source/source.spec.js',
|
||||||
|
@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var fromJson = angular.fromJson,
|
||||||
|
isArray = angular.isArray;
|
||||||
|
|
||||||
|
angular.module('hz.dashboard')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc factory
|
||||||
|
* @name hz.dashboard:factory:cloudServices
|
||||||
|
* @module hz.dashboard
|
||||||
|
* @kind hash table
|
||||||
|
* @description
|
||||||
|
*
|
||||||
|
* Provides a hash table contains all the cloud services so that:
|
||||||
|
*
|
||||||
|
* 1) Easy to inject all the services since they are injected with one dependency.
|
||||||
|
* 2) Provides a way to look up a service by name programmatically.
|
||||||
|
*
|
||||||
|
* The use of this is currently limited to existing API services. Use at
|
||||||
|
* your own risk for extensibility purposes at this time. The API will
|
||||||
|
* be evolving in the coming release and backward compatibility is not
|
||||||
|
* guaranteed. This also makes no guarantee that the back-end service
|
||||||
|
* is actually enabled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.factory('cloudServices', [
|
||||||
|
'cinderAPI',
|
||||||
|
'glanceAPI',
|
||||||
|
'keystoneAPI',
|
||||||
|
'neutronAPI',
|
||||||
|
'novaAPI',
|
||||||
|
'novaExtensions',
|
||||||
|
'securityGroup',
|
||||||
|
'serviceCatalog',
|
||||||
|
|
||||||
|
function (cinderAPI,
|
||||||
|
glanceAPI,
|
||||||
|
keystoneAPI,
|
||||||
|
neutronAPI,
|
||||||
|
novaAPI,
|
||||||
|
novaExtensions,
|
||||||
|
securityGroup,
|
||||||
|
serviceCatalog) {
|
||||||
|
|
||||||
|
return {
|
||||||
|
cinder: cinderAPI,
|
||||||
|
glance: glanceAPI,
|
||||||
|
keystone: keystoneAPI,
|
||||||
|
neutron: neutronAPI,
|
||||||
|
nova: novaAPI,
|
||||||
|
novaExtensions: novaExtensions,
|
||||||
|
securityGroup: securityGroup,
|
||||||
|
serviceCatalog: serviceCatalog
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc factory
|
||||||
|
* @name hz.dashboard:factory:ifExtensionsEnabled
|
||||||
|
* @module hz.dashboard
|
||||||
|
* @kind function
|
||||||
|
* @description
|
||||||
|
*
|
||||||
|
* Check to see if all the listed extensions are enabled on a certain service,
|
||||||
|
* which is described by the service name.
|
||||||
|
*
|
||||||
|
* This is an asynchronous operation.
|
||||||
|
*
|
||||||
|
* @param String serviceName The name of the service, e.g. `novaExtensions`.
|
||||||
|
* @param Array<String> extensions A list of extension's names.
|
||||||
|
* @return Promise the promise of the deferred task that gets resolved
|
||||||
|
* when all the sub-tasks are resolved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.factory('ifExtensionsEnabled', ['$q', 'cloudServices',
|
||||||
|
function ($q, cloudServices) {
|
||||||
|
return function ifExtensionsEnabled(serviceName, extensions) {
|
||||||
|
return $q.all(
|
||||||
|
extensions.map(function (extension) {
|
||||||
|
return cloudServices[serviceName].ifEnabled(extension);
|
||||||
|
})
|
||||||
|
);//return
|
||||||
|
};//return
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc factory
|
||||||
|
* @name hz.dashboard:factory:createDirectiveSpec
|
||||||
|
* @module hz.dashboard
|
||||||
|
* @kind function
|
||||||
|
* @description
|
||||||
|
*
|
||||||
|
* A normalized function that can create a directive specification object
|
||||||
|
* based on `serviceName`.
|
||||||
|
*
|
||||||
|
* @param String serviceName The name of the service, e.g. `novaExtensions`.
|
||||||
|
* @return Object a directive specification object that can be used to
|
||||||
|
* create an angular directive.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.factory('createDirectiveSpec', ['ifExtensionsEnabled',
|
||||||
|
function (ifExtensionsEnabled) {
|
||||||
|
return function createDirectiveSpec(serviceName) {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
transclude: true,
|
||||||
|
link: function link(scope, element, attrs, ctrl, transclude) {
|
||||||
|
element.addClass('ng-hide');
|
||||||
|
var extensions = fromJson(attrs.requiredExtensions);
|
||||||
|
if (isArray(extensions)) {
|
||||||
|
ifExtensionsEnabled(serviceName, extensions).then(
|
||||||
|
function () {
|
||||||
|
element.removeClass('ng-hide');
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
element.remove();
|
||||||
|
}
|
||||||
|
);//if-then
|
||||||
|
}
|
||||||
|
transclude(scope, function (clone) {
|
||||||
|
element.append(clone);
|
||||||
|
});
|
||||||
|
}//link
|
||||||
|
};//return
|
||||||
|
};//return
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc directive
|
||||||
|
* @name hz.dashboard:directive:novaExtension
|
||||||
|
* @module hz.dashboard
|
||||||
|
* @description
|
||||||
|
*
|
||||||
|
* This is to enable specifying conditional UI in a declarative way.
|
||||||
|
* Some UI components should be showing only when some certain extensions
|
||||||
|
* are enabled on `novaExtensions` service.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
```html
|
||||||
|
<nova-extension required-extensions='["config_drive"]'>
|
||||||
|
<div class="checkbox customization-script-source">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox"
|
||||||
|
ng-model="model.newInstanceSpec.config_drive">
|
||||||
|
{$ ::label.configurationDrive $}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</nova-extension>
|
||||||
|
|
||||||
|
<nova-extension required-extensions='["disk_config"]'>
|
||||||
|
<div class="form-group disk-partition">
|
||||||
|
<label for="launch-instance-disk-partition">
|
||||||
|
{$ ::label.diskPartition $}
|
||||||
|
</label>
|
||||||
|
<select class="form-control"
|
||||||
|
id="launch-instance-disk-partition"
|
||||||
|
ng-model="model.newInstanceSpec.disk_config"
|
||||||
|
ng-options="option.value as option.text for option in diskConfigOptions">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</nova-extension>
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
|
||||||
|
.directive('novaExtension', ['createDirectiveSpec',
|
||||||
|
function (createDirectiveSpec) {
|
||||||
|
return createDirectiveSpec('novaExtensions');
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
;})();
|
@ -0,0 +1,257 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('hz.dashboard', function () {
|
||||||
|
|
||||||
|
//
|
||||||
|
// factory:cloudServices
|
||||||
|
//
|
||||||
|
|
||||||
|
describe('factory:cloudServices', function () {
|
||||||
|
var cloudServices;
|
||||||
|
|
||||||
|
beforeEach(module('hz.dashboard', function ($provide) {
|
||||||
|
$provide.value('cinderAPI', {});
|
||||||
|
$provide.value('glanceAPI', {});
|
||||||
|
$provide.value('keystoneAPI', {});
|
||||||
|
$provide.value('neutronAPI', {});
|
||||||
|
$provide.value('novaAPI', {});
|
||||||
|
$provide.value('novaExtensions', {});
|
||||||
|
$provide.value('securityGroup', {});
|
||||||
|
$provide.value('serviceCatalog', {});
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(inject(function ($injector) {
|
||||||
|
cloudServices = $injector.get('cloudServices');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should have `cloudServices` defined.', function () {
|
||||||
|
expect(cloudServices).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have `cloudServices.cinder` defined.', function () {
|
||||||
|
expect(cloudServices.cinder).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have `cloudServices.glance` defined.', function () {
|
||||||
|
expect(cloudServices.glance).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have `cloudServices.keystone` defined.', function () {
|
||||||
|
expect(cloudServices.keystone).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have `cloudServices.neutron` defined.', function () {
|
||||||
|
expect(cloudServices.neutron).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have `cloudServices.nova` defined.', function () {
|
||||||
|
expect(cloudServices.nova).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have `cloudServices.novaExtensions` defined.', function () {
|
||||||
|
expect(cloudServices.novaExtensions).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// factory:ifExtensionsEnabled
|
||||||
|
//
|
||||||
|
|
||||||
|
describe('factory:ifExtensionsEnabled', function () {
|
||||||
|
var ifExtensionsEnabled,
|
||||||
|
$q,
|
||||||
|
cloudServices;
|
||||||
|
|
||||||
|
beforeEach(module('hz.dashboard', function ($provide) {
|
||||||
|
$q = {
|
||||||
|
all: function () {
|
||||||
|
return {
|
||||||
|
then: function () {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
cloudServices = {
|
||||||
|
'someService': {
|
||||||
|
ifEnabled: function () {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
spyOn(cloudServices.someService, 'ifEnabled');
|
||||||
|
spyOn($q, 'all');
|
||||||
|
|
||||||
|
$provide.value('$q', $q);
|
||||||
|
$provide.value('cloudServices', cloudServices);
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(inject(function ($injector) {
|
||||||
|
ifExtensionsEnabled = $injector.get('ifExtensionsEnabled');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should have `ifExtensionsEnabled` defined as a function.', function () {
|
||||||
|
expect(ifExtensionsEnabled).toBeDefined();
|
||||||
|
expect(angular.isFunction(ifExtensionsEnabled)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call $q.all() and someService.ifEnabled() when invoking ifExtensionsEnabled().', function () {
|
||||||
|
var extensions = ['ext1', 'ext2'];
|
||||||
|
ifExtensionsEnabled('someService', extensions);
|
||||||
|
expect($q.all).toHaveBeenCalled();
|
||||||
|
expect(cloudServices.someService.ifEnabled).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not throw when passing in an empty extensions list.', function () {
|
||||||
|
expect(function () {
|
||||||
|
ifExtensionsEnabled('someService', []);
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw when extensions is null or undefined or not an array', function () {
|
||||||
|
expect(function () {
|
||||||
|
ifExtensionsEnabled('someService', null);
|
||||||
|
}).toThrow();
|
||||||
|
|
||||||
|
expect(function () {
|
||||||
|
ifExtensionsEnabled('someService');
|
||||||
|
}).toThrow();
|
||||||
|
|
||||||
|
expect(function () {
|
||||||
|
ifExtensionsEnabled('123');
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not throw when the provided serviceName is not a key in the services hash table', function () {
|
||||||
|
expect(function () {
|
||||||
|
ifExtensionsEnabled('invlidServiceName', []);
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// factory:createDirectiveSpec
|
||||||
|
//
|
||||||
|
|
||||||
|
describe('factory:createDirectiveSpec', function () {
|
||||||
|
var createDirectiveSpec,
|
||||||
|
ifExtensionsEnabled;
|
||||||
|
|
||||||
|
beforeEach(module('hz.dashboard', function ($provide) {
|
||||||
|
ifExtensionsEnabled = function () {
|
||||||
|
return {
|
||||||
|
then: function (successCallback, errorCallback) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
$provide.value('ifExtensionsEnabled', ifExtensionsEnabled);
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(inject(function ($injector) {
|
||||||
|
createDirectiveSpec = $injector.get('createDirectiveSpec');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should have `createDirectiveSpec` defined as a function.', function () {
|
||||||
|
expect(createDirectiveSpec).toBeDefined();
|
||||||
|
expect(angular.isFunction(createDirectiveSpec)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When called, the returned object', function () {
|
||||||
|
var directiveSpec;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
directiveSpec = createDirectiveSpec('someService');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined.', function () {
|
||||||
|
expect(directiveSpec).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have "restrict" property "E".', function () {
|
||||||
|
expect(directiveSpec.restrict).toBe('E');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have "transclude" property true.', function () {
|
||||||
|
expect(directiveSpec.transclude).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have "link" property as a function.', function () {
|
||||||
|
expect(directiveSpec.link).toEqual(jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// directive:novaExtension
|
||||||
|
//
|
||||||
|
|
||||||
|
describe('directive:novaExtension', function () {
|
||||||
|
var $timeout,
|
||||||
|
$scope,
|
||||||
|
html = [
|
||||||
|
'<nova-extension required-extensions=\'["config_drive"]\'>',
|
||||||
|
'<div class="child-element">',
|
||||||
|
'</div>',
|
||||||
|
'</nova-extension>'
|
||||||
|
].join(''),
|
||||||
|
element;
|
||||||
|
|
||||||
|
beforeEach(module('hz.dashboard', function ($provide) {
|
||||||
|
$provide.value('ifExtensionsEnabled', function () {
|
||||||
|
return {
|
||||||
|
then: function (successCallback, errorCallback) {
|
||||||
|
$timeout(successCallback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(inject(function ($injector) {
|
||||||
|
var $compile = $injector.get('$compile');
|
||||||
|
$scope = $injector.get('$rootScope').$new();
|
||||||
|
$timeout = $injector.get('$timeout');
|
||||||
|
element = $compile(html)($scope);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should be compiled.', function () {
|
||||||
|
expect(element.hasClass('ng-scope')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have class name `ng-hide` by default.', function () {
|
||||||
|
expect(element.hasClass('ng-hide')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have no class name `ng-hide` after an asyncs callback.', function () {
|
||||||
|
$timeout(function () {
|
||||||
|
expect(element.hasClass('ng-hide')).toBe(false);
|
||||||
|
});
|
||||||
|
$timeout.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have the right child element.', function () {
|
||||||
|
expect(element.children().first().hasClass('child-element')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
;})();
|
@ -9,6 +9,7 @@
|
|||||||
key="user_data">
|
key="user_data">
|
||||||
</load-edit>
|
</load-edit>
|
||||||
|
|
||||||
|
<nova-extension required-extensions='["DiskConfig"]'>
|
||||||
<div class="form-group disk-partition">
|
<div class="form-group disk-partition">
|
||||||
<label for="launch-instance-disk-partition">
|
<label for="launch-instance-disk-partition">
|
||||||
{$ ::config.label.diskPartition $}
|
{$ ::config.label.diskPartition $}
|
||||||
@ -19,14 +20,17 @@
|
|||||||
ng-options="option.value as option.text for option in config.diskConfigOptions">
|
ng-options="option.value as option.text for option in config.diskConfigOptions">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
</nova-extension>
|
||||||
|
|
||||||
<div class="checkbox">
|
<nova-extension required-extensions='["ConfigDrive"]'>
|
||||||
|
<div class="checkbox customization-script-source">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
ng-model="model.newInstanceSpec.config_drive">
|
ng-model="model.newInstanceSpec.config_drive">
|
||||||
{$ ::config.label.configurationDrive $}
|
{$ ::config.label.configurationDrive $}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
</nova-extension>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -387,9 +387,8 @@
|
|||||||
volumePromises.push(cinderAPI.getVolumeSnapshots({ status: 'available' }).then(onGetVolumeSnapshots));
|
volumePromises.push(cinderAPI.getVolumeSnapshots({ status: 'available' }).then(onGetVolumeSnapshots));
|
||||||
|
|
||||||
// Can only boot image to volume if the Nova extension is enabled.
|
// Can only boot image to volume if the Nova extension is enabled.
|
||||||
novaExtensions.ifNameEnabled('BlockDeviceMappingV2Boot', function(){
|
novaExtensions.ifNameEnabled('BlockDeviceMappingV2Boot')
|
||||||
model.allowCreateVolumeFromImage = true;
|
.then(function(){ model.allowCreateVolumeFromImage = true; });
|
||||||
});
|
|
||||||
|
|
||||||
return $q.all(volumePromises);
|
return $q.all(volumePromises);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user