diff --git a/openstack_dashboard/enabled/_10_project.py b/openstack_dashboard/enabled/_10_project.py
index fd513e24b7..3111c4b1aa 100644
--- a/openstack_dashboard/enabled/_10_project.py
+++ b/openstack_dashboard/enabled/_10_project.py
@@ -37,6 +37,7 @@ ADD_JS_FILES = [
LAUNCH_INST + 'security-groups/security-groups.js',
LAUNCH_INST + 'keypair/keypair.js',
LAUNCH_INST + 'configuration/configuration.js',
+ LAUNCH_INST + 'configuration/load-edit.js',
]
ADD_JS_SPEC_FILES = [
diff --git a/openstack_dashboard/static/dashboard/launch-instance/configuration/configuration.html b/openstack_dashboard/static/dashboard/launch-instance/configuration/configuration.html
index 61eb09e23d..0003affdb0 100644
--- a/openstack_dashboard/static/dashboard/launch-instance/configuration/configuration.html
+++ b/openstack_dashboard/static/dashboard/launch-instance/configuration/configuration.html
@@ -1,57 +1,32 @@
-
-
{$ ::label.title $}
+
+
{$ ::config.label.title $}
-
{$ ::label.subtitle $}
+
{$ ::config.label.subtitle $}
-
-
- {$ ::label.customizationScriptSource $}
-
-
-
-
-
-
-
- {$ ::label.customizationScript $}
-
-
-
-
-
- {$ ::label.scriptFile $}
-
-
-
-
-
-
-
- {$ ::label.configurationDrive $}
-
-
+
+
- {$ ::label.diskPartition $}
+ {$ ::config.label.diskPartition $}
+ ng-options="option.value as option.text for option in config.diskConfigOptions">
+
+
+
+
+ {$ ::config.label.configurationDrive $}
+
+
+
diff --git a/openstack_dashboard/static/dashboard/launch-instance/configuration/configuration.js b/openstack_dashboard/static/dashboard/launch-instance/configuration/configuration.js
index 1cb981515c..f898cec0e4 100644
--- a/openstack_dashboard/static/dashboard/launch-instance/configuration/configuration.js
+++ b/openstack_dashboard/static/dashboard/launch-instance/configuration/configuration.js
@@ -1,44 +1,93 @@
(function () {
'use strict';
+ var MAX_SCRIPT_SIZE = 16 * 1024,
+ DEFAULT_CONFIG_DRIVE = false,
+ DEFAULT_USER_DATA = '',
+ DEFAULT_DISK_CONFIG = 'AUTO';
+
+ /**
+ * @ngdoc overview
+ * @name hz.dashboard.launch-instance
+ * @description
+ *
+ * # hz.dashboard.launch-instance
+ *
+ * The `hz.dashboard.launch-instance` module allows a user
+ * to launch an instance via the multi-step wizard framework
+ *
+ */
var module = angular.module('hz.dashboard.launch-instance');
+ /**
+ * @ngdoc controller
+ * @name LaunchInstanceConfigurationCtrl
+ * @description
+ * The `LaunchInstanceConfigurationCtrl` controller is responsible for
+ * setting the following instance properties:
+ *
+ * @property {string} user_data, default to empty string.
+ * The maximum size of user_data is 16 * 1024.
+ * @property {string} disk_config, default to `AUTO`.
+ * @property {boolean} config_drive, default to false.
+ */
module.controller('LaunchInstanceConfigurationCtrl', [
'$scope',
+ '$element',
+ '$timeout',
+ 'wizardEvents',
LaunchInstanceConfigurationCtrl
]);
- module.controller('LaunchInstanceConfigurationHelpCtrl', [
- LaunchInstanceConfigurationHelpCtrl
- ]);
+ function LaunchInstanceConfigurationCtrl(
+ $scope,
+ $element,
+ $timeout,
+ wizardEvents) {
- function LaunchInstanceConfigurationCtrl($scope) {
- $scope.label = {
+ var config = this,
+ newInstanceSpec = $scope.model.newInstanceSpec;
+
+ newInstanceSpec.user_data = DEFAULT_USER_DATA;
+ newInstanceSpec.disk_config = DEFAULT_DISK_CONFIG;
+ newInstanceSpec.config_drive = DEFAULT_CONFIG_DRIVE;
+
+ config.MAX_SCRIPT_SIZE = MAX_SCRIPT_SIZE;
+
+ config.label = {
title: gettext('Configuration'),
subtitle: gettext(''),
- customizationScriptSource: gettext('Customization Script Source'),
customizationScript: gettext('Customization Script'),
+ customizationScriptMax: gettext('(Max: 16Kb)'),
+ loadScriptFromFile: gettext('Load script from a file'),
configurationDrive: gettext('Configuration Drive'),
diskPartition: gettext('Disk Partition'),
- scriptFile: gettext('Script File')
+ scriptSize: gettext('Script size'),
+ scriptModified: gettext('Modified'),
+ scriptSizeWarningMsg: gettext('Script size > 16Kb'),
+ bytes: gettext('bytes'),
+ scriptSizeHoverWarningMsg: gettext('The maximum script size is 16Kb.')
};
- $scope.scriptSourceOptions = [
- { value: 'selected', text: gettext('Select Script Source') },
- { value: 'raw', text: gettext('Direct Input') },
- { value: 'file', text: gettext('File') }
- ];
-
- $scope.model.newInstanceSpec.script_source = $scope.scriptSourceOptions[0].value;
-
- $scope.diskConfigOptions = [
+ config.diskConfigOptions = [
{ value: 'AUTO', text: gettext('Automatic') },
{ value: 'MANUAL', text: gettext('Manual') }
];
-
- $scope.model.newInstanceSpec.disk_config = $scope.diskConfigOptions[0].value;
}
+ /**
+ * @ngdoc controller
+ * @name LaunchInstanceConfigurationHelpCtrl
+ * @description
+ * The `LaunchInstanceConfigurationHelpCtrl` controller provides functions for
+ * configuring the help text used within the configuration step of the
+ * Launch Instance Wizard.
+ *
+ */
+ module.controller('LaunchInstanceConfigurationHelpCtrl', [
+ LaunchInstanceConfigurationHelpCtrl
+ ]);
+
function LaunchInstanceConfigurationHelpCtrl() {
var ctrl = this;
@@ -49,9 +98,9 @@
ctrl.paragraphs = [
interpolate(customScriptText, customScriptMap, true),
- gettext('The
Customization Script Source field determines how the script information is delivered. Use
Direct Input if you want to type the script directly into the
Customization Script field.'),
- gettext('Check the
Configuration Drive box if you want to write metadata to a special configuration drive. When the instance boots, it attaches to the
Configuration Drive and accesses the metadata.'),
- gettext('An advanced option available when launching an instance is disk partitioning. There are two disk partition options. Selecting
Automatic resizes the disk and sets it to a single partition. Selecting
Manual allows you to create multiple partitions on the disk.')
+ gettext('Type your script directly into the Customization Script field. If your browser supports the HTML5 File API, you may choose to load your script from a file. The size of your script should not exceed 16 Kb.'),
+ gettext('An advanced option available when launching an instance is disk partitioning. There are two disk partition options. Selecting
Automatic resizes the disk and sets it to a single partition. Selecting
Manual allows you to create multiple partitions on the disk.'),
+ gettext('Check the
Configuration Drive box if you want to write metadata to a special configuration drive. When the instance boots, it attaches to the
Configuration Drive and accesses the metadata.')
];
}
diff --git a/openstack_dashboard/static/dashboard/launch-instance/configuration/configuration.scss b/openstack_dashboard/static/dashboard/launch-instance/configuration/configuration.scss
index 29aabd1884..a15dc7c886 100644
--- a/openstack_dashboard/static/dashboard/launch-instance/configuration/configuration.scss
+++ b/openstack_dashboard/static/dashboard/launch-instance/configuration/configuration.scss
@@ -1,13 +1,65 @@
-[ng-controller="LaunchInstanceConfigurationCtrl"] {
+[ng-controller="LaunchInstanceConfigurationCtrl as config"] {
- .customization-script-source select,
- .disk-partition select {
+ select {
width: 250px;
}
- .customization-script textarea {
- width: 480px;
- height: 280px;
- font-family: Menlo, Monaco, Consolas, 'Courier New';
+ textarea {
+ width: 100%;
+ height: 20em;
+ font-family: $code-font-family;
+ }
+
+ .btn-file {
+ position: relative;
+ overflow: hidden;
+
+ input[type=file] {
+ position: absolute;
+ top: 0;
+ right: 0;
+ min-width: 100%;
+ min-height: 100%;
+ font-size: 100px;
+ text-align: right;
+ filter: alpha(opacity=0);
+ opacity: 0;
+ outline: none;
+ background: white;
+ cursor: inherit;
+ display: block;
+ }
+ }
+
+ .script-modified {
+ font-width: normal;
+ font-style: italic;
+ color: #888;
+ }
+
+ .fa.invalid {
+ display: none;
+ }
+
+ .size-indicator.warning {
+ color: $WizardValidationErrorColor;
+ border: none;
+ padding: 0;
+ margin: 0;
+ border: none;
+
+ .fa.invalid {
+ display: inline;
+ color: $invalid-color;
+ cursor: pointer;
+ }
+ }
+
+ .script-file:after,
+ .disk-partition:after {
+ content: ' ';
+ display: block;
+ clear: both;
+ margin-bottom: 2.5em;
}
}
diff --git a/openstack_dashboard/static/dashboard/launch-instance/configuration/load-edit.html b/openstack_dashboard/static/dashboard/launch-instance/configuration/load-edit.html
new file mode 100644
index 0000000000..4c20ab3907
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/launch-instance/configuration/load-edit.html
@@ -0,0 +1,34 @@
+
+
+ {$ ::config.label.customizationScript $}
+
+ ({$ ::config.label.scriptModified $})
+
+
+
+
+ {$ ::config.label.scriptSize $}:
+ {$ (scriptLength || 0) | number $}
+ {$ ::config.label.bytes $}
+ {$ ::config.label.customizationScriptMax $}
+
+
+
+
+
+
+
+ {$ ::config.label.loadScriptFromFile $}
+
+
+
diff --git a/openstack_dashboard/static/dashboard/launch-instance/configuration/load-edit.js b/openstack_dashboard/static/dashboard/launch-instance/configuration/load-edit.js
new file mode 100644
index 0000000000..e6e144646e
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/launch-instance/configuration/load-edit.js
@@ -0,0 +1,92 @@
+(function () {
+ 'use strict';
+
+ angular.module('hz.dashboard.launch-instance')
+
+ .directive('loadEdit', ['dashboardBasePath', '$timeout',
+ function (path, $timeout) {
+
+ function link($scope, $element) {
+ var textarea = $element.find('textarea'),
+ fileInput = $element.find('input[type="file"]'),
+ userInput = $scope.userInput;
+
+ $scope.textContent = '';
+
+ // HTML5 file API is supported by IE10+, Chrome, FireFox and Safari (on Mac).
+ //
+ // If HTML5 file API is not supported by user's browser, remove the option
+ // to upload a script via file upload.
+ $scope.config.fileApiSupported = !!FileReader;
+
+ function onTextareaChange() {
+ $scope.$applyAsync(function () {
+ // Angular model won't provide the value of the