diff --git a/app/helpers/vm_infra_helper.rb b/app/helpers/vm_infra_helper.rb index 60c7442cfc9..034beaa2cf5 100644 --- a/app/helpers/vm_infra_helper.rb +++ b/app/helpers/vm_infra_helper.rb @@ -1,4 +1,37 @@ module VmInfraHelper include VmHelper include DataTableHelper + + # rubocop:disable Rails/HelperInstanceVariable + def reconfigure_form_data(vm = @reconfigitems.first) + { + :recordId => @reconfigitems.collect(&:id), + :requestId => @request_id || 'new', + :roles => { + :allowMemoryChange => role_allows?(:feature => 'vm_reconfigure_memory'), + :allowCpuChange => role_allows?(:feature => 'vm_reconfigure_cpu'), + :allowDiskChange => role_allows?(:feature => 'vm_reconfigure_disks') && item_supports?(:reconfigure_disks), + :allowDiskSizeChange => item_supports?(:reconfigure_disksize), + :allowNetworkChange => item_supports?(:reconfigure_network_adapters) && role_allows?(:feature => 'vm_reconfigure_networks'), + :allowCdromsChange => item_supports?(:reconfigure_cdroms) && role_allows?(:feature => 'vm_reconfigure_drives'), + :isVmwareInfra => vm.vendor == 'vmware' && vm.type.include?('InfraManager'), + :isVmwareCloud => vm.vendor == 'vmware' && vm.type.include?('CloudManager'), + :isRedhat => vm.vendor == 'redhat', + }, + :memory => { + :min => @reconfig_limits[:min__vm_memory], + :max => @reconfig_limits[:max__vm_memory], + :max_cpu => @reconfig_limits[:max__total_vcpus], + }, + :options => { + :controller_types => @reconfigitems.first.try(:scsi_controller_types) || [], + :vlan_options => @vlan_options || [], + :avail_adapter_names => @avail_adapter_names || [], + :host_file_options => @iso_options || [], + :socket_options => @socket_options || [], + :cores_options => @cores_options || [], + } + } + end + # rubocop:enable Rails/HelperInstanceVariable end diff --git a/app/javascript/components/miq-data-table/index.jsx b/app/javascript/components/miq-data-table/index.jsx index 403fa112e22..f5e2e29bec6 100644 --- a/app/javascript/components/miq-data-table/index.jsx +++ b/app/javascript/components/miq-data-table/index.jsx @@ -95,6 +95,7 @@ const MiqDataTable = ({ onClick={() => sortable && onSort(header)} isSortHeader={sortHeader} sortDirection={sortDirection} + className={classNames('miq-data-table-header', (header.contentButton ? 'header-button' : ''))} > {headerLabel(header.header)} diff --git a/app/javascript/components/reconfigure-vm-form/disk-form-fields.js b/app/javascript/components/reconfigure-vm-form/disk-form-fields.js new file mode 100644 index 00000000000..7385ff4b131 --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/disk-form-fields.js @@ -0,0 +1,118 @@ +import { componentTypes, validatorTypes } from '@@ddf'; +import { restructureOptions } from './helper'; +import { TYPES, getCellData, getObjectData } from './helpers/general'; + +const getSwitchData = (row, field) => (getCellData(row, field) === 'Yes'); + +const nameField = (data) => ({ + component: componentTypes.TEXT_FIELD, + id: 'name', + name: 'name', + label: __('Name'), + isReadOnly: true, + initialValue: data.form.action === TYPES.RESIZE ? getCellData(data.editingRow, 'name') : '', + hideField: data.form.action === 'add', +}); + +const sizeField = (data) => ({ + component: componentTypes.TEXT_FIELD, + id: 'size', + name: 'size', + label: __('Size'), + isRequired: true, + initialValue: data.form.action === TYPES.RESIZE ? getCellData(data.editingRow, 'size') : '', + validate: [ + { + type: 'diskMemoryCheck', + size: data.form.action === TYPES.RESIZE ? Number(getObjectData(data.editingRow.id.substring(4), data.dataTable.disks, 'orgHdSize')) + 1 : 1, + unit: data.form.action === TYPES.RESIZE ? getObjectData(data.editingRow.id.substring(4), data.dataTable.disks, 'orgHdUnit') : __('MB'), + }, + ], +}); + +const unitField = (data) => ({ + component: componentTypes.SELECT, + id: 'unit', + name: 'unit', + label: __('Unit'), + initialValue: data.form.action === TYPES.RESIZE ? getCellData(data.editingRow, 'unit') : '', + options: restructureOptions([__('GB'), __('MB')]), +}); + +const typeField = (data) => ({ + component: componentTypes.SELECT, + id: 'type', + name: 'type', + label: __('Type'), + autoFocus: true, + options: restructureOptions(['thin', 'thick']), + validate: [{ type: validatorTypes.REQUIRED }], + isReadOnly: data.form.action !== 'add', + isRequired: true, + placeholder: __(''), + includeEmpty: true, + disabled: data.form.action === TYPES.RESIZE, + initialValue: data.form.action === TYPES.RESIZE ? getCellData(data.editingRow, 'type') : '', +}); + +const modeField = (data, roles) => ({ + component: componentTypes.SELECT, + id: 'mode', + name: 'mode', + label: __('Mode'), + options: restructureOptions(['persistent', 'nonpersistent']), + isReadOnly: data.form.action !== 'add', + hideField: !roles.isVmwareInfra, + isRequired: true, + placeholder: __(''), + includeEmpty: true, + disabled: data.form.action === TYPES.RESIZE, + validate: [{ type: 'customRequired', hideField: !roles.isVmwareInfra }], + initialValue: data.form.action === TYPES.RESIZE ? getCellData(data.editingRow, 'mode') : '', +}); + +const controllerField = (data, roles, options) => ({ + component: componentTypes.SELECT, + id: 'controller', + name: 'controller', + label: __('Controller'), + options: restructureOptions(options), + isReadOnly: data.form.action !== 'add', + hideField: !roles.isVmwareInfra, + disabled: data.form.action === TYPES.RESIZE, + initialValue: data.form.action === TYPES.RESIZE ? getCellData(data.editingRow, 'controller') : '', +}); + +const dependentField = (data, roles) => ({ + component: 'switch', + id: 'dependent', + name: 'dependent', + label: __('Dependent'), + onText: __('Yes'), + offText: __('No'), + hideField: !roles.isVmwareInfra, + disabled: data.form.action === TYPES.RESIZE, + initialValue: data.form.action === TYPES.RESIZE ? getSwitchData(data.editingRow, 'dependent') : '', +}); + +const bootableField = (data, roles) => ({ + component: 'switch', + name: 'bootable', + label: __('Bootable'), + onText: __('Yes'), + offText: __('No'), + isReadOnly: data.form.action !== 'add', + hideField: !roles.isRedhat, + initialValue: data.form.action === TYPES.RESIZE ? getSwitchData(data.editingRow, 'bootable') : '', +}); + +export const diskFormFields = (data, roles, options, memory) => ([ + nameField(data), + typeField(data), + sizeField(data), + unitField(data, memory), + modeField(data, roles), + controllerField(data, roles, options.controller_types), + dependentField(data, roles), + bootableField(data, roles), +]); diff --git a/app/javascript/components/reconfigure-vm-form/drive-form-fields.js b/app/javascript/components/reconfigure-vm-form/drive-form-fields.js new file mode 100644 index 00000000000..0bf5b28d2c1 --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/drive-form-fields.js @@ -0,0 +1,31 @@ +import { componentTypes, validatorTypes } from '@@ddf'; +import { restructureOptions } from './helper'; +import { getCellData } from './helpers/general'; + +const nameField = (data) => ({ + component: componentTypes.TEXT_FIELD, + id: 'name', + name: 'name', + label: __('Name'), + initialValue: getCellData(data.editingRow, 'name'), + autoFocus: true, + isReadOnly: true, +}); + +const hostField = (data, options) => ({ + component: componentTypes.SELECT, + id: 'host_file', + name: 'host_file', + label: __('Host File'), + options: restructureOptions(options), + validate: [{ type: validatorTypes.REQUIRED }], + isRequired: true, + placeholder: __(''), + includeEmpty: true, + initialValue: getCellData(data.editingRow, 'hostFile'), +}); + +export const driveFormFields = (data, options) => ([ + nameField(data), + hostField(data, options.host_file_options), +]); diff --git a/app/javascript/components/reconfigure-vm-form/helper.js b/app/javascript/components/reconfigure-vm-form/helper.js new file mode 100644 index 00000000000..b7d0a8503a7 --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/helper.js @@ -0,0 +1,178 @@ +import { http } from '../../http_api'; +import { + deleteDisk, + cancelDeleteDisk, + cancelResizeDisk, + getDiskTableHeaders, + setDiskFormSubmit, + formatDiskData, +} from './helpers/disk'; +import { + cancelEditNetwork, + deleteNetwork, + cancelDeleteNetwork, + getNetworkTableHeaders, + setNetworkFormSubmit, +} from './helpers/network'; +import { + getDriveTableHeaders, + cancelConnectDrives, + setDriveFormSubmit, + cancelDisconnectDrives, + disconnectDrives, +} from './helpers/drive'; +import { TYPES, formsData, sizeInMB } from './helpers/general'; + +/** Function to check if an item is array. if yes, returns true, else returns false */ +const isArray = (item) => Array.isArray(item); + +/** Function to get the options. + * The data is either array of strings eg: ['aaa','bbb'] or + * array of string arrays eg: [['aaa','bbb], ['ccc','ddd']] */ +export const restructureOptions = (data) => { + if (!data) { return []; } return data.map((item) => ( + isArray(item) + ? ({ label: item[0], value: item[1] }) + : ({ label: item.toString(), value: item }))); +}; + +/** Function to set the submit button status based on change counters */ +export const getFormSubmitStatus = (data) => { + if (data.form.type === TYPES.RECONFIGURE && data.changeCounter > 0) { + return true; + } + return false; +}; + +/** Function to execute all button actions */ +export const setButtonActions = (item, data, setData, roles) => { + switch (item.callbackAction) { + case 'deleteDisk': deleteDisk(item, data, setData); break; + case 'cancelDeleteDisk': cancelDeleteDisk(item, data, setData); break; + case 'cancelEditNetwork': cancelEditNetwork(item, data, setData, roles); break; + case 'deleteNetwork': deleteNetwork(item, data, setData, roles); break; + case 'cancelDeleteNetwork': cancelDeleteNetwork(item, data, setData); break; + case 'cancelConnectDrives': cancelConnectDrives(item, data, setData); break; + case 'cancelResizeDisk': cancelResizeDisk(item, data, setData); break; + case 'cancelDisconnectDrives': cancelDisconnectDrives(item, data, setData); break; + case 'disconnectDrives': disconnectDrives(item, data, setData); break; + default: return true; + } + return true; +}; + +/** Function to load the datatable headers values */ +export const dataTableHeaders = (table, roles) => { + switch (table) { + case 'network': + return getNetworkTableHeaders(roles); + case 'drive': + return getDriveTableHeaders(); + default: + return getDiskTableHeaders(roles); + } +}; + +/** validate the memory size field. + * return false when the validation fails + */ +export const validateMemory = (value, checkValue, unit, limit) => { + if (checkValue) { + const valueInMB = sizeInMB(value, unit); + const remainder = valueInMB % 4; + if (valueInMB < limit.min || valueInMB > limit.max || remainder !== 0) { + return false; + } + } + return true; +}; + +/** validate the memory size field. + * return false when the validation fails + */ +export const validateCpu = (value, allValues, field, limit) => { + const cpuValue = field === 'socket' ? allValues.cores_per_socket_count : allValues.socket_count; + if ((cpuValue * value) > limit) { + return false; + } + + return true; +}; + +/** Setting up the sub forms submit data when the form submit action gets called */ +export const subFormSubmit = (data, setData, formData, roles) => { + switch (data.form.type) { + case TYPES.DISK: + case TYPES.RESIZE: + setDiskFormSubmit(data, setData, formData, roles, formsData.reconfigure); + break; + case TYPES.NETWORK: + case TYPES.EDITNETWORK: + setNetworkFormSubmit(data, setData, formData, roles, formsData.reconfigure); + break; + case TYPES.DRIVE: + setDriveFormSubmit(data, setData, formData, formsData.reconfigure); + break; + default: + break; + } +}; + +/** Setting up the final reconfigure submit data when the form submit button clicked */ +export const reconfigureSubmitData = (recordId, data, formData) => ({ + objectIds: recordId, + cb_memory: formData.cb_memory, + cb_cpu: formData.processor, + memory: formData.memory, + memory_type: formData.mem_type, + socket_count: formData.socket_count, + cores_per_socket_count: formData.cores_per_socket_count, + vmAddDisks: data.submitParams.disks.add || [], + vmRemoveDisks: data.submitParams.disks.delete || [], + vmResizeDisks: data.submitParams.disks.resize || [], + vmAddNetworkAdapters: data.submitParams.networks.add || [], + vmRemoveNetworkAdapters: data.submitParams.networks.delete || [], + vmEditNetworkAdapters: data.submitParams.networks.edit || [], + vmConnectCDRoms: data.submitParams.drives.connect || [], + vmDisconnectCDRoms: data.submitParams.drives.disconnect || [], +}); + +/** function to save the processor field changes to show total processors */ +export const socketChange = (value, data, setData, field) => { + if (data[field] !== value) { + data[field] = value; + data.initialValues.total_cpus = data.socket * data.cores; + setData({ + ...data, + }); + } +}; + +/** Setting up the reconfigure form details when the form loads + * TODO: replace with API endpoints. +*/ +export const setInitialData = (value, requestId, data, setData) => { + http.get(`/vm_infra/reconfigure_form_fields/${requestId},${value}`).then((response) => { + setData({ + ...data, + initialValues: { + processor: response.cb_cpu, + cb_memory: response.cb_memory, + cores_per_socket_count: response.cores_per_socket_count, + memory: response.memory, + mem_type: response.memory_type, + socket_count: response.socket_count, + }, + socket: response.socket_count, + cores: response.cores_per_socket_count, + orchestration_stack_id: response.orchestration_stack_id, + isLoading: false, + dataTable: { + ...data.dataTable, + disks: formatDiskData(response.disks), + networkAdapters: response.network_adapters, + drives: response.cdroms, + }, + }); + }); +}; diff --git a/app/javascript/components/reconfigure-vm-form/helpers/disk.js b/app/javascript/components/reconfigure-vm-form/helpers/disk.js new file mode 100644 index 00000000000..95ed5fb3779 --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/helpers/disk.js @@ -0,0 +1,351 @@ +import { TYPES, sizeInMB } from './general'; + +/** Function to execute when the delete backing toggle changed */ +export const backupDelete = (id, data, setData) => { + let backingIds = data.submitParams.diskIds.backup || []; + const index = id.substring(4); + if (backingIds.includes(id)) { + // code to remove from delete backlog + data.dataTable.disks[index].delete_backing = false; + backingIds = backingIds.filter((diskId) => diskId !== id); + } else { + // code to add the disk to delete backlog + data.dataTable.disks[index].delete_backing = true; + backingIds.push(id); + } + setData({ + ...data, + dataTable: { + ...data.dataTable, + disks: data.dataTable.disks, + }, + submitParams: { + ...data.submitParams, + diskIds: { + ...data.submitParams.diskIds, + backup: backingIds, + }, + }, + }); +}; + +/** function to delete disk executed when the delete button gets clicked for the disk datatable */ +export const deleteDisk = (row, data, setData) => { + let dataTableData = data.dataTable.disks; + let addDisks = data.submitParams.disks.add || []; + const deleteDisks = data.submitParams.disks.delete || []; + let addDiskIds = data.submitParams.diskIds.add || []; + const deleteIds = data.submitParams.diskIds.delete || []; + + if (addDiskIds.includes(row.id)) { + // delete from the newly added disks + // eslint-disable-next-line no-alert + if (window.confirm(__('Are you sure you want to delete this entry?'))) { + dataTableData = data.dataTable.disks.filter((disk) => disk.id !== row.id); + addDisks = data.submitParams.disks.add.filter((disk) => disk.id !== row.id); + addDiskIds = data.submitParams.diskIds.add.filter((diskId) => diskId !== row.id); + data.changeCounter -= 1; + } + } else { + // remove from the existing disk datatable + const index = row.id.substring(4); + const currentRow = data.dataTable.disks[index]; + currentRow.add_remove = 'remove'; + const deleteDiskData = { + id: row.id, + disk_name: currentRow.hdFilename, + delete_backing: deleteIds.includes(row.id), + }; + deleteDisks.push(deleteDiskData); + deleteIds.push(row.id); + data.changeCounter += 1; + } + setData({ + ...data, + dataTable: { + ...data.dataTable, + disks: dataTableData, + }, + submitParams: { + ...data.submitParams, + disks: { + ...data.submitParams.disks, + add: addDisks, + delete: deleteDisks, + }, + diskIds: { + ...data.submitParams.diskIds, + add: addDiskIds, + delete: deleteIds, + }, + }, + }); +}; + +/** Cancel delete disk function + * button click from datatable + */ +export const cancelDeleteDisk = (row, data, setData) => { + const submitDisks = data.submitParams.disks.delete.filter((disk) => disk.id !== row.id); + const deletedDiskIds = data.submitParams.diskIds.delete.filter((id) => id !== row.id); + data.changeCounter -= 1; + setData({ + ...data, + submitParams: { + ...data.submitParams, + disks: { + ...data.submitParams.disks, + delete: submitDisks, + }, + diskIds: { + ...data.submitParams.diskIds, + delete: deletedDiskIds, + }, + }, + }); +}; + +/** Cancel resize disk function - restore the previous data size + * button click from datatable + */ +export const cancelResizeDisk = (row, data, setData) => { + const { id } = row; + const index = id.substring(4); + data.dataTable.disks[index].hdSize = data.dataTable.disks[index].old_size; + data.dataTable.disks[index].hdUnit = data.dataTable.disks[index].old_unit; + const submitDisks = data.submitParams.disks.resize.filter((disk) => disk.id !== row.id); + const resizeDiskIds = data.submitParams.diskIds.resize.filter((id) => id !== row.id); + data.changeCounter -= 1; + setData({ + ...data, + submitParams: { + ...data.submitParams, + disks: { + ...data.submitParams.disks, + resize: submitDisks, + }, + diskIds: { + ...data.submitParams.diskIds, + resize: resizeDiskIds, + }, + }, + }); +}; + +/** Function to check the button need to be disabled or not */ +const diskDisableButton = (id, data) => { + if (data.submitParams.diskIds.delete.includes(id) || data.submitParams.diskIds.add.includes(id)) { + return true; + } + return false; +}; + +/** Function to check the delete button rendering */ +const diskAction = (id, data) => { + if (data.submitParams.diskIds.delete.includes(id)) { + return { + is_button: true, + title: __('Cancel Delete'), + text: __('Cancel Delete'), + alt: __('Cancel Delete'), + kind: 'ghost', + callback: 'cancelDeleteDisk', + }; + } + return { + is_button: true, + title: __('Delete'), + text: __('Delete'), + alt: __('Delete'), + kind: 'ghost', + disabled: data.submitParams.diskIds.resize.includes(id), + callback: 'deleteDisk', + }; +}; + +/** Function to check the resize button rendering */ +const resizeAction = (id, data) => { + if (data.submitParams.diskIds.resize.includes(id)) { + return { + is_button: true, + title: __('Cancel Resize'), + text: __('Cancel Resize'), + alt: __('Cancel Resize'), + kind: 'ghost', + callback: 'cancelResizeDisk', + }; + } + return { + is_button: true, + title: __('Resize'), + text: __('Resize'), + alt: __('Resize'), + kind: 'ghost', + callback: 'resizeDisk', + disabled: diskDisableButton(id, data), + }; +}; + +/** Function to validate the disk size + * This function will validate the disk size in resize form + */ +export const validateDiskSize = (value, unit, minSize, minUnit) => { + if (!Number.isNaN(value)) { + const valueInMb = sizeInMB(value, unit); + const minSizeInMb = sizeInMB(minSize, minUnit); + if (valueInMb >= minSizeInMb) { + return true; + } + } + return false; +}; + +/** Function to set the Disk datatable row data + * This formatting is needed for resize function validation + */ +export const formatDiskData = (disks) => { + disks.forEach((disk) => { + disk.orgHdSize = disk.hdSize; + disk.orgHdUnit = disk.hdUnit; + }); + + return disks; +}; + +/** Function to set the Disk datatable row data */ +export const setDiskData = (disks, roles, data, setData) => { + const diskData = []; + disks.forEach((disk, i) => { + const id = `disk${i}`; + diskData[i] = { + id, + name: disk.hdFilename || ' ', + type: disk.hdType, + size: disk.hdSize, + unit: disk.hdUnit, + action: diskAction(id, data), + }; + if (roles.isVmwareInfra) { + diskData[i].dependent = disk.cb_dependent ? __('Yes') : __('No'); + diskData[i].mode = disk.hdMode || __('None'); + diskData[i].controller = disk.new_controller_type || __('None'); + } + if (!roles.isVmwareCloud) { + diskData[i].backing = { + is_toggle: true, + labelText: __('Delete Backing'), + labelA: __('Yes'), + labelB: __('No'), + toggled: !!disk.delete_backing, + ontoggle: () => backupDelete(id, data, setData), + disabled: diskDisableButton(id, data), + }; + } + if (roles.isRedhat) { + diskData[i].bootable = disk.cb_bootable === true ? __('Yes') : __('No'); + } + if (roles.allowDiskSizeChange) { + diskData[i].resize = resizeAction(id, data); + } + }); + return diskData; +}; + +/** Function to set the Disk datatable headers */ +export const getDiskTableHeaders = (roles) => { + const headers = [ + { key: 'name', header: __('Name') }, + { key: 'type', header: __('Type') }, + { key: 'size', header: __('Size') }, + { key: 'unit', header: __('Unit') }, + ]; + if (roles.isVmwareInfra) { + headers.push( + { key: 'mode', header: __('Mode') }, + { key: 'controller', header: __('Controller Type') }, + { key: 'dependent', header: __('Dependent') } + ); + } + if (!roles.isVmwareCloud) { + headers.push({ key: 'backing', header: __('Delete Backing') }); + } + if (roles.isRedhat) { + headers.push({ key: 'bootable', header: __('Bootable') }); + } + if (roles.allowDiskSizeChange) { + headers.push({ key: 'resize', header: __('Resize') }); + } + headers.push({ key: 'action', header: __('Action'), contentButton: true }); + return headers; +}; + +/** function to execute disk sub forms submit gets called + * Disk add, resize function +*/ +export const setDiskFormSubmit = (data, setData, formData, roles, renderData) => { + const dataTableData = data.dataTable.disks || []; + if (data.form.action === 'add') { + // code for add + const id = `disk${dataTableData.length}`; + const diskDatatableData = { + id, + hdFilename: '', + hdType: formData.type, + hdSize: formData.size, + hdUnit: formData.unit, + add_remove: data.form.action, + }; + const submitDiskData = { + id, + disk_size_in_mb: sizeInMB(formData.size, formData.unit), + thin_provisioned: formData.type === 'thin', + type: formData.type, + }; + if (roles.isVmwareInfra) { + diskDatatableData.hdMode = formData.mode; + diskDatatableData.new_controller_type = formData.controller; + diskDatatableData.cb_dependent = formData.dependent || false; + submitDiskData.persistent = formData.hdMode; + submitDiskData.new_controller_type = formData.controller; + submitDiskData.dependent = formData.dependent || false; + } + if (!roles.isVmwareCloud) { + diskDatatableData.backing = false; + } + if (roles.isRedhat) { + diskDatatableData.cb_bootable = formData.bootable || false; + submitDiskData.bootable = formData.bootable || false; + } + data.submitParams.disks.add.push(submitDiskData); + data.submitParams.diskIds.add.push(diskDatatableData.id); + dataTableData.push(diskDatatableData); + } else { + // code for resize option + const { id } = data.editingRow; + const index = id.substring(4); + dataTableData[index].old_size = dataTableData[index].hdSize; + dataTableData[index].hdSize = formData.size; + dataTableData[index].old_unit = dataTableData[index].hdUnit; + dataTableData[index].hdUnit = formData.unit; + const resizeData = { + id, + disk_name: dataTableData[index].hdFilename, + disk_size_in_mb: sizeInMB(formData.size, formData.unit), + }; + data.submitParams.disks.resize.push(resizeData); + data.submitParams.diskIds.resize.push(id); + } + data.changeCounter += 1; + setData({ + ...data, + dataTable: { + ...data.dataTable, + disks: dataTableData, + }, + form: { + title: renderData.title, + type: TYPES.RECONFIGURE, + className: renderData.className, + }, + }); +}; diff --git a/app/javascript/components/reconfigure-vm-form/helpers/drive.js b/app/javascript/components/reconfigure-vm-form/helpers/drive.js new file mode 100644 index 00000000000..878deaaa999 --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/helpers/drive.js @@ -0,0 +1,228 @@ +import { TYPES } from './general'; + +/** Function to cancel the connection of the drive from device */ +export const cancelConnectDrives = (row, data, setData) => { + const { id } = row; + const index = id.substring(5); + const datatableData = data.dataTable.drives; + datatableData[index].filename = datatableData[index].old_filename; + + const submitDrives = data.submitParams.drives.connect.filter((drive) => drive.id !== id); + const connectedDriveIds = data.submitParams.driveIds.connect.filter((driveId) => driveId !== id); + data.changeCounter -= 1; + setData({ + ...data, + isLoading: false, + dataTable: { + ...data.dataTable, + drives: datatableData, + }, + submitParams: { + ...data.submitParams, + drives: { + ...data.submitParams.drives, + connect: submitDrives, + }, + driveIds: { + ...data.submitParams.driveIds, + connect: connectedDriveIds, + }, + }, + }); +}; + +/** Function to cancel the disconnection of drives from device */ +export const cancelDisconnectDrives = (row, data, setData) => { + const { id } = row; + const index = id.substring(5); + const datatableData = data.dataTable.drives; + datatableData[index].filename = datatableData[index].disconnect_filename; + + const submitDrives = data.submitParams.drives.disconnect.filter((drive) => drive.id !== id); + const disConnectedDriveIds = data.submitParams.driveIds.disconnect.filter((driveId) => driveId !== id); + data.changeCounter -= 1; + setData({ + ...data, + isLoading: false, + dataTable: { + ...data.dataTable, + drives: datatableData, + }, + submitParams: { + ...data.submitParams, + drives: { + ...data.submitParams.drives, + disconnect: submitDrives, + }, + driveIds: { + ...data.submitParams.driveIds, + disconnect: disConnectedDriveIds, + }, + }, + }); +}; + +/** Function to disconnect drives from device */ +export const disconnectDrives = (row, data, setData) => { + const { id } = row; + const index = id.substring(5); + const datatableData = data.dataTable.drives; + const submitDrives = data.submitParams.drives.disconnect || []; + const disConnectedDriveIds = data.submitParams.driveIds.disconnect || []; + datatableData[index].disconnect_filename = datatableData[index].filename; + datatableData[index].filename = ''; + const disconnectDriveData = { + id, + device_name: datatableData[index].device_name, + }; + submitDrives.push(disconnectDriveData); + disConnectedDriveIds.push(id); + data.changeCounter += 1; + setData({ + ...data, + isLoading: false, + dataTable: { + ...data.dataTable, + drives: datatableData, + }, + submitParams: { + ...data.submitParams, + drives: { + ...data.submitParams.drives, + disconnect: submitDrives, + }, + driveIds: { + ...data.submitParams.driveIds, + disconnect: disConnectedDriveIds, + }, + }, + }); +}; + +/** Function to check the connect button render options */ +const connectAction = (id, file, data) => { + if (data.submitParams.driveIds.connect.includes(id)) { + return { + is_button: true, + title: __('Cancel Connect'), + text: __('Cancel Connect'), + alt: __('Cancel Connect'), + kind: 'ghost', + callback: 'cancelConnectDrives', + }; + } + return { + is_button: true, + title: __('Connect'), + text: __('Connect'), + alt: __('Connect'), + disabled: !!file, + kind: 'ghost', + callback: 'connectDrives', + }; +}; + +/** Function to check the disconnect button render options */ +const disConnectAction = (id, data) => { + if (data.submitParams.driveIds.disconnect.includes(id)) { + return { + is_button: true, + title: __('Cancel Disconnect'), + text: __('Cancel Disconnect'), + alt: __('Cancel Disconnect'), + kind: 'ghost', + callback: 'cancelDisconnectDrives', + disabled: data.submitParams.driveIds.connect.includes(id), + }; + } + return { + is_button: true, + title: __('Disconnect'), + text: __('Disconnect'), + alt: __('Disconnect'), + kind: 'ghost', + callback: 'disconnectDrives', + disabled: data.submitParams.driveIds.connect.includes(id), + }; +}; + +/** Function to set the CD/ROM Drive datatable row data */ +export const setDrivesData = (drives, data) => { + const driveData = []; + + drives.forEach((drive, i) => { + const id = `drive${i}`; + driveData[i] = { + id, + name: drive.device_name, + hostFile: drive.filename, + action: connectAction(id, drive.filename, data), + }; + if (drive.filename || drive.disconnect_filename) { + driveData[i].disconnect = disConnectAction(id, data); + } else { + driveData[i].disconnect = ''; + } + }); + + return driveData; +}; + +/** Function to set the CD-ROM drive datatable headers */ +export const getDriveTableHeaders = () => [ + { key: 'name', header: __('Name') }, + { key: 'hostFile', header: __('Host File') }, + { key: 'disconnect', header: __('Disconnect') }, + { key: 'action', header: __('Actions') }, +]; + +/** function to execute drive sub forms submit gets called + * Drive connect form submission +*/ +export const setDriveFormSubmit = (data, setData, formData, renderData) => { + const { id } = data.editingRow; + const index = id.substring(5); + const datatableData = data.dataTable.drives; + const submitDrives = data.submitParams.drives.connect || []; + const connectedDriveIds = data.submitParams.driveIds.connect || []; + const isoSelect = formData.host_file.split(','); + + datatableData[index].old_filename = datatableData[index].filename; + // eslint-disable-next-line prefer-destructuring + datatableData[index].filename = isoSelect[0]; + + const connectDriveData = { + id, + device_name: datatableData[index].device_name, + filename: datatableData[index].filename, + storage_id: isoSelect[1], + }; + submitDrives.push(connectDriveData); + connectedDriveIds.push(id); + data.changeCounter += 1; + + setData({ + ...data, + isLoading: false, + form: { + title: renderData.title, + type: TYPES.RECONFIGURE, + className: renderData.className, + }, + dataTable: { + ...data.dataTable, + drives: datatableData, + }, + submitParams: { + ...data.submitParams, + drives: { + ...data.submitParams.drives, + connect: submitDrives, + }, + driveIds: { + ...data.submitParams.driveIds, + connect: connectedDriveIds, + }, + }, + }); +}; diff --git a/app/javascript/components/reconfigure-vm-form/helpers/general.js b/app/javascript/components/reconfigure-vm-form/helpers/general.js new file mode 100644 index 00000000000..767d3ef1778 --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/helpers/general.js @@ -0,0 +1,53 @@ +/** Function to get the value from selected datatable cells. */ +export const getCellData = (obj, value) => { + const nameCell = obj.cells.find((cell) => cell.id === `${obj.id}:${value}`); + return nameCell ? nameCell.value : ''; +}; + +/** Function to get the value from selected object + * needed from the form display methods + */ +export const getObjectData = (index, data, field) => data[index][field]; + +/** Function to set all forms types present in the reconfigure vm feature */ +export const TYPES = { + RECONFIGURE: 'reconfigure', + DISK: 'disk', + NETWORK: 'network', + DRIVE: 'drive', + RESIZE: 'resize', + EDITNETWORK: 'editNetwork', +}; + +/** Function to set all forms data in the reconfigure vm feature */ +export const formsData = { + reconfigure: { + title: __('Options'), + className: 'reconfigure_form', + }, + disk: { + title: __('Add Disk'), + className: 'disk_form', + }, + resize: { + title: __('Resize Disk'), + className: 'disk_form', + }, + network: { + title: __('Add Network Adapters'), + className: 'network_form', + }, + editNetwork: { + title: __('Edit Network Adapters'), + className: 'network_form', + }, + drive: { + title: __('Connect CD/DVD Drives'), + className: 'drive_form', + }, +}; + +/** Function to get the value in MB + * converts the value to GB to MB based on the passed unit + */ +export const sizeInMB = (value, unit) => (unit === __('GB') ? value * 1024 : value); diff --git a/app/javascript/components/reconfigure-vm-form/helpers/network.js b/app/javascript/components/reconfigure-vm-form/helpers/network.js new file mode 100644 index 00000000000..634e8eb866d --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/helpers/network.js @@ -0,0 +1,301 @@ +import { TYPES, formsData } from './general'; + +/** Function which executes when the cancel edit button gets clicked */ +export const cancelEditNetwork = (row, data, setData, roles) => { + const index = row.id.substring(7); + const networkRows = data.dataTable.networkAdapters; + + if (!roles.isVmwareCloud) { + networkRows[index].vlan = networkRows[index].old_vlan; + } + + if (roles.isVmwareCloud) { + networkRows[index].network = networkRows[index].old_network; + } + const submitNetworks = data.submitParams.networks.edit.filter((network) => network.id !== row.id); + const editedNetworkIds = data.submitParams.networkIds.edit.filter((id) => id !== row.id); + + data.dataTable.networkAdapters = networkRows; + data.changeCounter -= 1; + + setData({ + ...data, + submitParams: { + ...data.submitParams, + networks: { + ...data.submitParams.networks, + edit: submitNetworks, + }, + networkIds: { + ...data.submitParams.networkIds, + edit: editedNetworkIds, + }, + }, + }); +}; + +/** Function which executes when the delete button gets clicked */ +export const deleteNetwork = (row, data, setData, roles) => { + let dataTableData = data.dataTable.networkAdapters || []; + let submitNetworks = data.submitParams.networks.add || []; + let addNetworkIds = data.submitParams.networkIds.add || []; + const deleteNetworksData = data.submitParams.networks.delete || []; + const deletedNetworkIds = data.submitParams.networkIds.delete || []; + + if (data.submitParams.networkIds.add.includes(row.id)) { + // remove from the newly added networks + // eslint-disable-next-line no-alert + if (window.confirm(__('Are you sure you want to delete this entry?'))) { + dataTableData = data.dataTable.networkAdapters.filter((network) => network.id !== row.id); + submitNetworks = data.submitParams.networks.add.filter((network) => network.id !== row.id); + addNetworkIds = data.submitParams.networkIds.add.filter((id) => id !== row.id); + } + data.changeCounter -= 1; + } else { + // remove from the existing networks + const index = row.id.substring(7); + const deleteNetworkData = { + id: row.id, + network: { + name: dataTableData[index].name, + mac: dataTableData[index].mac, + add_remove: 'remove', + }, + }; + if (!roles.isVmwareCloud) { + deleteNetworkData.network.vlan = dataTableData[index].vlan; + } + if (roles.isVmwareCloud) { + deleteNetworkData.network.network = dataTableData[index].network; + } + deleteNetworksData.push(deleteNetworkData); + deletedNetworkIds.push(row.id); + data.changeCounter += 1; + } + setData({ + ...data, + dataTable: { + ...data.dataTable, + networkAdapters: dataTableData, + }, + submitParams: { + ...data.submitParams, + networks: { + ...data.submitParams.networks, + add: submitNetworks, + delete: deleteNetworksData, + }, + networkIds: { + ...data.submitParams.networkIds, + add: addNetworkIds, + delete: deletedNetworkIds, + }, + }, + }); +}; + +/** Function which executes when the cancel delete button gets clicked */ +export const cancelDeleteNetwork = (row, data, setData) => { + const deleteNetworksData = data.submitParams.networks.delete.filter((network) => network.id !== row.id); + const deletedNetworkIds = data.submitParams.networkIds.delete.filter((id) => id !== row.id); + data.changeCounter -= 1; + setData({ + ...data, + submitParams: { + ...data.submitParams, + networks: { + ...data.submitParams.networks, + delete: deleteNetworksData, + }, + networkIds: { + ...data.submitParams.networkIds, + delete: deletedNetworkIds, + }, + }, + }); +}; + +/** Function to set the Network datatable row data - name */ +const getNetworkName = (id, data) => { + if (data.submitParams.networkIds.add.includes(id)) { + return __('to be determined'); + } + return __(' '); +}; + +/** Function to set the Network datatable row data - mac */ +const getNetworkMac = (id, data) => { + if (data.submitParams.networkIds.add.includes(id)) { + return __('not available yet'); + } + return __(' '); +}; + +/** Function to check edit button should be disabled or not */ +const disableNetworkEditButton = (id, data) => data.submitParams.networkIds.add.includes(id) || data.submitParams.networkIds.delete.includes(id); + +/** Function to check and render the network edit button */ +const networkEditAction = (id, data) => { + if (data.submitParams.networkIds.edit.includes(id)) { + return { + is_button: true, + title: __('Cancel Edit'), + text: __('Cancel Edit'), + alt: __('Cancel Edit'), + kind: 'ghost', + callback: 'cancelEditNetwork', + disabled: disableNetworkEditButton(id, data), + }; + } + return { + is_button: true, + title: __('Edit'), + text: __('Edit'), + alt: __('Edit'), + kind: 'ghost', + disabled: disableNetworkEditButton(id, data), + callback: 'editNetwork', + }; +}; + +/** Function to check and render the network delete button */ +const networkDeleteAction = (id, data) => { + if (data.submitParams.networkIds.delete.includes(id)) { + return { + is_button: true, + title: __('Cancel Delete'), + text: __('Cancel Delete'), + alt: __('Cancel Delete'), + kind: 'ghost', + callback: 'cancelDeleteNetwork', + }; + } + return { + is_button: true, + title: __('Delete'), + text: __('Delete'), + alt: __('Delete'), + kind: 'ghost', + callback: 'deleteNetwork', + disabled: data.submitParams.networkIds.edit.includes(id), + }; +}; + +/** Function to set the Network datatable row data */ +export const setNetworkData = (networks, roles, data) => { + const networkData = []; + networks.forEach((network, i) => { + const id = `network${i}`; + const name = network.name ? network.name : getNetworkName(id, data); + const mac = network.mac ? network.mac : getNetworkMac(id, data); + networkData[i] = { + id, + name, + mac, + action: networkDeleteAction(id, data), + edit: networkEditAction(id, data), + }; + if (!roles.isVmwareCloud) { + networkData[i].vlan = network.vlan; + } + if (roles.isVmwareCloud) { + networkData[i].network = network.network || __('None'); + } + }); + return networkData; +}; + +/** Function to set the Network datatable headers */ +export const getNetworkTableHeaders = (roles) => { + const headers = [ + { key: 'name', header: __('Name') }, + { key: 'mac', header: __('MAC address') }, + ]; + if (!roles.isVmwareCloud) { + headers.push({ key: 'vlan', header: __('vLan') }); + } + if (roles.isVmwareCloud) { + headers.push({ key: 'network', header: __('Network') }); + } + headers.push({ key: 'edit', header: __('Edit'), contentButton: true }, { key: 'action', header: __('Action'), contentButton: true }); + return headers; +}; + +/** Setting up the network form details when the form loads for cloud */ +export const setNetworkOptions = (id, data, setData, type, action, row) => { + API.get(`/api/cloud_networks?expand=resources&attributes=name&filter[]=orchestration_stack_id=${id}`).then(({ resources }) => { + const networkOptions = resources.map((item) => ( + item.name + )); + setData({ + ...data, + isLoading: false, + networkOptions, + editingRow: row, + form: { + title: formsData[type].title, + type, + action, + className: formsData[type].className, + }, + }); + }); +}; + +/** Function to execute the network form data submission + * network add, edit function +*/ +export const setNetworkFormSubmit = (data, setData, formData, roles, renderData) => { + if (data.form.action === 'add') { + // code for add function + const id = `network${data.dataTable.networkAdapters.length}`; + const networkData = { + id, + name: '', + }; + const networkSubmitData = { + id, + name: 'to be determined', + }; + if (!roles.isVmwareCloud) { + networkData.vlan = formData.vlan; + networkSubmitData.network = formData.vlan; + } + if (roles.isVmwareCloud) { + networkData.network = formData.network; + networkSubmitData.cloud_network = formData.network; + } + data.submitParams.networks.add.push(networkSubmitData); + data.submitParams.networkIds.add.push(id); + data.dataTable.networkAdapters.push(networkData); + } else { + // code for edit function + const index = data.editingRow.id.substring(7); + const networkData = { id: data.editingRow.id }; + const networkRows = data.dataTable.networkAdapters; + if (!roles.isVmwareCloud) { + networkData.network = formData.vlan; + networkRows[index].old_vlan = networkRows[index].vlan; + networkRows[index].vlan = formData.vlan; + } + if (roles.isVmwareCloud) { + networkData.network = formData.network; + networkRows[index].old_network = networkRows[index].network; + networkRows[index].network = networkData.network; + } + networkData.name = networkRows[index].name; + data.submitParams.networks.edit.push(networkData); + data.submitParams.networkIds.edit.push(networkData.id); + data.dataTable.networkAdapters = networkRows; + } + data.changeCounter += 1; + setData({ + ...data, + isLoading: false, + form: { + title: renderData.title, + type: TYPES.RECONFIGURE, + className: renderData.className, + }, + }); +}; diff --git a/app/javascript/components/reconfigure-vm-form/index.jsx b/app/javascript/components/reconfigure-vm-form/index.jsx new file mode 100644 index 00000000000..f95911317b6 --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/index.jsx @@ -0,0 +1,229 @@ +import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import { Loading } from 'carbon-components-react'; +import componentMapper from '../../forms/mappers/componentMapper'; +import MiqFormRenderer from '../../forms/data-driven-form'; +import { createSchema } from './reconfigure-form.schema'; +import { CellAction } from '../miq-data-table/helper'; +import ReconfigureTable from './reconfigure-table'; +import ReconfigureTemplate from './reconfigure-template'; +import miqRedirectBack from '../../helpers/miq-redirect-back'; +import { + setInitialData, + subFormSubmit, + setButtonActions, + reconfigureSubmitData, + validateMemory, + getFormSubmitStatus, + validateCpu, +} from './helper'; +import { TYPES, formsData } from './helpers/general'; +import { validateDiskSize } from './helpers/disk'; +import { setNetworkOptions } from './helpers/network'; + +const ReconfigureVmForm = ({ + recordId, requestId, roles, options, memory, +}) => { + const [data, setData] = useState({ + initialValues: {}, + isLoading: true, + form: { + title: formsData.reconfigure.title, + type: TYPES.RECONFIGURE, + className: formsData.reconfigure.className, + action: 'edit', + }, + orchestration_stack_id: '', + networkOptions: [], + dataTable: { + disks: [], + networkAdapters: [], + drives: [], + }, + editingRow: [], + submitParams: { + disks: { add: [], resize: [], delete: [] }, + diskIds: { + add: [], resize: [], delete: [], backup: [], + }, + networks: { add: [], edit: [], delete: [] }, + networkIds: { add: [], edit: [], delete: [] }, + drives: { connect: [], disconnect: [] }, + driveIds: { connect: [], disconnect: [] }, + }, + changeCounter: 0, + socket: '', + cores: '', + reset: 1, + }); + + useEffect(() => { + setInitialData(recordId, requestId, data, setData, roles); + }, [recordId, data.reset]); + + const onSubmit = (formsData) => { + miqSparkleOn(); + if (data.form.type === TYPES.RECONFIGURE) { + const URL = `/vm_infra/reconfigure_update/${requestId}?button=submit`; + miqAjaxButton(URL, reconfigureSubmitData(recordId, data, formsData)); + } else { + subFormSubmit(data, setData, formsData, roles); + } + miqSparkleOff(); + }; + + const onCancel = () => { + if (data.form.type === TYPES.RECONFIGURE) { + miqSparkleOn(); + const returnURL = '/vm_infra/explorer/'; + const message = sprintf(__('VM Reconfigure Request was cancelled by the user')); + miqRedirectBack(message, 'success', returnURL); + } else { + setData({ + ...data, + isLoading: false, + form: { + title: __('Options'), + type: TYPES.RECONFIGURE, + className: 'reconfigureForm', + }, + }); + } + }; + + const onReset = () => { + if (data.form.type === TYPES.RECONFIGURE) { + setData({ + ...data, + editingRow: [], + submitParams: { + disks: { add: [], resize: [], delete: [] }, + diskIds: { + add: [], resize: [], delete: [], backup: [], + }, + networks: { add: [], edit: [], delete: [] }, + networkIds: { add: [], edit: [], delete: [] }, + drives: { connect: [], disconnect: [] }, + driveIds: { connect: [], disconnect: [] }, + }, + changeCounter: 0, + reset: data.reset + 1, + }); + } + }; + + /** Function to define the custom validation functions */ + const customValidatorMapper = { + customRequired: ({ hideField }) => (value) => (!value && !hideField ? __('Required') : undefined), + memoryCheck: () => (value, allValues) => ( + validateMemory(value, allValues.cb_memory, allValues.mem_type, memory) ? undefined : __('Memory value not in range or not a multiple of 4') + ), + cpuCheck: ({ field }) => (value, allValues) => ( + validateCpu(value, allValues, field, memory.max_cpu) ? undefined : __(`Total processors value larger than the maximum allowed value`) + ), + diskMemoryCheck: ({ size, unit }) => (value, allValues) => ( + validateDiskSize(value, allValues.unit, size, unit) ? undefined : __(`Disk size has to be greater than ${size}${unit}`) + ), + }; + + /** Function to render the forms by setting form type. + * return true for no render action. + */ + // eslint-disable-next-line consistent-return + const setRenderForm = (row, type, action) => { + if (type === TYPES.DISK && action === 'edit') { + return true; + } + if (type === TYPES.NETWORK || type === TYPES.EDITNETWORK) { + if (action === 'edit') { + const networks = data.submitParams.networkIds; + if (networks.add.includes(row.id) || networks.edit.includes(row.id) || networks.delete.includes(row.id)) { + return true; + } + } + if (roles.isVmwareCloud) { + setNetworkOptions(data.orchestration_stack_id, data, setData, type, action, row); + return true; + } + } + setData({ + ...data, + isLoading: false, + editingRow: row, + form: { + title: formsData[type].title, + type, + action, + className: formsData[type].className, + }, + }); + }; + + /** Function to handle the button clicks of the datatable. */ + const setButtonClick = (item) => { + if (item && item.callbackAction) { + if (item.callbackAction === TYPES.EDITNETWORK) { + setRenderForm(item, TYPES.EDITNETWORK, 'edit'); + } else if (item.callbackAction === 'connectDrives') { + setRenderForm(item, TYPES.DRIVE, 'edit'); + } else if (item.callbackAction === 'resizeDisk') { + setRenderForm(item, TYPES.RESIZE, TYPES.RESIZE); + } else { + setButtonActions(item, data, setData, roles); + } + } + }; + + /** Function to execute the click events of from the datables. + * Like - row's click event for resize and delete button click event. + */ + const onCellClick = (selectedRow, cellType) => { + if (cellType === CellAction.buttonCallback) { + setButtonClick(selectedRow); + } + return true; + }; + + const tableComponentMapper = { + ...componentMapper, + 'reconfigure-table': ReconfigureTable, + }; + + if (data.isLoading) return ; + return !data.isLoading && ( + <> + ( + + )} + initialValues={data.initialValues} + onSubmit={onSubmit} + onReset={onReset} + onCancel={() => onCancel(data)} + validatorMapper={customValidatorMapper} + clearOnUnmount={data.form.type !== TYPES.RECONFIGURE} + /> + + ); +}; + +ReconfigureVmForm.propTypes = { + recordId: PropTypes.arrayOf(PropTypes.any).isRequired, + requestId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + roles: PropTypes.objectOf(PropTypes.any), + options: PropTypes.objectOf(PropTypes.any), + memory: PropTypes.objectOf(PropTypes.any), +}; + +ReconfigureVmForm.defaultProps = { + roles: undefined, + options: undefined, + memory: undefined, +}; + +export default ReconfigureVmForm; diff --git a/app/javascript/components/reconfigure-vm-form/network-form-fields.js b/app/javascript/components/reconfigure-vm-form/network-form-fields.js new file mode 100644 index 00000000000..4dce6406b8e --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/network-form-fields.js @@ -0,0 +1,76 @@ +import { componentTypes, validatorTypes } from '@@ddf'; +import { restructureOptions } from './helper'; +import { getCellData } from './helpers/general'; + +const vlanField = (options, roles, data) => ({ + component: componentTypes.SELECT, + id: 'vlan', + name: 'vlan', + label: __('vLan'), + options: restructureOptions(options), + isRequired: true, + placeholder: __(''), + includeEmpty: true, + initialValue: data.form.action === 'edit' ? getCellData(data.editingRow, 'vlan') : '', + hideField: roles.isVmwareCloud, + validate: [{ type: 'customRequired', hideField: roles.isVmwareCloud }], +}); + +const networkField = (options, roles, data) => ({ + component: componentTypes.SELECT, + id: 'network', + name: 'network', + label: __('Network'), + options: restructureOptions(options), + isRequired: true, + placeholder: __(''), + includeEmpty: true, + initialValue: data.form.action === 'edit' ? getCellData(data.editingRow, 'network') : '', + hideField: !roles.isVmwareCloud, + validate: [{ type: 'customRequired', hideField: !roles.isVmwareCloud }], +}); + +const nameField = (data, options, roles) => { + if (roles.isVmwareCloud && data.form.action === 'add') { + return { + component: componentTypes.SELECT, + id: 'network', + name: 'network', + label: __('Network'), + options: restructureOptions(options), + isRequired: true, + placeholder: __(''), + initialValue: data.form.action === 'edit' ? getCellData(data.editingRow, 'name') : '', + includeEmpty: true, + hideField: !roles.isVmwareCloud, + validate: [{ type: validatorTypes.REQUIRED }], + }; + } + return { + component: componentTypes.TEXT_FIELD, + id: 'name', + name: 'name', + label: __('Name'), + isReadOnly: data.form.action === 'edit', + autoFocus: true, + initialValue: data.form.action === 'edit' ? getCellData(data.editingRow, 'name') : '', + hideField: data.form.action === 'add', + }; +}; + +const macField = (data) => ({ + component: componentTypes.TEXT_FIELD, + id: 'mac', + name: 'mac', + label: __('MAC Address'), + initialValue: data.form.action === 'edit' ? getCellData(data.editingRow, 'mac') : '', + isReadOnly: data.form.action === 'edit', + hideField: data.form.action === 'add', +}); + +export const networkFormFields = (data, options, roles) => ([ + nameField(data, options.avail_adapter_names, roles), + vlanField(options.vlan_options, roles, data), + networkField(data.networkOptions, roles, data), + macField(data), +]); diff --git a/app/javascript/components/reconfigure-vm-form/reconfigure-form-fields.js b/app/javascript/components/reconfigure-vm-form/reconfigure-form-fields.js new file mode 100644 index 00000000000..20b7c63e842 --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/reconfigure-form-fields.js @@ -0,0 +1,151 @@ +import { componentTypes } from '@@ddf'; +import { dataTableHeaders, restructureOptions, socketChange } from './helper'; +import { setDiskData } from './helpers/disk'; +import { setNetworkData } from './helpers/network'; +import { setDrivesData } from './helpers/drive'; +import { TYPES } from './helpers/general'; + +const memoryField = (roles) => ({ + component: 'switch', + name: 'cb_memory', + label: __('Memory'), + onText: __('Yes'), + offText: __('No'), + isDisabled: roles.allowMemoryChange === false, +}); + +const memoryValueField = () => ({ + component: componentTypes.TEXT_FIELD, + name: 'memory', + label: __('Memory Size'), + initialValue: 16, + isRequired: true, + condition: { + when: 'cb_memory', + is: true, + }, + validate: [{ type: 'memoryCheck' }], +}); + +const memoryTypeField = (memory) => ({ + component: componentTypes.SELECT, + id: 'memoryType', + name: 'mem_type', + label: __('Memory Type'), + initialValue: 'GB', + options: restructureOptions([__('GB'), __('MB')]), + helperText: __(`Between ${memory.min}MB and ${memory.max / 1024}GB`), + condition: { + when: 'cb_memory', + is: true, + }, +}); + +const processorField = (roles) => ({ + component: 'switch', + name: 'processor', + label: __('Processor'), + onText: __('Yes'), + offText: __('No'), + isDisabled: roles.allowCpuChange === false, +}); + +const socketField = (data, setData, options) => ({ + component: componentTypes.SELECT, + id: 'socket', + name: 'socket_count', + label: __('Sockets'), + options: restructureOptions(options), + hideField: options.length === 0, + onChange: (value) => socketChange(value, data, setData, 'socket'), + condition: { + when: 'processor', + is: true, + }, + validate: [{ type: 'cpuCheck', field: 'socket' }], +}); + +const coresPerSocketField = (data, setData, options) => ({ + component: componentTypes.SELECT, + id: 'cores', + name: 'cores_per_socket_count', + label: __('Cores Per Socket'), + options: restructureOptions(options), + onChange: (value) => socketChange(value, data, setData, 'cores'), + validate: [{ type: 'cpuCheck', field: 'cores' }], + hideField: options.length === 0, + condition: { + when: 'processor', + is: true, + }, +}); + +const totalProcessorsField = (value) => ({ + component: componentTypes.TEXT_FIELD, + id: 'total_cpus', + name: 'total_cpus', + label: __('Total Processors'), + isReadOnly: true, + type: 'number', + initialValue: value, + condition: { + when: 'processor', + is: true, + }, +}); + +const diskTable = (data, roles, setData, onCellClick, buttonClick) => ({ + component: 'reconfigure-table', + name: 'disk', + label: __('Disks'), + headers: dataTableHeaders('disk', roles), + rows: data.dataTable.disks ? setDiskData(data.dataTable.disks, roles, data, setData) : [], + onCellClick, + formType: TYPES.DISK, + addButtonLabel: __('Add Disk'), + buttonClick, +}); + +const networkTable = (data, roles, setData, onCellClick, buttonClick) => ({ + component: 'reconfigure-table', + name: 'network', + label: __('Network Adapters'), + headers: dataTableHeaders('network', roles), + rows: data.dataTable.networkAdapters ? setNetworkData(data.dataTable.networkAdapters, roles, data, setData) : [], + onCellClick, + formType: TYPES.NETWORK, + addButtonLabel: __('Add Network'), + buttonClick, +}); + +const driveTable = (data, roles, setData, onCellClick) => ({ + component: 'reconfigure-table', + name: 'drive', + label: __('CD/DVD Drives'), + headers: dataTableHeaders('drive', roles), + rows: data.dataTable.drives ? setDrivesData(data.dataTable.drives, data) : [], + onCellClick, + addButton: false, + formType: TYPES.DRIVE, + hideField: data.dataTable.drives.length === 0, +}); + +const renderDatatables = (recordId, data, roles, setData, onCellClick, buttonClick) => { + if (recordId.length === 1) { + return [diskTable(data, roles, setData, onCellClick, buttonClick), + networkTable(data, roles, setData, onCellClick, buttonClick), + driveTable(data, roles, setData, onCellClick)]; + } + return ''; +}; + +export const reconfigureFormFields = (recordId, roles, memory, data, setData, options, onCellClick, buttonClick) => ([ + memoryField(roles), + memoryValueField(), + memoryTypeField(memory), + processorField(roles), + socketField(data, setData, options.socket_options, memory.max_cpu), + coresPerSocketField(data, setData, options.cores_options, memory.max_cpu), + totalProcessorsField(data.socket * data.cores), + renderDatatables(recordId, data, roles, setData, onCellClick, buttonClick), +]); diff --git a/app/javascript/components/reconfigure-vm-form/reconfigure-form.schema.js b/app/javascript/components/reconfigure-vm-form/reconfigure-form.schema.js new file mode 100644 index 00000000000..e31fa62b4c1 --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/reconfigure-form.schema.js @@ -0,0 +1,37 @@ +import { componentTypes } from '@@ddf'; +import { reconfigureFormFields } from './reconfigure-form-fields'; +import { networkFormFields } from './network-form-fields'; +import { diskFormFields } from './disk-form-fields'; +import { driveFormFields } from './drive-form-fields'; +import { TYPES } from './helpers/general'; + +export const createSchema = (recordId, data, setData, roles, options, memory, onCellClick, buttonClick) => { + let formFields; + + switch (data.form.type) { + case TYPES.DISK: + case TYPES.RESIZE: + formFields = diskFormFields(data, roles, options, memory); + break; + case TYPES.NETWORK: + case TYPES.EDITNETWORK: + formFields = networkFormFields(data, options, roles); + break; + case TYPES.DRIVE: + formFields = driveFormFields(data, options); + break; + default: + formFields = reconfigureFormFields(recordId, roles, memory, data, setData, options, onCellClick, buttonClick); + } + + const fields = [ + { + component: componentTypes.SUB_FORM, + name: 'BasicInformation', + title: data.form.title, + className: data.form.className, + fields: [formFields], + }, + ]; + return { fields }; +}; diff --git a/app/javascript/components/reconfigure-vm-form/reconfigure-table/index.jsx b/app/javascript/components/reconfigure-vm-form/reconfigure-table/index.jsx new file mode 100644 index 00000000000..a66a6b62d23 --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/reconfigure-table/index.jsx @@ -0,0 +1,54 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Button } from 'carbon-components-react'; +import MiqDataTable from '../../miq-data-table'; + +const ReconfigureTable = ({ + label, headers, rows, addButtonLabel, buttonClick, onCellClick, formType, +}) => { + const renderAddButton = () => addButtonLabel && ( + + ); + return ( +
+
+

{label}

+ {renderAddButton()} + onCellClick(selectedRow, cellType)} + mode={`${formType}-table-list`} + /> +
+ ); +}; + +ReconfigureTable.propTypes = { + label: PropTypes.string, + headers: PropTypes.arrayOf(PropTypes.any), + rows: PropTypes.arrayOf(PropTypes.any), + addButtonLabel: PropTypes.string, + formType: PropTypes.string, + onCellClick: PropTypes.func, + buttonClick: PropTypes.func, +}; + +ReconfigureTable.defaultProps = { + headers: undefined, + rows: undefined, + onCellClick: undefined, + buttonClick: undefined, + addButtonLabel: '', + formType: '', + label: '', +}; +export default ReconfigureTable; diff --git a/app/javascript/components/reconfigure-vm-form/reconfigure-template.jsx b/app/javascript/components/reconfigure-vm-form/reconfigure-template.jsx new file mode 100644 index 00000000000..7b971dcc296 --- /dev/null +++ b/app/javascript/components/reconfigure-vm-form/reconfigure-template.jsx @@ -0,0 +1,43 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { useFormApi } from '@data-driven-forms/react-form-renderer'; + +const ReconfigureTemplate = ({ + formFields, canSubmit, +}) => { + const { + handleSubmit, onReset, onCancel, getState, + } = useFormApi(); + const { submitting, valid, pristine } = getState(); + let formContent = ''; + if (formFields) { + formContent = formFields; + } + const submitValue = canSubmit ? false : (submitting || pristine); + + return ( +
+ {formContent} + +
+ + + +
+
+ ); +}; + +ReconfigureTemplate.propTypes = { + // eslint-disable-next-line react/require-default-props + formFields: PropTypes.node, + canSubmit: PropTypes.bool, + hideButtons: PropTypes.bool, +}; + +ReconfigureTemplate.defaultProps = { + canSubmit: false, + hideButtons: false, +}; + +export default ReconfigureTemplate; diff --git a/app/javascript/oldjs/controllers/index.js b/app/javascript/oldjs/controllers/index.js index 6bd8edd0cb2..dfe526f0d75 100644 --- a/app/javascript/oldjs/controllers/index.js +++ b/app/javascript/oldjs/controllers/index.js @@ -12,5 +12,4 @@ require('./error_modal_controller.js'); require('./miq_ae_class/ae_inline_method_selection_controller.js'); require('./ops/pglogical_replication_form_controller.js'); require('./playbook-reusable-code-mixin.js'); -require('./reconfigure/reconfigure_form_controller.js'); require('./tree_view_controller.js'); diff --git a/app/javascript/oldjs/controllers/reconfigure/reconfigure_form_controller.js b/app/javascript/oldjs/controllers/reconfigure/reconfigure_form_controller.js deleted file mode 100644 index 9c99329b7b7..00000000000 --- a/app/javascript/oldjs/controllers/reconfigure/reconfigure_form_controller.js +++ /dev/null @@ -1,609 +0,0 @@ -ManageIQ.angular.app.controller('reconfigureFormController', ['$http', '$scope', 'reconfigureFormId', 'objectIds', 'miqService', function($http, $scope, reconfigureFormId, objectIds, miqService) { - var vm = this; - var init = function() { - vm.reconfigureModel = { - memory: '0', - memory_type: '', - socket_count: '1', - cores_per_socket_count: '1', - total_cpus: '1', - vmdisks: [], - hdType: 'thin', - hdMode: 'persistent', - hdSize: '', - hdUnit: 'MB', - new_controller_type: 'VirtualLsiLogicController', - cb_dependent: true, - nicsEnabled: false, - addEnabled: false, - cdRomConnectEnabled: false, - enableAddDiskButton: true, - enableAddNetworkAdapterButton: true, - enableConnectCDRomButton: true, - cb_bootable: false, - vmAddDisks: [], - vmRemoveDisks: [], - vmResizeDisks: [], - vLan_requested: '', - adapterNetwork: '', - availableAdapterNetworks: [], - cdRom: '', - vmCDRoms: [], - }; - vm.cb_disks = false; - vm.cb_networkAdapters = false; - vm.cb_cdRoms = false; - vm.hdpattern = '^[1-9][0-9]*$'; - vm.reconfigureFormId = reconfigureFormId; - vm.afterGet = false; - vm.objectIds = objectIds; - vm.cb_memory = vm.cb_memoryCopy = false; - vm.cb_cpu = vm.cb_cpuCopy = false; - vm.mem_type_prev = vm.reconfigureModel.memory_type; - vm.validateClicked = miqService.validateWithAjax; - vm.modelCopy = angular.copy( vm.reconfigureModel ); - vm.model = 'reconfigureModel'; - vm.vm_vendor = ''; - vm.vm_type = ''; - vm.disk_default_type = ''; - vm.availableIsoFiles = []; - vm.selected_iso = ['', null]; - - ManageIQ.angular.scope = $scope; - - if (reconfigureFormId === 'new') { - vm.newRecord = true; - } else { - vm.newRecord = false; - } - - miqService.sparkleOn(); - $http.get('reconfigure_form_fields/' + reconfigureFormId + ',' + vm.objectIds) - .then(getReconfigureFormData) - .catch(miqService.handleFailure); - }; - - vm.setEnableAddDiskButton = function() { - var nrDisksAfterReconfigure = 0; - angular.forEach(vm.reconfigureModel.vmdisks, function(disk) { - switch (disk.add_remove) { - case 'remove': - break; - default: - nrDisksAfterReconfigure++; - break; - } - }); - vm.reconfigureModel.enableAddDiskButton = (nrDisksAfterReconfigure < 4); - }; - - vm.setEnableAddNetworkAdapterButton = function() { - var nrNetworksAfterReconfigure = _.reject(vm.reconfigureModel.vmNetworkAdapters, { add_remove: 'remove' }).length; - vm.reconfigureModel.enableAddNetworkAdapterButton = (nrNetworksAfterReconfigure < 4); - }; - - vm.canValidateBasicInfo = function() { - if (vm.isBasicInfoValid()) { - return true; - } - return false; - }; - - vm.isBasicInfoValid = function() { - if (($scope.angularForm.memory && !$scope.angularForm.memory.$valid) || - ($scope.angularForm.socket_count && !$scope.angularForm.socket_count.$valid) || - ($scope.angularForm.mem_type && !$scope.angularForm.mem_type.$valid) || - ($scope.angularForm.cores_per_socket_count && !$scope.angularForm.cores_per_socket_count.$valid) || - ($scope.angularForm.total_cpus && !$scope.angularForm.total_cpus.$valid) || - ($scope.angularForm.hdSize && !$scope.angularForm.hdSize.$valid)) { - return false; - } - return true; - }; - - vm.cbChange = function() { - var memUnchanged = false; - var cpuUnchanged = false; - miqService.miqFlashClear(); - - if (!vm.newRecord) { - return; - } - $scope.angularForm.$setValidity('unchanged', true); - - if (vm.cb_memory) { - var memorynow = vm.reconfigureModel.memory; - var memoryprev = vm.modelCopy.memory; - if (vm.reconfigureModel.memory_type === 'GB') { - memorynow *= 1024; - } - if (vm.modelCopy.memory_type === 'GB') { - memoryprev *= 1024; - } - if (memorynow === memoryprev) { - memUnchanged = true; - } - } - - if (vm.cb_cpu && ((vm.reconfigureModel.socket_count === vm.modelCopy.socket_count)) && - (vm.reconfigureModel.cores_per_socket_count === vm.modelCopy.cores_per_socket_count)) { - cpuUnchanged = true; - } - - if (vm.cb_memory && vm.cb_cpu && memUnchanged && cpuUnchanged) { - miqService.miqFlash('warn', __('Change Memory and Processor value to submit reconfigure request')); - $scope.angularForm.$setValidity('unchanged', false); - } else { - if (vm.cb_memory && memUnchanged) { - miqService.miqFlash('warn', __('Change Memory value to submit reconfigure request')); - $scope.angularForm.$setValidity('unchanged', false); - } - if (vm.cb_cpu && cpuUnchanged) { - miqService.miqFlash('warn', __('Change Processor Sockets or Cores Per Socket value to submit reconfigure request')); - $scope.angularForm.$setValidity('unchanged', false); - } - } - }; - - vm.processorValueChanged = function() { - if (vm.reconfigureModel.socket_count !== '' && vm.reconfigureModel.cores_per_socket_count !== '') { - var vtotalCpus = parseInt(vm.reconfigureModel.socket_count, 10) * parseInt(vm.reconfigureModel.cores_per_socket_count, 10); - vm.reconfigureModel.total_cpus = vtotalCpus.toString(); - } - vm.cbChange(); - }; - - vm.memtypeChanged = function() { - if (vm.reconfigureModel.memory_type === 'GB' && vm.mem_type_prev === 'MB') { - vm.reconfigureModel.memory = ~~(parseInt(vm.reconfigureModel.memory, 10) / 1024); - } else if (vm.reconfigureModel.memory_type === 'MB' && vm.mem_type_prev === 'GB') { - vm.reconfigureModel.memory = parseInt(vm.reconfigureModel.memory, 10) * 1024; - } - vm.mem_type_prev = vm.reconfigureModel.memory_type; - $scope.angularForm.memory.$validate(); - vm.cbChange(); - }; - - vm.updateDisksAddRemove = function() { - vm.reconfigureModel.vmAddDisks = []; - vm.reconfigureModel.vmRemoveDisks = []; - vm.reconfigureModel.vmResizeDisks = []; - angular.forEach(vm.reconfigureModel.vmdisks, function(disk) { - if (disk.add_remove === 'remove') { - vm.reconfigureModel.vmRemoveDisks.push({ - disk_name: disk.hdFilename, - delete_backing: disk.delete_backing}); - } else if (disk.add_remove === 'resize') { - var diskSizeResize = parseInt(disk.hdSize, 10); - if (disk.hdUnit === 'GB') { - diskSizeResize *= 1024; - } - vm.reconfigureModel.vmResizeDisks.push({ - disk_name: disk.hdFilename, - disk_size_in_mb: diskSizeResize}); - } else if (disk.add_remove === 'add') { - var diskSizeAdd = parseInt(disk.hdSize, 10); - if (disk.hdUnit === 'GB') { - diskSizeAdd *= 1024; - } - var dmode = (disk.hdMode === 'persistent'); - var dtype = (disk.hdType === 'thin'); - vm.reconfigureModel.vmAddDisks.push({disk_size_in_mb: diskSizeAdd, - persistent: dmode, - thin_provisioned: dtype, - type: disk.hdType, - new_controller_type: disk.new_controller_type, - dependent: disk.cb_dependent, - bootable: disk.cb_bootable}); - } else if (disk.add_remove === '') { - disk.delete_backing = false; - } - }); - if (vm.reconfigureModel.vmAddDisks.length > 0 || - vm.reconfigureModel.vmRemoveDisks.length > 0 || - vm.reconfigureModel.vmResizeDisks.length > 0) { - vm.cb_disks = true; - } else { - vm.cb_disks = false; - } - vm.setEnableAddDiskButton(); - }; - - vm.updateNetworkAdaptersAddRemove = function() { - vm.reconfigureModel.vmEditNetworkAdapters = []; - vm.reconfigureModel.vmAddNetworkAdapters = []; - vm.reconfigureModel.vmRemoveNetworkAdapters = []; - angular.forEach(vm.reconfigureModel.vmNetworkAdapters, function(networkAdapter) { - if (networkAdapter.add_remove === 'add') { - vm.reconfigureModel.vmAddNetworkAdapters.push( - { - network: networkAdapter.vlan, - name: networkAdapter.name, - cloud_network: networkAdapter.network, - } - ); - } - else if (networkAdapter.add_remove === 'remove') { - vm.reconfigureModel.vmRemoveNetworkAdapters.push({network: networkAdapter}); - } - else if (networkAdapter.add_remove === 'edit') { - vm.reconfigureModel.vmEditNetworkAdapters.push( - { - network: networkAdapter.vlan, - name: networkAdapter.name, - cloud_network: networkAdapter.network, - } - ); - } - }); - vm.setEnableAddNetworkAdapterButton(); - vm.cb_networkAdapters = vm.reconfigureModel.vmAddNetworkAdapters.length > 0 || - vm.reconfigureModel.vmRemoveNetworkAdapters.length > 0 || - vm.reconfigureModel.vmEditNetworkAdapters.length > 0; - }; - - vm.resetAddValues = function() { - vm.reconfigureModel.hdType = vm.disk_default_type; - vm.reconfigureModel.hdMode = 'persistent'; - vm.reconfigureModel.hdSize = ''; - vm.reconfigureModel.hdUnit = 'MB'; - vm.reconfigureModel.new_controller_type = 'VirtualLsiLogicController'; - vm.reconfigureModel.cb_dependent = true; - vm.reconfigureModel.addEnabled = false; - vm.reconfigureModel.cb_bootable = false; - }; - - vm.validateAddSelectedNetwork = function() { - if (!vm.reconfigureModel.vLan_requested && !vm.isVmwareCloud()) { - return false; - } else if (!vm.reconfigureModel.name && vm.isVmwareCloud()) { - return false; - } else if (vm.reconfigureModel.vmNetworkAdapters.length > 4) { - return false; - } - return true; - }; - - vm.validateEditSelectedNetwork = function(networkAdapter) { - if (! networkAdapter.vLan_edit_requested && ! vm.isVmwareCloud()) { - return false; - } else if (! vm.reconfigureModel.name && vm.isVmwareCloud()) { - return false; - } else if (vm.reconfigureModel.vmNetworkAdapters.length > 4) { - return false; - } - return true; - }; - - vm.processAddSelectedNetwork = function() { - vm.reconfigureModel.vmNetworkAdapters.push( - { - name: vm.reconfigureModel.name ? vm.reconfigureModel.name : __('to be determined'), - vlan: vm.reconfigureModel.vLan_requested, - network: vm.reconfigureModel.adapterNetwork, - mac: __('not available yet'), - add_remove: 'add', - }); - vm.resetAddNetworkAdapterValues(); - vm.updateNetworkAdaptersAddRemove(); - }; - - vm.removeExistingNetworkAdapter = function(thisNetworkAdapter) { - thisNetworkAdapter.add_remove = 'remove'; - vm.updateNetworkAdaptersAddRemove(); - }; - - vm.editExistingNetworkAdapter = function(thisNetworkAdapter) { - thisNetworkAdapter.vLan_edit_requested = null; - thisNetworkAdapter.add_remove = 'update'; - thisNetworkAdapter.originalVLan = thisNetworkAdapter.vlan; - vm.updateNetworkAdaptersAddRemove(); - }; - - vm.cancelChangeExistingNetworkAdapter = function(thisNetworkAdapter) { - thisNetworkAdapter.vLan_edit_requested = null; - thisNetworkAdapter.vlan = thisNetworkAdapter.originalVLan; - thisNetworkAdapter.add_remove = ''; - vm.updateNetworkAdaptersAddRemove(); - }; - - vm.confirmEditSelectedNetworkAdapter = function(networkAdapter) { - networkAdapter.originalVLan = networkAdapter.vlan; - networkAdapter.vlan = networkAdapter.vLan_edit_requested; - networkAdapter.add_remove = 'edit'; - vm.updateNetworkAdaptersAddRemove(); - }; - - vm.checkEditNetworkAdapter = function() { - return _.some(vm.reconfigureModel.vmNetworkAdapters, ['add_remove', 'update'] ); - }; - - vm.enableAddNetworkAdapter = function() { - vm.reconfigureModel.nicsEnabled = true; - vm.reconfigureModel.enableAddNetworkAdapterButton = false; - vm.reconfigureModel.showDropDownNetwork = true; - vm.reconfigureModel.vLan_requested = ''; - }; - - vm.hideAddNetworkAdapter = function() { - vm.resetAddNetworkAdapterValues(); - }; - - vm.resetAddNetworkAdapterValues = function() { - vm.reconfigureModel.nicsEnabled = false; - vm.reconfigureModel.addNetworkAdapterEnabled = false; - vm.reconfigureModel.showDropDownNetwork = false; - vm.setEnableAddNetworkAdapterButton(); - vm.reconfigureModel.vLan_requested = ''; - vm.reconfigureModel.name = ''; - vm.reconfigureModel.adapterNetwork = ''; - }; - - vm.cancelAddRemoveNetworkAdapter = function(vmNetworkAdapter) { - if (vmNetworkAdapter.add_remove === 'remove' || vmNetworkAdapter.add_remove === 'edit' ) { - vmNetworkAdapter.add_remove = ''; - } else if (vmNetworkAdapter.add_remove === 'add') { - var index = vm.reconfigureModel.vmNetworkAdapters.indexOf(vmNetworkAdapter); - vm.reconfigureModel.vmNetworkAdapters.splice(index, 1); - } - vm.updateNetworkAdaptersAddRemove(); - }; - - vm.addDisk = function() { - vm.reconfigureModel.vmdisks.push({ - hdFilename: '', - hdType: vm.reconfigureModel.hdType, - hdMode: vm.reconfigureModel.hdMode, - hdSize: vm.reconfigureModel.hdSize, - hdUnit: vm.reconfigureModel.hdUnit, - new_controller_type: vm.reconfigureModel.new_controller_type, - cb_dependent: vm.reconfigureModel.cb_dependent, - cb_bootable: vm.reconfigureModel.cb_bootable, - add_remove: 'add'}); - vm.resetAddValues(); - vm.updateDisksAddRemove(); - }; - - vm.enableDiskAdd = function() { - vm.resetAddValues(); - vm.reconfigureModel.addEnabled = true; - }; - - vm.hideAddDisk = function() { - vm.reconfigureModel.addEnabled = false; - vm.resetAddValues(); - }; - - vm.enableResizeDisk = function(disk) { - disk.add_remove = 'resizing'; - }; - - vm.resizeDisk = function(disk) { - disk.add_remove = 'resize'; - vm.updateDisksAddRemove(); - }; - - vm.resizeDiskUnitChanged = function(disk) { - if (disk.hdUnit === 'MB') { - disk.hdSize = disk.hdSize * 1024; - } else if ((disk.hdSize % 1024) === 0) { - disk.hdSize = disk.hdSize / 1024; - } else { - disk.hdSize = ''; - } - }; - - vm.deleteDisk = function(name) { - for (var disk in vm.reconfigureModel.vmdisks) { - if (vm.reconfigureModel.vmdisks[disk].hdFilename === name) { - vm.reconfigureModel.vmdisks[disk].add_remove = 'remove'; - } - } - vm.updateDisksAddRemove(); - }; - - vm.cancelAddRemoveDisk = function(vmDisk) { - switch (vmDisk.add_remove) { - case 'remove': - vmDisk.add_remove = ''; - vmDisk.cb_deletebacking = false; - vmDisk.cb_bootable = false; - break; - case 'resize': - case 'resizing': - vmDisk.add_remove = ''; - vmDisk.hdSize = vmDisk.orgHdSize; - vmDisk.hdUnit = vmDisk.orgHdUnit; - break; - case 'add': - var index = vm.reconfigureModel.vmdisks.indexOf(vmDisk); - vm.reconfigureModel.vmdisks.splice(index, 1); - break; - default: - break; - } - vm.updateDisksAddRemove(); - }; - - var reconfigureEditButtonClicked = function(buttonName, serializeFields) { - miqService.sparkleOn(); - var url = 'reconfigure_update/' + reconfigureFormId + '?button=' + buttonName; - if (typeof serializeFields === 'undefined') { - miqService.miqAjaxButton(url); - } else { - miqService.miqAjaxButton(url, {objectIds: vm.objectIds, - cb_memory: vm.cb_memory, - cb_cpu: vm.cb_cpu, - memory: vm.reconfigureModel.memory, - memory_type: vm.reconfigureModel.memory_type, - socket_count: vm.reconfigureModel.socket_count, - cores_per_socket_count: vm.reconfigureModel.cores_per_socket_count, - vmAddDisks: vm.reconfigureModel.vmAddDisks, - vmRemoveDisks: vm.reconfigureModel.vmRemoveDisks, - vmResizeDisks: vm.reconfigureModel.vmResizeDisks, - vmAddNetworkAdapters: vm.reconfigureModel.vmAddNetworkAdapters, - vmRemoveNetworkAdapters: vm.reconfigureModel.vmRemoveNetworkAdapters, - vmEditNetworkAdapters: vm.reconfigureModel.vmEditNetworkAdapters, - vmConnectCDRoms: vm.reconfigureModel.vmConnectCDRoms, - vmDisconnectCDRoms: vm.reconfigureModel.vmDisconnectCDRoms, - }); - } - }; - - vm.cancelClicked = function() { - miqService.sparkleOn(); - miqService.miqAjaxButton('reconfigure_update?button=cancel'); - }; - - vm.resetClicked = function() { - $scope.$broadcast('resetClicked'); - vm.reconfigureModel = angular.copy(vm.modelCopy); - vm.cb_memory = vm.cb_memoryCopy; - vm.cb_cpu = vm.cb_cpuCopy; - vm.mem_type_prev = vm.reconfigureModel.memory_type; - - angular.forEach(vm.reconfigureModel.vmdisks, function(disk) { - vm.cancelAddRemoveDisk(disk); - }); - - angular.forEach(vm.reconfigureModel.vmCDRoms, function(cd) { - vm.cancelCDRomConnectDisconnect(cd); - }); - - $scope.angularForm.$setPristine(true); - vm.updateDisksAddRemove(); - vm.updateCDRomsConnectDisconnect(); - - miqService.miqFlash('warn', __('All changes have been reset')); - }; - - vm.submitClicked = function() { - // change memory value based ontype - reconfigureEditButtonClicked('submit', true); - }; - - vm.addClicked = function() { - vm.submitClicked(); - }; - - vm.isVmwareCloud = function() { - return vm.vm_vendor === 'vmware' && vm.vm_type.includes('CloudManager'); - }; - - vm.fetchAvailableAdapterNetworks = function(orchestrationStackId) { - API.get('/api/cloud_networks?expand=resources&attributes=name&filter[]=orchestration_stack_id=' + orchestrationStackId).then(function(data) { - vm.reconfigureModel.availableAdapterNetworks = data.resources.map(function(network) { - return network.name; - }); - }).catch(miqService.handleFailure); - }; - - function getReconfigureFormData(response) { - var data = response.data; - vm.reconfigureModel.memory = data.memory; - vm.reconfigureModel.memory_type = data.memory_type; - vm.reconfigureModel.socket_count = data.socket_count; - vm.reconfigureModel.cores_per_socket_count = data.cores_per_socket_count; - vm.mem_type_prev = vm.reconfigureModel.memory_type; - vm.cb_memory = data.cb_memory; - vm.cb_cpu = data.cb_cpu; - vm.reconfigureModel.vmdisks = angular.copy(data.disks); - vm.reconfigureModel.vmNetworkAdapters = angular.copy(data.network_adapters); - vm.reconfigureModel.vmCDRoms = angular.copy(data.cdroms); - vm.vm_vendor = data.vm_vendor; - vm.vm_type = data.vm_type; - vm.disk_default_type = data.disk_default_type; - vm.updateDisksAddRemove(); - vm.updateNetworkAdaptersAddRemove(); - vm.updateCDRomsConnectDisconnect(); - - angular.forEach(vm.reconfigureModel.vmdisks, function(disk) { - if (typeof disk !== 'undefined') { - disk.orgHdSize = disk.hdSize; - disk.orgHdUnit = disk.hdUnit; - if ( disk.add_remove !== 'add' && disk.add_remove !== 'remove' ) { - disk.delete_backing = false; - } - } - }); - if (data.socket_count && data.cores_per_socket_count) { - vm.reconfigureModel.total_cpus = (parseInt(vm.reconfigureModel.socket_count, 10) * parseInt(vm.reconfigureModel.cores_per_socket_count, 10)).toString(); - } - - angular.forEach(vm.reconfigureModel.vmCDRoms, function(cdRom) { - if (typeof cdRom !== 'undefined') { - cdRom.orgFilename = cdRom.filename; - cdRom.connect_disconnect = ''; - cdRom.connected = cdRom.device_type === 'cdrom_image'; - } - }); - - if (data.socket_count && data.cores_per_socket_count) { - vm.reconfigureModel.total_cpus = (parseInt(vm.reconfigureModel.socket_count, 10) * parseInt(vm.reconfigureModel.cores_per_socket_count, 10)).toString(); - } - - if (vm.isVmwareCloud()) { - vm.fetchAvailableAdapterNetworks(data.orchestration_stack_id); - } - - vm.afterGet = true; - vm.modelCopy = angular.copy( vm.reconfigureModel ); - vm.cb_memoryCopy = vm.cb_memory; - vm.cb_cpuCopy = vm.cb_cpu; - miqService.sparkleOff(); - } - - vm.updateCDRomsConnectDisconnect = function() { - vm.reconfigureModel.vmConnectCDRoms = []; - vm.reconfigureModel.vmDisconnectCDRoms = []; - angular.forEach(vm.reconfigureModel.vmCDRoms, function(cdRom) { - if (cdRom.connect_disconnect === 'connect') { - vm.reconfigureModel.vmConnectCDRoms.push( - { device_name: cdRom.device_name, - filename: cdRom.filename, - storage_id: cdRom.storage_id, - } - ); - } - if (cdRom.connect_disconnect === 'disconnect') { - vm.reconfigureModel.vmDisconnectCDRoms.push( - { device_name: cdRom.device_name }); - } - }); - vm.cb_cdRoms = vm.reconfigureModel.vmConnectCDRoms.length > 0 || - vm.reconfigureModel.vmDisconnectCDRoms.length > 0; - }; - - - vm.connectCDRom = function(cdRom) { - var iso = vm.selected_iso.split(','); - cdRom.filename = iso[0]; - cdRom.storage_id = iso[1]; - cdRom.connect_disconnect = 'connect'; - vm.updateCDRomsConnectDisconnect(); - }; - - vm.disconnectCDRom = function(cdRom) { - cdRom.connect_disconnect = 'disconnect'; - cdRom.filename = ''; - vm.updateCDRomsConnectDisconnect(); - }; - - vm.enableConnectCDRom = function(cdRom) { - cdRom.connect_disconnect = 'connecting'; - }; - - vm.enableDisconnectCDRom = function(cdRom) { - cdRom.filename = ''; - cdRom.connect_disconnect = 'disconnecting'; - }; - - vm.cancelCDRomConnectDisconnect = function(vmCDRom) { - var index = vm.reconfigureModel.vmCDRoms.indexOf(vmCDRom); - vmCDRom.filename = vmCDRom.orgFilename; - vmCDRom.connect_disconnect = ''; - vm.reconfigureModel.vmCDRoms[index].connect_disconnect = ''; - }; - - init(); -}]); diff --git a/app/javascript/packs/component-definitions-common.js b/app/javascript/packs/component-definitions-common.js index 7737ca332b2..530278e78e0 100644 --- a/app/javascript/packs/component-definitions-common.js +++ b/app/javascript/packs/component-definitions-common.js @@ -37,6 +37,7 @@ import Datastore from '../components/data-tables/datastore'; import DatastoreForm from '../components/data-store-form'; import DbList from '../components/data-tables/db-list'; import DiagnosticsCollectLogForm from '../components/diagnostics-collect-log-form'; +import ReconfigureTable from '../components/reconfigure-vm-form/reconfigure-table'; import EvacuateForm from '../components/evacuate-form'; import EventChart from "../components/provider-dashboard-charts/events-bar-chart"; import FlavorForm from '../components/flavor-form'; @@ -90,6 +91,7 @@ import PolicyProfileForm from '../components/policy-profile-form'; import PfAggregateStatusCard from '../components/pf_aggregate_status_card'; import RecentHostGraph from '../components/provider-dashboard-charts/recent-host-chart'; import RecentVmGraph from '../components/provider-dashboard-charts/recent-vm-chart'; +import ReconfigureVmForm from '../components/reconfigure-vm-form'; import RefreshDataNotification from '../components/refresh-data-notification'; import RegionForm from '../components/region-form'; import RemoveCatalogItemModal from '../components/remove-catalog-item-modal'; @@ -196,6 +198,7 @@ ManageIQ.component.addReact('Datastore', Datastore); ManageIQ.component.addReact('DatastoreForm', DatastoreForm); ManageIQ.component.addReact('DbList', DbList); ManageIQ.component.addReact('DiagnosticsCollectLogForm', DiagnosticsCollectLogForm); +ManageIQ.component.addReact('ReconfigureTable', ReconfigureTable); ManageIQ.component.addReact('EvacuateForm', EvacuateForm); ManageIQ.component.addReact('EventChart', EventChart); ManageIQ.component.addReact('FirmwareRegistryForm', FirmwareRegistryForm); @@ -251,6 +254,7 @@ ManageIQ.component.addReact('PfAggregateStatusCard', PfAggregateStatusCard); ManageIQ.component.addReact('Quadicon', Quadicon); ManageIQ.component.addReact('RecentHostGraph', RecentHostGraph); ManageIQ.component.addReact('RecentVmGraph', RecentVmGraph); +ManageIQ.component.addReact('ReconfigureVmForm', ReconfigureVmForm); ManageIQ.component.addReact('RefreshDataNotification', RefreshDataNotification); ManageIQ.component.addReact('RegionForm', RegionForm); ManageIQ.component.addReact('RemoveCatalogItemModal', RemoveCatalogItemModal); diff --git a/app/javascript/spec/prov-grid/__snapshots__/prov-grid.spec.js.snap b/app/javascript/spec/prov-grid/__snapshots__/prov-grid.spec.js.snap index c3a4df54f6a..6f8148b455d 100644 --- a/app/javascript/spec/prov-grid/__snapshots__/prov-grid.spec.js.snap +++ b/app/javascript/spec/prov-grid/__snapshots__/prov-grid.spec.js.snap @@ -695,6 +695,7 @@ exports[`ProvGrid component should render prov_ds_grid table 1`] = `
+ + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Name +
+
+
+ Type +
+
+
+ Size +
+
+
+ Unit +
+
+
+ Mode +
+
+
+ Controller Type +
+
+
+ Dependent +
+
+
+ Delete Backing +
+
+
+ Bootable +
+
+
+ Resize +
+
+
+ Action +
+
+
+ + disk test 2 + +
+
+
+ + thin + +
+
+
+ + 16 + +
+
+
+ + GB + +
+
+
+ + persistent + +
+
+
+ + None + +
+
+
+ + No + +
+
+
+ + + + } + onToggle={[Function]} + tabIndex={0} + toggled={false} + > + + + + } + onToggle={[Function]} + tabIndex={0} + toggled={false} + > +
+ + +
+
+
+
+
+
+ + No + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+ + + + + + + + + + +
+
+

+ Network Adapters +

+ + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Name +
+
+
+ MAC address +
+
+
+ vLan +
+
+
+ Edit +
+
+
+ Action +
+
+
+ + +
+ + +
+
+
+
+ + + + +
+
+

+ CD/DVD Drives +

+ +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Name +
+
+
+ Host File +
+
+
+ Disconnect +
+
+
+ Actions +
+
+
+ + CD/DVD drive 1 + +
+
+
+ +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+ + +
+
+
+
+ + + + + + + + + + + + + + +
+ + + +
+ +
+ + + +
+ + + +`; + +exports[`Reconfigure VM form component should render reconfigure form and show cd rom connect form 1`] = ` + + + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + ], + ], + "name": "BasicInformation", + "title": "Connect CD/DVD Drives", + }, + ], + } + } + validatorMapper={ + Object { + "cpuCheck": [Function], + "customRequired": [Function], + "diskMemoryCheck": [Function], + "memoryCheck": [Function], + } + } + > + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + ], + ], + "name": "BasicInformation", + "title": "Connect CD/DVD Drives", + }, + ], + } + } + showFormControls={true} + validatorMapper={ + Object { + "cpuCheck": [Function], + "customRequired": [Function], + "diskMemoryCheck": [Function], + "memoryCheck": [Function], + } + } + > + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + ], + ], + "name": "BasicInformation", + "title": "Connect CD/DVD Drives", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + validatorMapper={ + Object { + "cpuCheck": [Function], + "customRequired": [Function], + "diskMemoryCheck": [Function], + "memoryCheck": [Function], + } + } + > + + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + ], + ] + } + name="BasicInformation" + title="Connect CD/DVD Drives" + />, + , + ] + } + schema={ + Object { + "fields": Array [ + Object { + "className": "drive_form", + "component": "sub-form", + "fields": Array [ + Array [ + Object { + "autoFocus": true, + "component": "text-field", + "id": "name", + "initialValue": "CD/DVD drive 1", + "isReadOnly": true, + "label": "Name", + "name": "name", + }, + Object { + "component": "select", + "id": "host_file", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "Host File", + "name": "host_file", + "options": Array [ + Object { + "label": "host file test 1.iso", + "value": "host file test 1.iso,18", + }, + Object { + "label": "host file test 2.iso", + "value": "host file test 2.iso,18", + }, + Object { + "label": "host file test 3.iso", + "value": "host file test 3.iso,18", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + ], + ], + "name": "BasicInformation", + "title": "Connect CD/DVD Drives", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + > + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + ], + ] + } + name="BasicInformation" + title="Connect CD/DVD Drives" + />, + , + ] + } + hideButtons={false} + schema={ + Object { + "fields": Array [ + Object { + "className": "drive_form", + "component": "sub-form", + "fields": Array [ + Array [ + Object { + "autoFocus": true, + "component": "text-field", + "id": "name", + "initialValue": "CD/DVD drive 1", + "isReadOnly": true, + "label": "Name", + "name": "name", + }, + Object { + "component": "select", + "id": "host_file", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "Host File", + "name": "host_file", + "options": Array [ + Object { + "label": "host file test 1.iso", + "value": "host file test 1.iso,18", + }, + Object { + "label": "host file test 2.iso", + "value": "host file test 2.iso,18", + }, + Object { + "label": "host file test 3.iso", + "value": "host file test 3.iso,18", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + ], + ], + "name": "BasicInformation", + "title": "Connect CD/DVD Drives", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + > +
+ ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + ], + ] + } + key="BasicInformation" + name="BasicInformation" + title="Connect CD/DVD Drives" + > + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + ], + ], + "name": "BasicInformation", + "title": "Connect CD/DVD Drives", + } + } + > + + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + ], + ] + } + name="BasicInformation" + title="Connect CD/DVD Drives" + > +
+
+

+ Connect CD/DVD Drives +

+
+ + + + + +
+ +
+
+ + + + + + + + +
+
+
+
+
+
+
+
+ + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + } + } + > + + + + Host File + + } + loadOptionsChangeCounter={1} + loadingMessage="Loading..." + name="host_file" + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + options={ + Array [ + Object { + "label": "", + "value": undefined, + }, + Object { + "label": "host file test 1.iso", + "value": "host file test 1.iso,18", + }, + Object { + "label": "host file test 2.iso", + "value": "host file test 2.iso,18", + }, + Object { + "label": "host file test 3.iso", + "value": "host file test 3.iso,18", + }, + ] + } + placeholder="" + pluckSingleValue={true} + simpleValue={false} + value="" + > + + Host File + + } + name="host_file" + noOptionsMessage={[Function]} + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + onInputChange={[Function]} + options={ + Array [ + Object { + "label": "", + "value": undefined, + }, + Object { + "label": "host file test 1.iso", + "value": "host file test 1.iso,18", + }, + Object { + "label": "host file test 2.iso", + "value": "host file test 2.iso,18", + }, + Object { + "label": "host file test 3.iso", + "value": "host file test 3.iso,18", + }, + ] + } + placeholder="" + value="" + > + + + + + + + + + + + + + +
+ + + + + + + +
+
+
+ + + + + + + + + + + + + + +
+ + + +
+
+
+
+
+
+
+
+
+
+`; + +exports[`Reconfigure VM form component should render reconfigure form and show disk add form 1`] = ` + + + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 1, + "type": "diskMemoryCheck", + "unit": "MB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "", + "isReadOnly": false, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "controller", + "initialValue": "", + "isReadOnly": false, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": false, + "hideField": false, + "id": "dependent", + "initialValue": "", + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": "", + "isReadOnly": false, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ], + "name": "BasicInformation", + "title": "Add Disk", + }, + ], + } + } + validatorMapper={ + Object { + "cpuCheck": [Function], + "customRequired": [Function], + "diskMemoryCheck": [Function], + "memoryCheck": [Function], + } + } + > + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 1, + "type": "diskMemoryCheck", + "unit": "MB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "", + "isReadOnly": false, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "controller", + "initialValue": "", + "isReadOnly": false, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": false, + "hideField": false, + "id": "dependent", + "initialValue": "", + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": "", + "isReadOnly": false, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ], + "name": "BasicInformation", + "title": "Add Disk", + }, + ], + } + } + showFormControls={true} + validatorMapper={ + Object { + "cpuCheck": [Function], + "customRequired": [Function], + "diskMemoryCheck": [Function], + "memoryCheck": [Function], + } + } + > + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 1, + "type": "diskMemoryCheck", + "unit": "MB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "", + "isReadOnly": false, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "controller", + "initialValue": "", + "isReadOnly": false, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": false, + "hideField": false, + "id": "dependent", + "initialValue": "", + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": "", + "isReadOnly": false, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ], + "name": "BasicInformation", + "title": "Add Disk", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + validatorMapper={ + Object { + "cpuCheck": [Function], + "customRequired": [Function], + "diskMemoryCheck": [Function], + "memoryCheck": [Function], + } + } + > + + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 1, + "type": "diskMemoryCheck", + "unit": "MB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "", + "isReadOnly": false, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "controller", + "initialValue": "", + "isReadOnly": false, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": false, + "hideField": false, + "id": "dependent", + "initialValue": "", + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": "", + "isReadOnly": false, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ] + } + name="BasicInformation" + title="Add Disk" + />, + , + ] + } + schema={ + Object { + "fields": Array [ + Object { + "className": "disk_form", + "component": "sub-form", + "fields": Array [ + Array [ + Object { + "component": "text-field", + "hideField": true, + "id": "name", + "initialValue": "", + "isReadOnly": true, + "label": "Name", + "name": "name", + }, + Object { + "autoFocus": true, + "component": "select", + "disabled": false, + "id": "type", + "includeEmpty": true, + "initialValue": "", + "isReadOnly": false, + "isRequired": true, + "label": "Type", + "name": "type", + "options": Array [ + Object { + "label": "thin", + "value": "thin", + }, + Object { + "label": "thick", + "value": "thick", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 1, + "type": "diskMemoryCheck", + "unit": "MB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "", + "isReadOnly": false, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "controller", + "initialValue": "", + "isReadOnly": false, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": false, + "hideField": false, + "id": "dependent", + "initialValue": "", + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": "", + "isReadOnly": false, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ], + "name": "BasicInformation", + "title": "Add Disk", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + > + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 1, + "type": "diskMemoryCheck", + "unit": "MB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "", + "isReadOnly": false, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "controller", + "initialValue": "", + "isReadOnly": false, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": false, + "hideField": false, + "id": "dependent", + "initialValue": "", + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": "", + "isReadOnly": false, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ] + } + name="BasicInformation" + title="Add Disk" + />, + , + ] + } + hideButtons={false} + schema={ + Object { + "fields": Array [ + Object { + "className": "disk_form", + "component": "sub-form", + "fields": Array [ + Array [ + Object { + "component": "text-field", + "hideField": true, + "id": "name", + "initialValue": "", + "isReadOnly": true, + "label": "Name", + "name": "name", + }, + Object { + "autoFocus": true, + "component": "select", + "disabled": false, + "id": "type", + "includeEmpty": true, + "initialValue": "", + "isReadOnly": false, + "isRequired": true, + "label": "Type", + "name": "type", + "options": Array [ + Object { + "label": "thin", + "value": "thin", + }, + Object { + "label": "thick", + "value": "thick", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 1, + "type": "diskMemoryCheck", + "unit": "MB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "", + "isReadOnly": false, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "controller", + "initialValue": "", + "isReadOnly": false, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": false, + "hideField": false, + "id": "dependent", + "initialValue": "", + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": "", + "isReadOnly": false, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ], + "name": "BasicInformation", + "title": "Add Disk", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + > +
+ ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 1, + "type": "diskMemoryCheck", + "unit": "MB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "", + "isReadOnly": false, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "controller", + "initialValue": "", + "isReadOnly": false, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": false, + "hideField": false, + "id": "dependent", + "initialValue": "", + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": "", + "isReadOnly": false, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ] + } + key="BasicInformation" + name="BasicInformation" + title="Add Disk" + > + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 1, + "type": "diskMemoryCheck", + "unit": "MB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "", + "isReadOnly": false, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "controller", + "initialValue": "", + "isReadOnly": false, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": false, + "hideField": false, + "id": "dependent", + "initialValue": "", + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": "", + "isReadOnly": false, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ], + "name": "BasicInformation", + "title": "Add Disk", + } + } + > + + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 1, + "type": "diskMemoryCheck", + "unit": "MB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "", + "isReadOnly": false, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": false, + "hideField": false, + "id": "controller", + "initialValue": "", + "isReadOnly": false, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": false, + "hideField": false, + "id": "dependent", + "initialValue": "", + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": "", + "isReadOnly": false, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ] + } + name="BasicInformation" + title="Add Disk" + > +
+
+

+ Add Disk +

+
+ + + + + + + + + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + } + } + > + + + + Type + + } + loadOptionsChangeCounter={1} + loadingMessage="Loading..." + name="type" + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + options={ + Array [ + Object { + "label": "", + "value": undefined, + }, + Object { + "label": "thin", + "value": "thin", + }, + Object { + "label": "thick", + "value": "thick", + }, + ] + } + placeholder="" + pluckSingleValue={true} + readOnly={false} + simpleValue={false} + value="" + > + + Type + + } + name="type" + noOptionsMessage={[Function]} + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + onInputChange={[Function]} + options={ + Array [ + Object { + "label": "", + "value": undefined, + }, + Object { + "label": "thin", + "value": "thin", + }, + Object { + "label": "thick", + "value": "thick", + }, + ] + } + placeholder="" + readOnly={false} + value="" + > + + + + + + + + + + + + +
+ + + + + + + +
+
+
+ + + + + + Size + + } + name="size" + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + value="" + warn={false} + warnText="" + > +
+ +
+
+ +
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + } + } + > + + + + Mode + + } + loadOptionsChangeCounter={1} + loadingMessage="Loading..." + name="mode" + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + options={ + Array [ + Object { + "label": "", + "value": undefined, + }, + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ] + } + placeholder="" + pluckSingleValue={true} + readOnly={false} + simpleValue={false} + value="" + > + + Mode + + } + name="mode" + noOptionsMessage={[Function]} + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + onInputChange={[Function]} + options={ + Array [ + Object { + "label": "", + "value": undefined, + }, + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ] + } + placeholder="" + readOnly={false} + value="" + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+
+ +
+
+
+
+
+ + + + +
+ + +
+ + +
+
+
+ +
+
+
+
+
+ + + + + + + + + + + + + + +
+ + + +
+
+
+
+
+
+
+
+
+
+`; + +exports[`Reconfigure VM form component should render reconfigure form and show disk resize form 1`] = ` + + + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "16", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 17, + "type": "diskMemoryCheck", + "unit": "GB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "GB", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "persistent", + "isReadOnly": true, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "controller", + "initialValue": "None", + "isReadOnly": true, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": true, + "hideField": false, + "id": "dependent", + "initialValue": false, + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": false, + "isReadOnly": true, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ], + "name": "BasicInformation", + "title": "Resize Disk", + }, + ], + } + } + validatorMapper={ + Object { + "cpuCheck": [Function], + "customRequired": [Function], + "diskMemoryCheck": [Function], + "memoryCheck": [Function], + } + } + > + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "16", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 17, + "type": "diskMemoryCheck", + "unit": "GB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "GB", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "persistent", + "isReadOnly": true, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "controller", + "initialValue": "None", + "isReadOnly": true, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": true, + "hideField": false, + "id": "dependent", + "initialValue": false, + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": false, + "isReadOnly": true, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ], + "name": "BasicInformation", + "title": "Resize Disk", + }, + ], + } + } + showFormControls={true} + validatorMapper={ + Object { + "cpuCheck": [Function], + "customRequired": [Function], + "diskMemoryCheck": [Function], + "memoryCheck": [Function], + } + } + > + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "16", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 17, + "type": "diskMemoryCheck", + "unit": "GB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "GB", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "persistent", + "isReadOnly": true, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "controller", + "initialValue": "None", + "isReadOnly": true, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": true, + "hideField": false, + "id": "dependent", + "initialValue": false, + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": false, + "isReadOnly": true, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ], + "name": "BasicInformation", + "title": "Resize Disk", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + validatorMapper={ + Object { + "cpuCheck": [Function], + "customRequired": [Function], + "diskMemoryCheck": [Function], + "memoryCheck": [Function], + } + } + > + + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "16", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 17, + "type": "diskMemoryCheck", + "unit": "GB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "GB", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "persistent", + "isReadOnly": true, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "controller", + "initialValue": "None", + "isReadOnly": true, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": true, + "hideField": false, + "id": "dependent", + "initialValue": false, + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": false, + "isReadOnly": true, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ] + } + name="BasicInformation" + title="Resize Disk" + />, + , + ] + } + schema={ + Object { + "fields": Array [ + Object { + "className": "disk_form", + "component": "sub-form", + "fields": Array [ + Array [ + Object { + "component": "text-field", + "hideField": false, + "id": "name", + "initialValue": "disk test 2", + "isReadOnly": true, + "label": "Name", + "name": "name", + }, + Object { + "autoFocus": true, + "component": "select", + "disabled": true, + "id": "type", + "includeEmpty": true, + "initialValue": "thin", + "isReadOnly": true, + "isRequired": true, + "label": "Type", + "name": "type", + "options": Array [ + Object { + "label": "thin", + "value": "thin", + }, + Object { + "label": "thick", + "value": "thick", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "16", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 17, + "type": "diskMemoryCheck", + "unit": "GB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "GB", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "persistent", + "isReadOnly": true, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "controller", + "initialValue": "None", + "isReadOnly": true, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": true, + "hideField": false, + "id": "dependent", + "initialValue": false, + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": false, + "isReadOnly": true, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ], + "name": "BasicInformation", + "title": "Resize Disk", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + > + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "16", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 17, + "type": "diskMemoryCheck", + "unit": "GB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "GB", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "persistent", + "isReadOnly": true, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "controller", + "initialValue": "None", + "isReadOnly": true, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": true, + "hideField": false, + "id": "dependent", + "initialValue": false, + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": false, + "isReadOnly": true, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ] + } + name="BasicInformation" + title="Resize Disk" + />, + , + ] + } + hideButtons={false} + schema={ + Object { + "fields": Array [ + Object { + "className": "disk_form", + "component": "sub-form", + "fields": Array [ + Array [ + Object { + "component": "text-field", + "hideField": false, + "id": "name", + "initialValue": "disk test 2", + "isReadOnly": true, + "label": "Name", + "name": "name", + }, + Object { + "autoFocus": true, + "component": "select", + "disabled": true, + "id": "type", + "includeEmpty": true, + "initialValue": "thin", + "isReadOnly": true, + "isRequired": true, + "label": "Type", + "name": "type", + "options": Array [ + Object { + "label": "thin", + "value": "thin", + }, + Object { + "label": "thick", + "value": "thick", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "16", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 17, + "type": "diskMemoryCheck", + "unit": "GB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "GB", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "persistent", + "isReadOnly": true, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "controller", + "initialValue": "None", + "isReadOnly": true, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": true, + "hideField": false, + "id": "dependent", + "initialValue": false, + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": false, + "isReadOnly": true, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ], + "name": "BasicInformation", + "title": "Resize Disk", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + > +
+ ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "16", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 17, + "type": "diskMemoryCheck", + "unit": "GB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "GB", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "persistent", + "isReadOnly": true, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "controller", + "initialValue": "None", + "isReadOnly": true, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": true, + "hideField": false, + "id": "dependent", + "initialValue": false, + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": false, + "isReadOnly": true, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ] + } + key="BasicInformation" + name="BasicInformation" + title="Resize Disk" + > + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "16", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 17, + "type": "diskMemoryCheck", + "unit": "GB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "GB", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "persistent", + "isReadOnly": true, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "controller", + "initialValue": "None", + "isReadOnly": true, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": true, + "hideField": false, + "id": "dependent", + "initialValue": false, + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": false, + "isReadOnly": true, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ], + "name": "BasicInformation", + "title": "Resize Disk", + } + } + > + + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + }, + Object { + "component": "text-field", + "id": "size", + "initialValue": "16", + "isRequired": true, + "label": "Size", + "name": "size", + "validate": Array [ + Object { + "size": 17, + "type": "diskMemoryCheck", + "unit": "GB", + }, + ], + }, + Object { + "component": "select", + "id": "unit", + "initialValue": "GB", + "label": "Unit", + "name": "unit", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "mode", + "includeEmpty": true, + "initialValue": "persistent", + "isReadOnly": true, + "isRequired": true, + "label": "Mode", + "name": "mode", + "options": Array [ + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "disabled": true, + "hideField": false, + "id": "controller", + "initialValue": "None", + "isReadOnly": true, + "label": "Controller", + "name": "controller", + "options": Array [ + Object { + "label": "VirtualController", + "value": "VirtualController", + }, + Object { + "label": "ParaVirtualController", + "value": "ParaVirtualController", + }, + Object { + "label": "VirtualBusController", + "value": "VirtualBusController", + }, + ], + }, + Object { + "component": "switch", + "disabled": true, + "hideField": false, + "id": "dependent", + "initialValue": false, + "label": "Dependent", + "name": "dependent", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "switch", + "hideField": false, + "initialValue": false, + "isReadOnly": true, + "label": "Bootable", + "name": "bootable", + "offText": "No", + "onText": "Yes", + }, + ], + ] + } + name="BasicInformation" + title="Resize Disk" + > +
+
+

+ Resize Disk +

+
+ + + + + +
+ +
+
+ + + + + + + + +
+
+
+
+
+
+
+
+ + ", + "validate": Array [ + Object { + "type": "required", + }, + ], + } + } + > + + + + Type + + } + loadOptionsChangeCounter={1} + loadingMessage="Loading..." + name="type" + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + options={ + Array [ + Object { + "label": "", + "value": undefined, + }, + Object { + "label": "thin", + "value": "thin", + }, + Object { + "label": "thick", + "value": "thick", + }, + ] + } + placeholder="" + pluckSingleValue={true} + readOnly={true} + simpleValue={false} + value="thin" + > + + Type + + } + name="type" + noOptionsMessage={[Function]} + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + onInputChange={[Function]} + options={ + Array [ + Object { + "label": "", + "value": undefined, + }, + Object { + "label": "thin", + "value": "thin", + }, + Object { + "label": "thick", + "value": "thick", + }, + ] + } + placeholder="" + readOnly={true} + value="thin" + > + + + + + + + + + + + + +
+ + + + + + + +
+
+
+ + + + + + Size + + } + name="size" + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + value="16" + warn={false} + warnText="" + > +
+ +
+
+ +
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + } + } + > + + + + Mode + + } + loadOptionsChangeCounter={1} + loadingMessage="Loading..." + name="mode" + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + options={ + Array [ + Object { + "label": "", + "value": undefined, + }, + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ] + } + placeholder="" + pluckSingleValue={true} + readOnly={true} + simpleValue={false} + value="persistent" + > + + Mode + + } + name="mode" + noOptionsMessage={[Function]} + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + onInputChange={[Function]} + options={ + Array [ + Object { + "label": "", + "value": undefined, + }, + Object { + "label": "persistent", + "value": "persistent", + }, + Object { + "label": "nonpersistent", + "value": "nonpersistent", + }, + ] + } + placeholder="" + readOnly={true} + value="persistent" + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+
+ +
+
+
+
+
+ + + + +
+ + +
+ + +
+
+
+ +
+
+
+
+
+ + + + + + + + + + + + + + +
+ + + +
+
+
+
+
+
+
+
+
+
+`; + +exports[`Reconfigure VM form component should render reconfigure form and show hidden fields 1`] = ` + + + + + + +
+

+ Form could not be rendered, because of invalid form schema. +

+

+ DefaultSchemaError + : +

+

+ Each fields item must have "component" property! +

+

+ If you don't know what this error means, please contact site administrator. +

+
+
+
+
+
+
+
+`; + +exports[`Reconfigure VM form component should render reconfigure form and show network add form 1`] = ` + + + ", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "hideField": true, + "id": "network", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "Network", + "name": "network", + "options": Array [], + "placeholder": "", + "validate": Array [ + Object { + "hideField": true, + "type": "customRequired", + }, + ], + }, + Object { + "component": "text-field", + "hideField": true, + "id": "mac", + "initialValue": "", + "isReadOnly": false, + "label": "MAC Address", + "name": "mac", + }, + ], + ], + "name": "BasicInformation", + "title": "Add Network Adapters", + }, + ], + } + } + validatorMapper={ + Object { + "cpuCheck": [Function], + "customRequired": [Function], + "diskMemoryCheck": [Function], + "memoryCheck": [Function], + } + } + > + ", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "hideField": true, + "id": "network", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "Network", + "name": "network", + "options": Array [], + "placeholder": "", + "validate": Array [ + Object { + "hideField": true, + "type": "customRequired", + }, + ], + }, + Object { + "component": "text-field", + "hideField": true, + "id": "mac", + "initialValue": "", + "isReadOnly": false, + "label": "MAC Address", + "name": "mac", + }, + ], + ], + "name": "BasicInformation", + "title": "Add Network Adapters", + }, + ], + } + } + showFormControls={true} + validatorMapper={ + Object { + "cpuCheck": [Function], + "customRequired": [Function], + "diskMemoryCheck": [Function], + "memoryCheck": [Function], + } + } + > + ", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "hideField": true, + "id": "network", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "Network", + "name": "network", + "options": Array [], + "placeholder": "", + "validate": Array [ + Object { + "hideField": true, + "type": "customRequired", + }, + ], + }, + Object { + "component": "text-field", + "hideField": true, + "id": "mac", + "initialValue": "", + "isReadOnly": false, + "label": "MAC Address", + "name": "mac", + }, + ], + ], + "name": "BasicInformation", + "title": "Add Network Adapters", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + validatorMapper={ + Object { + "cpuCheck": [Function], + "customRequired": [Function], + "diskMemoryCheck": [Function], + "memoryCheck": [Function], + } + } + > + + ", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "hideField": true, + "id": "network", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "Network", + "name": "network", + "options": Array [], + "placeholder": "", + "validate": Array [ + Object { + "hideField": true, + "type": "customRequired", + }, + ], + }, + Object { + "component": "text-field", + "hideField": true, + "id": "mac", + "initialValue": "", + "isReadOnly": false, + "label": "MAC Address", + "name": "mac", + }, + ], + ] + } + name="BasicInformation" + title="Add Network Adapters" + />, + , + ] + } + schema={ + Object { + "fields": Array [ + Object { + "className": "network_form", + "component": "sub-form", + "fields": Array [ + Array [ + Object { + "autoFocus": true, + "component": "text-field", + "hideField": true, + "id": "name", + "initialValue": "", + "isReadOnly": false, + "label": "Name", + "name": "name", + }, + Object { + "component": "select", + "hideField": false, + "id": "vlan", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "vLan", + "name": "vlan", + "options": Array [ + Object { + "label": "vlan test 0", + "value": "vlan test 0", + }, + Object { + "label": "vlan test 1", + "value": "vlan test 1", + }, + Object { + "label": "vlan test 3", + "value": "vlan test 3", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "hideField": true, + "id": "network", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "Network", + "name": "network", + "options": Array [], + "placeholder": "", + "validate": Array [ + Object { + "hideField": true, + "type": "customRequired", + }, + ], + }, + Object { + "component": "text-field", + "hideField": true, + "id": "mac", + "initialValue": "", + "isReadOnly": false, + "label": "MAC Address", + "name": "mac", + }, + ], + ], + "name": "BasicInformation", + "title": "Add Network Adapters", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + > + ", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "hideField": true, + "id": "network", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "Network", + "name": "network", + "options": Array [], + "placeholder": "", + "validate": Array [ + Object { + "hideField": true, + "type": "customRequired", + }, + ], + }, + Object { + "component": "text-field", + "hideField": true, + "id": "mac", + "initialValue": "", + "isReadOnly": false, + "label": "MAC Address", + "name": "mac", + }, + ], + ] + } + name="BasicInformation" + title="Add Network Adapters" + />, + , + ] + } + hideButtons={false} + schema={ + Object { + "fields": Array [ + Object { + "className": "network_form", + "component": "sub-form", + "fields": Array [ + Array [ + Object { + "autoFocus": true, + "component": "text-field", + "hideField": true, + "id": "name", + "initialValue": "", + "isReadOnly": false, + "label": "Name", + "name": "name", + }, + Object { + "component": "select", + "hideField": false, + "id": "vlan", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "vLan", + "name": "vlan", + "options": Array [ + Object { + "label": "vlan test 0", + "value": "vlan test 0", + }, + Object { + "label": "vlan test 1", + "value": "vlan test 1", + }, + Object { + "label": "vlan test 3", + "value": "vlan test 3", + }, + ], + "placeholder": "", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "hideField": true, + "id": "network", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "Network", + "name": "network", + "options": Array [], + "placeholder": "", + "validate": Array [ + Object { + "hideField": true, + "type": "customRequired", + }, + ], + }, + Object { + "component": "text-field", + "hideField": true, + "id": "mac", + "initialValue": "", + "isReadOnly": false, + "label": "MAC Address", + "name": "mac", + }, + ], + ], + "name": "BasicInformation", + "title": "Add Network Adapters", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + > +
+ ", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "hideField": true, + "id": "network", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "Network", + "name": "network", + "options": Array [], + "placeholder": "", + "validate": Array [ + Object { + "hideField": true, + "type": "customRequired", + }, + ], + }, + Object { + "component": "text-field", + "hideField": true, + "id": "mac", + "initialValue": "", + "isReadOnly": false, + "label": "MAC Address", + "name": "mac", + }, + ], + ] + } + key="BasicInformation" + name="BasicInformation" + title="Add Network Adapters" + > + ", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "hideField": true, + "id": "network", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "Network", + "name": "network", + "options": Array [], + "placeholder": "", + "validate": Array [ + Object { + "hideField": true, + "type": "customRequired", + }, + ], + }, + Object { + "component": "text-field", + "hideField": true, + "id": "mac", + "initialValue": "", + "isReadOnly": false, + "label": "MAC Address", + "name": "mac", + }, + ], + ], + "name": "BasicInformation", + "title": "Add Network Adapters", + } + } + > + + ", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + }, + Object { + "component": "select", + "hideField": true, + "id": "network", + "includeEmpty": true, + "initialValue": "", + "isRequired": true, + "label": "Network", + "name": "network", + "options": Array [], + "placeholder": "", + "validate": Array [ + Object { + "hideField": true, + "type": "customRequired", + }, + ], + }, + Object { + "component": "text-field", + "hideField": true, + "id": "mac", + "initialValue": "", + "isReadOnly": false, + "label": "MAC Address", + "name": "mac", + }, + ], + ] + } + name="BasicInformation" + title="Add Network Adapters" + > +
+
+

+ Add Network Adapters +

+
+ + + + + + + + + ", + "validate": Array [ + Object { + "hideField": false, + "type": "customRequired", + }, + ], + } + } + > + + + + vLan + + } + loadOptionsChangeCounter={1} + loadingMessage="Loading..." + name="vlan" + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + options={ + Array [ + Object { + "label": "", + "value": undefined, + }, + Object { + "label": "vlan test 0", + "value": "vlan test 0", + }, + Object { + "label": "vlan test 1", + "value": "vlan test 1", + }, + Object { + "label": "vlan test 3", + "value": "vlan test 3", + }, + ] + } + placeholder="" + pluckSingleValue={true} + simpleValue={false} + value="" + > + + vLan + + } + name="vlan" + noOptionsMessage={[Function]} + onBlur={[Function]} + onChange={[Function]} + onFocus={[Function]} + onInputChange={[Function]} + options={ + Array [ + Object { + "label": "", + "value": undefined, + }, + Object { + "label": "vlan test 0", + "value": "vlan test 0", + }, + Object { + "label": "vlan test 1", + "value": "vlan test 1", + }, + Object { + "label": "vlan test 3", + "value": "vlan test 3", + }, + ] + } + placeholder="" + value="" + > + + + + + + + + + + + + + +
+ + + + + + + +
+
+
+ + ", + "validate": Array [ + Object { + "hideField": true, + "type": "customRequired", + }, + ], + } + } + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+
+
+
+
+
+
+
+
+`; + +exports[`Reconfigure VM form component should render reconfigure form with datatables 1`] = ` + + + + + + + , + , + ] + } + schema={ + Object { + "fields": Array [ + Object { + "className": "reconfigure_form", + "component": "sub-form", + "fields": Array [ + Array [ + Object { + "component": "switch", + "isDisabled": false, + "label": "Memory", + "name": "cb_memory", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "text-field", + "condition": Object { + "is": true, + "when": "cb_memory", + }, + "initialValue": 16, + "isRequired": true, + "label": "Memory Size", + "name": "memory", + "validate": Array [ + Object { + "type": "memoryCheck", + }, + ], + }, + Object { + "component": "select", + "condition": Object { + "is": true, + "when": "cb_memory", + }, + "helperText": "Between 1024MB and 0.009765625GB", + "id": "memoryType", + "initialValue": "GB", + "label": "Memory Type", + "name": "mem_type", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "switch", + "isDisabled": false, + "label": "Processor", + "name": "processor", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "select", + "condition": Object { + "is": true, + "when": "processor", + }, + "hideField": false, + "id": "socket", + "label": "Sockets", + "name": "socket_count", + "onChange": [Function], + "options": Array [ + Object { + "label": "1", + "value": 1, + }, + Object { + "label": "2", + "value": 2, + }, + Object { + "label": "3", + "value": 3, + }, + Object { + "label": "4", + "value": 4, + }, + ], + "validate": Array [ + Object { + "field": "socket", + "type": "cpuCheck", + }, + ], + }, + Object { + "component": "select", + "condition": Object { + "is": true, + "when": "processor", + }, + "hideField": false, + "id": "cores", + "label": "Cores Per Socket", + "name": "cores_per_socket_count", + "onChange": [Function], + "options": Array [ + Object { + "label": "1", + "value": 1, + }, + Object { + "label": "2", + "value": 2, + }, + Object { + "label": "3", + "value": 3, + }, + Object { + "label": "4", + "value": 4, + }, + ], + "validate": Array [ + Object { + "field": "cores", + "type": "cpuCheck", + }, + ], + }, + Object { + "component": "text-field", + "condition": Object { + "is": true, + "when": "processor", + }, + "id": "total_cpus", + "initialValue": 4, + "isReadOnly": true, + "label": "Total Processors", + "name": "total_cpus", + "type": "number", + }, + Array [ + Object { + "addButtonLabel": "Add Disk", + "buttonClick": [Function], + "component": "reconfigure-table", + "formType": "disk", + "headers": Array [ + Object { + "header": "Name", + "key": "name", + }, + Object { + "header": "Type", + "key": "type", + }, + Object { + "header": "Size", + "key": "size", + }, + Object { + "header": "Unit", + "key": "unit", + }, + Object { + "header": "Mode", + "key": "mode", + }, + Object { + "header": "Controller Type", + "key": "controller", + }, + Object { + "header": "Dependent", + "key": "dependent", + }, + Object { + "header": "Delete Backing", + "key": "backing", + }, + Object { + "header": "Bootable", + "key": "bootable", + }, + Object { + "header": "Resize", + "key": "resize", + }, + Object { + "contentButton": true, + "header": "Action", + "key": "action", + }, + ], + "label": "Disks", + "name": "disk", + "onCellClick": [Function], + "rows": Array [ + Object { + "action": Object { + "alt": "Delete", + "callback": "deleteDisk", + "disabled": false, + "is_button": true, + "kind": "ghost", + "text": "Delete", + "title": "Delete", + }, + "backing": Object { + "disabled": false, + "is_toggle": true, + "labelA": "Yes", + "labelB": "No", + "labelText": "Delete Backing", + "ontoggle": [Function], + "toggled": false, + }, + "bootable": "Yes", + "controller": "None", + "dependent": "No", + "id": "disk0", + "mode": "persistent", + "name": "disk-test-file", + "resize": Object { + "alt": "Resize", + "callback": "resizeDisk", + "disabled": false, + "is_button": true, + "kind": "ghost", + "text": "Resize", + "title": "Resize", + }, + "size": "90", + "type": "thin", + "unit": "GB", + }, + ], + }, + Object { + "addButtonLabel": "Add Network", + "buttonClick": [Function], + "component": "reconfigure-table", + "formType": "network", + "headers": Array [ + Object { + "header": "Name", + "key": "name", + }, + Object { + "header": "MAC address", + "key": "mac", + }, + Object { + "header": "vLan", + "key": "vlan", + }, + Object { + "contentButton": true, + "header": "Edit", + "key": "edit", + }, + Object { + "contentButton": true, + "header": "Action", + "key": "action", + }, + ], + "label": "Network Adapters", + "name": "network", + "onCellClick": [Function], + "rows": Array [ + Object { + "action": Object { + "alt": "Delete", + "callback": "deleteNetwork", + "disabled": false, + "is_button": true, + "kind": "ghost", + "text": "Delete", + "title": "Delete", + }, + "edit": Object { + "alt": "Edit", + "callback": "editNetwork", + "disabled": false, + "is_button": true, + "kind": "ghost", + "text": "Edit", + "title": "Edit", + }, + "id": "network0", + "mac": "00:1a:4a:16:01:bc", + "name": "nic1", + "vlan": "vm_network2", + }, + ], + }, + Object { + "addButton": false, + "component": "reconfigure-table", + "formType": "drive", + "headers": Array [ + Object { + "header": "Name", + "key": "name", + }, + Object { + "header": "Host File", + "key": "hostFile", + }, + Object { + "header": "Disconnect", + "key": "disconnect", + }, + Object { + "header": "Actions", + "key": "action", + }, + ], + "hideField": true, + "label": "CD/DVD Drives", + "name": "drive", + "onCellClick": [Function], + "rows": Array [], + }, + ], + ], + ], + "name": "BasicInformation", + "title": "Options", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + > + , + , + ] + } + hideButtons={false} + schema={ + Object { + "fields": Array [ + Object { + "className": "reconfigure_form", + "component": "sub-form", + "fields": Array [ + Array [ + Object { + "component": "switch", + "isDisabled": false, + "label": "Memory", + "name": "cb_memory", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "text-field", + "condition": Object { + "is": true, + "when": "cb_memory", + }, + "initialValue": 16, + "isRequired": true, + "label": "Memory Size", + "name": "memory", + "validate": Array [ + Object { + "type": "memoryCheck", + }, + ], + }, + Object { + "component": "select", + "condition": Object { + "is": true, + "when": "cb_memory", + }, + "helperText": "Between 1024MB and 0.009765625GB", + "id": "memoryType", + "initialValue": "GB", + "label": "Memory Type", + "name": "mem_type", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "switch", + "isDisabled": false, + "label": "Processor", + "name": "processor", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "select", + "condition": Object { + "is": true, + "when": "processor", + }, + "hideField": false, + "id": "socket", + "label": "Sockets", + "name": "socket_count", + "onChange": [Function], + "options": Array [ + Object { + "label": "1", + "value": 1, + }, + Object { + "label": "2", + "value": 2, + }, + Object { + "label": "3", + "value": 3, + }, + Object { + "label": "4", + "value": 4, + }, + ], + "validate": Array [ + Object { + "field": "socket", + "type": "cpuCheck", + }, + ], + }, + Object { + "component": "select", + "condition": Object { + "is": true, + "when": "processor", + }, + "hideField": false, + "id": "cores", + "label": "Cores Per Socket", + "name": "cores_per_socket_count", + "onChange": [Function], + "options": Array [ + Object { + "label": "1", + "value": 1, + }, + Object { + "label": "2", + "value": 2, + }, + Object { + "label": "3", + "value": 3, + }, + Object { + "label": "4", + "value": 4, + }, + ], + "validate": Array [ + Object { + "field": "cores", + "type": "cpuCheck", + }, + ], + }, + Object { + "component": "text-field", + "condition": Object { + "is": true, + "when": "processor", + }, + "id": "total_cpus", + "initialValue": 4, + "isReadOnly": true, + "label": "Total Processors", + "name": "total_cpus", + "type": "number", + }, + Array [ + Object { + "addButtonLabel": "Add Disk", + "buttonClick": [Function], + "component": "reconfigure-table", + "formType": "disk", + "headers": Array [ + Object { + "header": "Name", + "key": "name", + }, + Object { + "header": "Type", + "key": "type", + }, + Object { + "header": "Size", + "key": "size", + }, + Object { + "header": "Unit", + "key": "unit", + }, + Object { + "header": "Mode", + "key": "mode", + }, + Object { + "header": "Controller Type", + "key": "controller", + }, + Object { + "header": "Dependent", + "key": "dependent", + }, + Object { + "header": "Delete Backing", + "key": "backing", + }, + Object { + "header": "Bootable", + "key": "bootable", + }, + Object { + "header": "Resize", + "key": "resize", + }, + Object { + "contentButton": true, + "header": "Action", + "key": "action", + }, + ], + "label": "Disks", + "name": "disk", + "onCellClick": [Function], + "rows": Array [ + Object { + "action": Object { + "alt": "Delete", + "callback": "deleteDisk", + "disabled": false, + "is_button": true, + "kind": "ghost", + "text": "Delete", + "title": "Delete", + }, + "backing": Object { + "disabled": false, + "is_toggle": true, + "labelA": "Yes", + "labelB": "No", + "labelText": "Delete Backing", + "ontoggle": [Function], + "toggled": false, + }, + "bootable": "Yes", + "controller": "None", + "dependent": "No", + "id": "disk0", + "mode": "persistent", + "name": "disk-test-file", + "resize": Object { + "alt": "Resize", + "callback": "resizeDisk", + "disabled": false, + "is_button": true, + "kind": "ghost", + "text": "Resize", + "title": "Resize", + }, + "size": "90", + "type": "thin", + "unit": "GB", + }, + ], + }, + Object { + "addButtonLabel": "Add Network", + "buttonClick": [Function], + "component": "reconfigure-table", + "formType": "network", + "headers": Array [ + Object { + "header": "Name", + "key": "name", + }, + Object { + "header": "MAC address", + "key": "mac", + }, + Object { + "header": "vLan", + "key": "vlan", + }, + Object { + "contentButton": true, + "header": "Edit", + "key": "edit", + }, + Object { + "contentButton": true, + "header": "Action", + "key": "action", + }, + ], + "label": "Network Adapters", + "name": "network", + "onCellClick": [Function], + "rows": Array [ + Object { + "action": Object { + "alt": "Delete", + "callback": "deleteNetwork", + "disabled": false, + "is_button": true, + "kind": "ghost", + "text": "Delete", + "title": "Delete", + }, + "edit": Object { + "alt": "Edit", + "callback": "editNetwork", + "disabled": false, + "is_button": true, + "kind": "ghost", + "text": "Edit", + "title": "Edit", + }, + "id": "network0", + "mac": "00:1a:4a:16:01:bc", + "name": "nic1", + "vlan": "vm_network2", + }, + ], + }, + Object { + "addButton": false, + "component": "reconfigure-table", + "formType": "drive", + "headers": Array [ + Object { + "header": "Name", + "key": "name", + }, + Object { + "header": "Host File", + "key": "hostFile", + }, + Object { + "header": "Disconnect", + "key": "disconnect", + }, + Object { + "header": "Actions", + "key": "action", + }, + ], + "hideField": true, + "label": "CD/DVD Drives", + "name": "drive", + "onCellClick": [Function], + "rows": Array [], + }, + ], + ], + ], + "name": "BasicInformation", + "title": "Options", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + > +
+ + + + +
+
+

+ Options +

+
+ + + + +
+ + +
+ + +
+
+
+ +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+
+ +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

+ Disks +

+ + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Name +
+
+
+ Type +
+
+
+ Size +
+
+
+ Unit +
+
+
+ Mode +
+
+
+ Controller Type +
+
+
+ Dependent +
+
+
+ Delete Backing +
+
+
+ Bootable +
+
+
+ Resize +
+
+
+ Action +
+
+
+ + disk-test-file + +
+
+
+ + thin + +
+
+
+ + 90 + +
+
+
+ + GB + +
+
+
+ + persistent + +
+
+
+ + None + +
+
+
+ + No + +
+
+
+ + + + } + onToggle={[Function]} + tabIndex={0} + toggled={false} + > + + + + } + onToggle={[Function]} + tabIndex={0} + toggled={false} + > +
+ + +
+
+
+
+
+
+ + Yes + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+ +
+ +
+
+
+ + + + +
+
+

+ Network Adapters +

+ + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Name +
+
+
+ MAC address +
+
+
+ vLan +
+
+
+ Edit +
+
+
+ Action +
+
+
+ + nic1 + +
+
+
+ + 00:1a:4a:16:01:bc + +
+
+
+ + vm_network2 + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+ + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+
+
+
+
+
+
+
+
+`; + +exports[`Reconfigure VM form component should render reconfigure form without datatables 1`] = ` + + + + + + +
+

+ Form could not be rendered, because of invalid form schema. +

+

+ DefaultSchemaError + : +

+

+ Each fields item must have "component" property! +

+

+ If you don't know what this error means, please contact site administrator. +

+
+
+
+
+
+
+
+`; + +exports[`Reconfigure VM form component should render reconfigure sub form and click delete button 1`] = ` + + + + + + + , + , + ] + } + schema={ + Object { + "fields": Array [ + Object { + "className": "reconfigure_form", + "component": "sub-form", + "fields": Array [ + Array [ + Object { + "component": "switch", + "isDisabled": false, + "label": "Memory", + "name": "cb_memory", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "text-field", + "condition": Object { + "is": true, + "when": "cb_memory", + }, + "initialValue": 16, + "isRequired": true, + "label": "Memory Size", + "name": "memory", + "validate": Array [ + Object { + "type": "memoryCheck", + }, + ], + }, + Object { + "component": "select", + "condition": Object { + "is": true, + "when": "cb_memory", + }, + "helperText": "Between 1024MB and 0.009765625GB", + "id": "memoryType", + "initialValue": "GB", + "label": "Memory Type", + "name": "mem_type", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "switch", + "isDisabled": false, + "label": "Processor", + "name": "processor", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "select", + "condition": Object { + "is": true, + "when": "processor", + }, + "hideField": false, + "id": "socket", + "label": "Sockets", + "name": "socket_count", + "onChange": [Function], + "options": Array [ + Object { + "label": "1", + "value": 1, + }, + Object { + "label": "2", + "value": 2, + }, + Object { + "label": "3", + "value": 3, + }, + Object { + "label": "4", + "value": 4, + }, + ], + "validate": Array [ + Object { + "field": "socket", + "type": "cpuCheck", + }, + ], + }, + Object { + "component": "select", + "condition": Object { + "is": true, + "when": "processor", + }, + "hideField": false, + "id": "cores", + "label": "Cores Per Socket", + "name": "cores_per_socket_count", + "onChange": [Function], + "options": Array [ + Object { + "label": "1", + "value": 1, + }, + Object { + "label": "2", + "value": 2, + }, + Object { + "label": "3", + "value": 3, + }, + Object { + "label": "4", + "value": 4, + }, + ], + "validate": Array [ + Object { + "field": "cores", + "type": "cpuCheck", + }, + ], + }, + Object { + "component": "text-field", + "condition": Object { + "is": true, + "when": "processor", + }, + "id": "total_cpus", + "initialValue": 2, + "isReadOnly": true, + "label": "Total Processors", + "name": "total_cpus", + "type": "number", + }, + Array [ + Object { + "addButtonLabel": "Add Disk", + "buttonClick": [Function], + "component": "reconfigure-table", + "formType": "disk", + "headers": Array [ + Object { + "header": "Name", + "key": "name", + }, + Object { + "header": "Type", + "key": "type", + }, + Object { + "header": "Size", + "key": "size", + }, + Object { + "header": "Unit", + "key": "unit", + }, + Object { + "header": "Mode", + "key": "mode", + }, + Object { + "header": "Controller Type", + "key": "controller", + }, + Object { + "header": "Dependent", + "key": "dependent", + }, + Object { + "header": "Delete Backing", + "key": "backing", + }, + Object { + "header": "Bootable", + "key": "bootable", + }, + Object { + "header": "Resize", + "key": "resize", + }, + Object { + "contentButton": true, + "header": "Action", + "key": "action", + }, + ], + "label": "Disks", + "name": "disk", + "onCellClick": [Function], + "rows": Array [ + Object { + "action": Object { + "alt": "Cancel Delete", + "callback": "cancelDeleteDisk", + "is_button": true, + "kind": "ghost", + "text": "Cancel Delete", + "title": "Cancel Delete", + }, + "backing": Object { + "disabled": true, + "is_toggle": true, + "labelA": "Yes", + "labelB": "No", + "labelText": "Delete Backing", + "ontoggle": [Function], + "toggled": false, + }, + "bootable": "No", + "controller": "None", + "dependent": "No", + "id": "disk0", + "mode": "persistent", + "name": "disk test 2", + "resize": Object { + "alt": "Resize", + "callback": "resizeDisk", + "disabled": true, + "is_button": true, + "kind": "ghost", + "text": "Resize", + "title": "Resize", + }, + "size": "16", + "type": "thin", + "unit": "GB", + }, + ], + }, + Object { + "addButtonLabel": "Add Network", + "buttonClick": [Function], + "component": "reconfigure-table", + "formType": "network", + "headers": Array [ + Object { + "header": "Name", + "key": "name", + }, + Object { + "header": "MAC address", + "key": "mac", + }, + Object { + "header": "vLan", + "key": "vlan", + }, + Object { + "contentButton": true, + "header": "Edit", + "key": "edit", + }, + Object { + "contentButton": true, + "header": "Action", + "key": "action", + }, + ], + "label": "Network Adapters", + "name": "network", + "onCellClick": [Function], + "rows": Array [], + }, + Object { + "addButton": false, + "component": "reconfigure-table", + "formType": "drive", + "headers": Array [ + Object { + "header": "Name", + "key": "name", + }, + Object { + "header": "Host File", + "key": "hostFile", + }, + Object { + "header": "Disconnect", + "key": "disconnect", + }, + Object { + "header": "Actions", + "key": "action", + }, + ], + "hideField": false, + "label": "CD/DVD Drives", + "name": "drive", + "onCellClick": [Function], + "rows": Array [ + Object { + "action": Object { + "alt": "Connect", + "callback": "connectDrives", + "disabled": true, + "is_button": true, + "kind": "ghost", + "text": "Connect", + "title": "Connect", + }, + "disconnect": Object { + "alt": "Disconnect", + "callback": "disconnectDrives", + "disabled": false, + "is_button": true, + "kind": "ghost", + "text": "Disconnect", + "title": "Disconnect", + }, + "hostFile": "teset", + "id": "drive0", + "name": "CD/DVD drive 1", + }, + ], + }, + ], + ], + ], + "name": "BasicInformation", + "title": "Options", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + > + , + , + ] + } + hideButtons={false} + schema={ + Object { + "fields": Array [ + Object { + "className": "reconfigure_form", + "component": "sub-form", + "fields": Array [ + Array [ + Object { + "component": "switch", + "isDisabled": false, + "label": "Memory", + "name": "cb_memory", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "text-field", + "condition": Object { + "is": true, + "when": "cb_memory", + }, + "initialValue": 16, + "isRequired": true, + "label": "Memory Size", + "name": "memory", + "validate": Array [ + Object { + "type": "memoryCheck", + }, + ], + }, + Object { + "component": "select", + "condition": Object { + "is": true, + "when": "cb_memory", + }, + "helperText": "Between 1024MB and 0.009765625GB", + "id": "memoryType", + "initialValue": "GB", + "label": "Memory Type", + "name": "mem_type", + "options": Array [ + Object { + "label": "GB", + "value": "GB", + }, + Object { + "label": "MB", + "value": "MB", + }, + ], + }, + Object { + "component": "switch", + "isDisabled": false, + "label": "Processor", + "name": "processor", + "offText": "No", + "onText": "Yes", + }, + Object { + "component": "select", + "condition": Object { + "is": true, + "when": "processor", + }, + "hideField": false, + "id": "socket", + "label": "Sockets", + "name": "socket_count", + "onChange": [Function], + "options": Array [ + Object { + "label": "1", + "value": 1, + }, + Object { + "label": "2", + "value": 2, + }, + Object { + "label": "3", + "value": 3, + }, + Object { + "label": "4", + "value": 4, + }, + ], + "validate": Array [ + Object { + "field": "socket", + "type": "cpuCheck", + }, + ], + }, + Object { + "component": "select", + "condition": Object { + "is": true, + "when": "processor", + }, + "hideField": false, + "id": "cores", + "label": "Cores Per Socket", + "name": "cores_per_socket_count", + "onChange": [Function], + "options": Array [ + Object { + "label": "1", + "value": 1, + }, + Object { + "label": "2", + "value": 2, + }, + Object { + "label": "3", + "value": 3, + }, + Object { + "label": "4", + "value": 4, + }, + ], + "validate": Array [ + Object { + "field": "cores", + "type": "cpuCheck", + }, + ], + }, + Object { + "component": "text-field", + "condition": Object { + "is": true, + "when": "processor", + }, + "id": "total_cpus", + "initialValue": 2, + "isReadOnly": true, + "label": "Total Processors", + "name": "total_cpus", + "type": "number", + }, + Array [ + Object { + "addButtonLabel": "Add Disk", + "buttonClick": [Function], + "component": "reconfigure-table", + "formType": "disk", + "headers": Array [ + Object { + "header": "Name", + "key": "name", + }, + Object { + "header": "Type", + "key": "type", + }, + Object { + "header": "Size", + "key": "size", + }, + Object { + "header": "Unit", + "key": "unit", + }, + Object { + "header": "Mode", + "key": "mode", + }, + Object { + "header": "Controller Type", + "key": "controller", + }, + Object { + "header": "Dependent", + "key": "dependent", + }, + Object { + "header": "Delete Backing", + "key": "backing", + }, + Object { + "header": "Bootable", + "key": "bootable", + }, + Object { + "header": "Resize", + "key": "resize", + }, + Object { + "contentButton": true, + "header": "Action", + "key": "action", + }, + ], + "label": "Disks", + "name": "disk", + "onCellClick": [Function], + "rows": Array [ + Object { + "action": Object { + "alt": "Cancel Delete", + "callback": "cancelDeleteDisk", + "is_button": true, + "kind": "ghost", + "text": "Cancel Delete", + "title": "Cancel Delete", + }, + "backing": Object { + "disabled": true, + "is_toggle": true, + "labelA": "Yes", + "labelB": "No", + "labelText": "Delete Backing", + "ontoggle": [Function], + "toggled": false, + }, + "bootable": "No", + "controller": "None", + "dependent": "No", + "id": "disk0", + "mode": "persistent", + "name": "disk test 2", + "resize": Object { + "alt": "Resize", + "callback": "resizeDisk", + "disabled": true, + "is_button": true, + "kind": "ghost", + "text": "Resize", + "title": "Resize", + }, + "size": "16", + "type": "thin", + "unit": "GB", + }, + ], + }, + Object { + "addButtonLabel": "Add Network", + "buttonClick": [Function], + "component": "reconfigure-table", + "formType": "network", + "headers": Array [ + Object { + "header": "Name", + "key": "name", + }, + Object { + "header": "MAC address", + "key": "mac", + }, + Object { + "header": "vLan", + "key": "vlan", + }, + Object { + "contentButton": true, + "header": "Edit", + "key": "edit", + }, + Object { + "contentButton": true, + "header": "Action", + "key": "action", + }, + ], + "label": "Network Adapters", + "name": "network", + "onCellClick": [Function], + "rows": Array [], + }, + Object { + "addButton": false, + "component": "reconfigure-table", + "formType": "drive", + "headers": Array [ + Object { + "header": "Name", + "key": "name", + }, + Object { + "header": "Host File", + "key": "hostFile", + }, + Object { + "header": "Disconnect", + "key": "disconnect", + }, + Object { + "header": "Actions", + "key": "action", + }, + ], + "hideField": false, + "label": "CD/DVD Drives", + "name": "drive", + "onCellClick": [Function], + "rows": Array [ + Object { + "action": Object { + "alt": "Connect", + "callback": "connectDrives", + "disabled": true, + "is_button": true, + "kind": "ghost", + "text": "Connect", + "title": "Connect", + }, + "disconnect": Object { + "alt": "Disconnect", + "callback": "disconnectDrives", + "disabled": false, + "is_button": true, + "kind": "ghost", + "text": "Disconnect", + "title": "Disconnect", + }, + "hostFile": "teset", + "id": "drive0", + "name": "CD/DVD drive 1", + }, + ], + }, + ], + ], + ], + "name": "BasicInformation", + "title": "Options", + }, + Object { + "component": "spy-field", + "initialize": undefined, + "name": "spy-field", + }, + ], + } + } + > +
+ + + + +
+
+

+ Options +

+
+ + + + +
+ + +
+ + +
+
+
+ +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+
+ +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

+ Disks +

+ + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Name +
+
+
+ Type +
+
+
+ Size +
+
+
+ Unit +
+
+
+ Mode +
+
+
+ Controller Type +
+
+
+ Dependent +
+
+
+ Delete Backing +
+
+
+ Bootable +
+
+
+ Resize +
+
+
+ Action +
+
+
+ + disk test 2 + +
+
+
+ + thin + +
+
+
+ + 16 + +
+
+
+ + GB + +
+
+
+ + persistent + +
+
+
+ + None + +
+
+
+ + No + +
+
+
+ + + + } + onToggle={[Function]} + tabIndex={0} + toggled={false} + > + + + + } + onToggle={[Function]} + tabIndex={0} + toggled={false} + > +
+ + +
+
+
+
+
+
+ + No + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+ +
+ +
+
+
+ + + + +
+
+

+ Network Adapters +

+ + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Name +
+
+
+ MAC address +
+
+
+ vLan +
+
+
+ Edit +
+
+
+ Action +
+
+
+ + +
+ + +
+
+
+
+ + + + +
+
+

+ CD/DVD Drives +

+ +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Name +
+
+
+ Host File +
+
+
+ Disconnect +
+
+
+ Actions +
+
+
+ + CD/DVD drive 1 + +
+
+
+ + teset + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+ + +
+
+
+
+ + + + + + + + + + + + + + +
+ + + +
+
+
+
+
+
+
+
+
+
+`; diff --git a/app/javascript/spec/reconfigure-vm-form/data.js b/app/javascript/spec/reconfigure-vm-form/data.js new file mode 100644 index 00000000000..a91f105049d --- /dev/null +++ b/app/javascript/spec/reconfigure-vm-form/data.js @@ -0,0 +1,159 @@ +export const valueFromHelpers = { + recordId: [12], + requestId: 'new', + roles: { + allowMemoryChange: true, + allowCpuChange: true, + allowDiskChange: true, + allowDiskSizeChange: true, + allowNetworkChange: true, + allowCdromsChange: true, + isVmwareInfra: true, + isVmwareCloud: false, + isRedhat: true, + }, + memory: { + min: 1024, + max: 10, + }, + options: { + controller_types: [ + 'VirtualController', + 'ParaVirtualController', + 'VirtualBusController', + ], + vlan_options: [ + 'vlan test 0', + 'vlan test 1', + 'vlan test 3', + ], + avail_adapter_names: [], + host_file_options: [ + [ + 'host file test 1.iso', + 'host file test 1.iso,18', + ], + [ + 'host file test 2.iso', + 'host file test 2.iso,18', + ], + [ + 'host file test 3.iso', + 'host file test 3.iso,18', + ], + ], + socket_options: [1, 2, 3, 4], + cores_options: [1, 2, 3, 4], + }, +}; + +export const valueFromHelpersTwo = { + recordId: [12, 13], + requestId: 'new', + roles: { + allowMemoryChange: true, + allowCpuChange: true, + allowDiskChange: true, + allowDiskSizeChange: true, + allowNetworkChange: true, + allowCdromsChange: true, + isVmwareInfra: true, + isVmwareCloud: false, + isRedhat: true, + }, + memory: { + min: 1024, + max: 10, + }, + options: { + controller_types: [], + vlan_options: [], + avail_adapter_names: [], + host_file_options: [], + socket_options: [1, 2, 3, 4], + cores_options: [1, 2, 3, 4], + }, +}; +export const responseDataOne = { + objectIds: [ + 12, + ], + memory: '16', + memory_type: 'GB', + socket_count: '4', + cores_per_socket_count: '1', + disks: [ + { + hdFilename: 'disk-test-file', + hdType: 'thin', + hdMode: 'persistent', + hdSize: '90', + hdUnit: 'GB', + cb_bootable: true, + orgHdSize: '90', + orgHdUnit: 'GB', + }, + ], + network_adapters: [ + { + name: 'nic1', + vlan: 'vm_network2', + mac: '00:1a:4a:16:01:bc', + }, + ], + cdroms: [], + orchestration_stack_id: null, + cb_memory: false, + cb_cpu: false, +}; + +export const responseDataTwo = { + objectIds: [ + '13', + ], + memory: '2', + memory_type: 'GB', + socket_count: '2', + cores_per_socket_count: '1', + disks: [ + { + hdFilename: 'disk test 2', + hdType: 'thin', + hdMode: 'persistent', + hdSize: '16', + hdUnit: 'GB', + cb_bootable: null, + orgHdSize: '16', + orgHdUnit: 'GB', + }, + ], + network_adapters: [], + cdroms: [ + { + id: 39202, + device_name: 'CD/DVD drive 1', + filename: 'teset', + type: 'cdrom-raw', + storage_id: '', + }, + ], + orchestration_stack_id: null, + cb_memory: false, + cb_cpu: false, +}; + +export const responseDataThree = { + objectIds: [ + '12', '13', + ], + memory: '4', + memory_type: 'GB', + socket_count: '3', + cores_per_socket_count: '1', + disks: [], + network_adapters: [], + cdroms: [], + orchestration_stack_id: null, + cb_memory: true, + cb_cpu: true, +}; diff --git a/app/javascript/spec/reconfigure-vm-form/datatable-data.js b/app/javascript/spec/reconfigure-vm-form/datatable-data.js new file mode 100644 index 00000000000..05b1d77f8c2 --- /dev/null +++ b/app/javascript/spec/reconfigure-vm-form/datatable-data.js @@ -0,0 +1,116 @@ +export const driveHeaders = [ + { key: 'name', header: __('Name') }, + { key: 'hostFile', header: __('Host File') }, + { key: 'disconnect', header: __('Disconnect') }, + { key: 'action', header: __('Actions') }, +]; +export const driveRows = [ + { + id: 'drive0', + name: 'test drive', + hostFile: 'teset', + action: { + is_button: true, + title: 'Connect', + text: 'Connect', + alt: 'Connect', + disabled: true, + callback: 'connectDrives', + }, + disconnect: { + is_button: true, + title: 'Disconnect', + text: 'Disconnect', + alt: 'Disconnect', + disabled: false, + callback: 'disconnectDrives', + }, + }, +]; + +export const networkHeaders = [ + { key: 'name', header: 'Name' }, + { key: 'mac', header: 'MAC address' }, + { key: 'vlan', header: 'vLan' }, + { key: 'edit', header: 'Edit' }, + { key: 'action', header: 'Action' }, +]; + +export const networkRows = [ + { + id: 'network0', + name: 'nic1', + mac: 'test', + action: { + is_button: true, + title: 'Delete', + text: 'Delete', + alt: 'Delete', + kind: 'danger', + callback: 'deleteNetwork', + disabled: false, + }, + edit: { + is_button: true, + title: 'Edit', + text: 'Edit', + alt: 'Edit', + kind: 'secondary', + disabled: false, + callback: 'editNetwork', + }, + vlan: 'vm_network2', + }, +]; + +export const diskHeaders = [ + { key: 'name', header: 'Name' }, + { key: 'type', header: 'Type' }, + { key: 'size', header: 'Size' }, + { key: 'unit', header: 'Unit' }, + { key: 'mode', header: 'Mode' }, + { key: 'controller', header: 'Controller Type' }, + { key: 'dependent', header: 'Dependent' }, + { key: 'backing', header: 'Delete Backing' }, + { key: 'resize', header: 'Resize' }, + { key: 'action', header: 'Action' }, +]; + +export const diskRows = [ + { + id: 'disk0', + name: 'test.vmdk', + type: 'thin', + size: '16', + unit: 'GB', + action: { + is_button: true, + title: 'Delete', + text: 'Delete', + alt: 'Delete', + kind: 'danger', + disabled: false, + callback: 'deleteDisk', + }, + dependent: 'No', + mode: 'persistent', + controller: 'None', + backing: { + is_toggle: true, + labelText: 'Delete Backing', + labelA: 'Yes', + labelB: 'No', + toggled: true, + disabled: false, + }, + resize: { + is_button: true, + title: 'Resize', + text: 'Resize', + alt: 'Resize', + kind: 'secondary', + callback: 'resizeDisk', + disabled: false, + }, + }, +]; diff --git a/app/javascript/spec/reconfigure-vm-form/reconfigure-table/reconfigure-table.spec.js b/app/javascript/spec/reconfigure-vm-form/reconfigure-table/reconfigure-table.spec.js new file mode 100644 index 00000000000..f2a16300b78 --- /dev/null +++ b/app/javascript/spec/reconfigure-vm-form/reconfigure-table/reconfigure-table.spec.js @@ -0,0 +1,36 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import ReconfigureTable from '../../../components/reconfigure-vm-form/reconfigure-table'; +import { + diskHeaders, diskRows, networkHeaders, networkRows, driveHeaders, driveRows, +} from '../datatable-data'; + +describe('ReconfigureTable', () => { + it('should render disk table with headers and rows', () => { + const wrapper = shallow(); + expect(wrapper.find('MiqDataTable')).toHaveLength(1); + expect(wrapper.find('MiqDataTable').prop('headers')).toEqual(diskHeaders); + expect(wrapper.find('MiqDataTable').prop('rows')).toEqual(diskRows); + }); + + it('should render network table with headers and rows', () => { + const wrapper = shallow(); + expect(wrapper.find('MiqDataTable')).toHaveLength(1); + expect(wrapper.find('MiqDataTable').prop('headers')).toEqual(networkHeaders); + expect(wrapper.find('MiqDataTable').prop('rows')).toEqual(networkRows); + }); + + it('should render drive table with headers and rows', () => { + const wrapper = shallow(); + expect(wrapper.find('MiqDataTable')).toHaveLength(1); + expect(wrapper.find('MiqDataTable').prop('headers')).toEqual(driveHeaders); + expect(wrapper.find('MiqDataTable').prop('rows')).toEqual(driveRows); + }); + + it('should call onCellClick when a cell is clicked', () => { + const onCellClick = jest.fn(); + const wrapper = shallow(); + wrapper.find('MiqDataTable').prop('onCellClick')(diskRows[0], 'name'); + expect(onCellClick).toHaveBeenCalledWith(diskRows[0], 'name'); + }); +}); diff --git a/app/javascript/spec/reconfigure-vm-form/reconfigure-vm-form.spec.js b/app/javascript/spec/reconfigure-vm-form/reconfigure-vm-form.spec.js new file mode 100644 index 00000000000..44223d6051c --- /dev/null +++ b/app/javascript/spec/reconfigure-vm-form/reconfigure-vm-form.spec.js @@ -0,0 +1,173 @@ +import React from 'react'; +import toJson from 'enzyme-to-json'; +import fetchMock from 'fetch-mock'; +import { act } from 'react-dom/test-utils'; +import ReconfigureVmForm from '../../components/reconfigure-vm-form/index'; +import { + valueFromHelpers, valueFromHelpersTwo, responseDataOne, responseDataThree, responseDataTwo, +} from './data'; +import { mount } from '../helpers/mountForm'; + +require('../helpers/miqSparkle.js'); + +jest.mock('../../helpers/miq-redirect-back', () => jest.fn()); + +describe('Reconfigure VM form component', () => { + afterEach(() => { + fetchMock.reset(); + fetchMock.restore(); + }); + + it('should render reconfigure form with datatables', async(done) => { + fetchMock.get('/vm_infra/reconfigure_form_fields/new,12', responseDataOne); + let wrapper; + await act(async() => { + wrapper = mount(); + }); + wrapper.update(); + expect(fetchMock.calls()).toHaveLength(1); + expect(wrapper.find('div.disk-table-list')).toHaveLength(1); + expect(wrapper.find('div.network-table-list')).toHaveLength(1); + expect(toJson(wrapper)).toMatchSnapshot(); + done(); + }); + + it('should render reconfigure form without datatables', async(done) => { + fetchMock.get('vm_infra/reconfigure_form_fields/new,12,13', responseDataThree); + let wrapper; + await act(async() => { + wrapper = mount(); + }); + wrapper.update(); + expect(fetchMock.calls()).toHaveLength(1); + expect(wrapper.find('div.disk-table-list')).toHaveLength(0); + expect(wrapper.find('div.network-table-list')).toHaveLength(0); + expect(toJson(wrapper)).toMatchSnapshot(); + done(); + }); + + it('should render reconfigure form and show hidden fields', async(done) => { + fetchMock.get('vm_infra/reconfigure_form_fields/new,12,13', responseDataThree); + let wrapper; + await act(async() => { + wrapper = mount(); + }); + wrapper.update(); + expect(fetchMock.calls()).toHaveLength(1); + expect(wrapper.find('memory')).toBeDefined(); + expect(wrapper.find('mem_type')).toBeDefined(); + expect(wrapper.find('socket_count')).toBeDefined(); + expect(wrapper.find('cores_per_socket_count')).toBeDefined(); + expect(toJson(wrapper)).toMatchSnapshot(); + done(); + }); + + it('should render reconfigure form and show disk add form', async(done) => { + fetchMock.get('vm_infra/reconfigure_form_fields/new,12', responseDataOne); + let wrapper; + await act(async() => { + wrapper = mount(); + }); + wrapper.update(); + await act(async() => { + wrapper.find('button.disk-add').simulate('click'); + }); + wrapper.update(); + expect(fetchMock.calls()).toHaveLength(1); + expect(wrapper.find('type')).toBeDefined(); + expect(wrapper.find('size')).toBeDefined(); + expect(wrapper.find('unit')).toBeDefined(); + expect(toJson(wrapper)).toMatchSnapshot(); + done(); + }); + + it('should render reconfigure form and show network add form', async(done) => { + fetchMock.get('vm_infra/reconfigure_form_fields/new,12', responseDataOne); + let wrapper; + await act(async() => { + wrapper = mount(); + }); + wrapper.update(); + await act(async() => { + wrapper.find('button.network-add').simulate('click'); + }); + wrapper.update(); + expect(fetchMock.calls()).toHaveLength(1); + expect(wrapper.find('vlan')).toBeDefined(); + expect(toJson(wrapper)).toMatchSnapshot(); + done(); + }); + + it('should render reconfigure form and show cd rom connect form', async(done) => { + fetchMock.get('vm_infra/reconfigure_form_fields/new,12', responseDataTwo); + let wrapper; + await act(async() => { + wrapper = mount(); + }); + wrapper.update(); + await act(async() => { + wrapper.find('button[title="Disconnect"]').simulate('click'); + }); + wrapper.update(); + await act(async() => { + wrapper.find('button[title="Connect"]').simulate('click'); + }); + wrapper.update(); + expect(fetchMock.calls()).toHaveLength(1); + expect(wrapper.find('host_file')).toBeDefined(); + expect(toJson(wrapper)).toMatchSnapshot(); + done(); + }); + + it('should render reconfigure form and show disk resize form', async(done) => { + fetchMock.get('vm_infra/reconfigure_form_fields/new,12', responseDataTwo); + let wrapper; + await act(async() => { + wrapper = mount(); + }); + wrapper.update(); + await act(async() => { + wrapper.find('button[title="Resize"]').simulate('click'); + }); + wrapper.update(); + expect(fetchMock.calls()).toHaveLength(1); + expect(wrapper.find('size')).toBeDefined(); + expect(wrapper.find('unit')).toBeDefined(); + expect(toJson(wrapper)).toMatchSnapshot(); + done(); + }); + + it('should render reconfigure sub form and click delete button', async(done) => { + fetchMock.get('vm_infra/reconfigure_form_fields/new,12', responseDataTwo); + let wrapper; + await act(async() => { + wrapper = mount(); + }); + wrapper.update(); + await act(async() => { + wrapper.find('button[title="Delete"]').simulate('click'); + }); + wrapper.update(); + expect(fetchMock.calls()).toHaveLength(1); + expect(wrapper.find('button[title="Cancel Delete"]')).toBeDefined(); + expect(toJson(wrapper)).toMatchSnapshot(); + done(); + }); + + it('should render reconfigure form and click cd-rom disconnect button', async(done) => { + fetchMock.get('vm_infra/reconfigure_form_fields/new,12', responseDataTwo); + let wrapper; + await act(async() => { + wrapper = mount(); + }); + wrapper.update(); + await act(async() => { + wrapper.find('button[title="Disconnect"]').simulate('click'); + }); + wrapper.update(); + expect(fetchMock.calls()).toHaveLength(1); + expect(wrapper.find('button[title="Cancel Disconnect"]')).toBeDefined(); + expect(toJson(wrapper)).toMatchSnapshot(); + done(); + }); +}); diff --git a/app/javascript/spec/settings-compan-categories/__snapshots__/settings-company-categories.spec.js.snap b/app/javascript/spec/settings-compan-categories/__snapshots__/settings-company-categories.spec.js.snap index a7884ad42b5..d74dc3454be 100644 --- a/app/javascript/spec/settings-compan-categories/__snapshots__/settings-company-categories.spec.js.snap +++ b/app/javascript/spec/settings-compan-categories/__snapshots__/settings-company-categories.spec.js.snap @@ -595,6 +595,7 @@ exports[`SettingsCompanyCategories component should render a SettingsCompanyCate
"layouts/flash_msg" += react('ReconfigureVmForm', reconfigure_form_data) -%form#form_div.form-horizontal{"name" => "angularForm", - "ng-controller" => "reconfigureFormController as vm", - "miq-form" => 'true', - "model-copy" => 'vm.modelCopy', - "ng-show" => "vm.afterGet"} - = render :partial => "layouts/flash_msg" - %h3= _('Options') - - if role_allows?(:feature => 'vm_reconfigure_memory') - .form-group{"ng-class" => "{'has-error': angularForm.memory.$invalid}"} - %label.col-md-2.control-label - = _('Memory') - .col-md-1 - %input{"bs-switch" => "", - "type" => "checkbox", - "name" => "cb_memory", - "ng-model" => "vm.cb_memory", - "ng-change" => "vm.cbChange()", - "switch-on-text" => _("Yes"), - "switch-off-text" => _("No")} - #memory_div{"ng-if" => "vm.cb_memory"} - .col-md-4 - %input.form-control{"type" => "text", - "id" => "memory_value", - "name" => "memory", - "ng-model" => "vm.reconfigureModel.memory", - "ng-change" => "vm.cbChange()", - "maxlength" => "50", - "ng-pattern" => "/^[-+]?[0-9]+$/", - "miqrequired" => "", - "checkchange" => "", - "auto-focus" => "", - "validate-multiple" => "4", - :miqmin => "#{@reconfig_limits[:min__vm_memory]}", - :miqmax => "#{@reconfig_limits[:max__vm_memory]}", - :memtype => "{{vm.reconfigureModel.memory_type}}"} - %span{"style"=>"color:red", "ng-show" => "angularForm.memory.$invalid"} - = _(" Memory value not in range or not a multiple of 4") - %span{"style"=>"color:red", "ng-show" => "angularForm.memory.$required"} - = _(" Valid memory value required") - .col-md-2 - = select_tag('mem_type', - options_for_select(%w(MB GB)), - "ng-model" => "vm.reconfigureModel.memory_type", - "ng-change" => "vm.memtypeChanged()", - "maxlength" => "20", - "required" => "", - "selectpicker-for-select-tag" => "") - = (@reconfig_memory_note) - - if role_allows?(:feature => 'vm_reconfigure_cpu') - .form-group - %label.col-md-2.control-label - = _('Processors') - .col-md-1 - %input{"bs-switch" => "", - "type" => "checkbox", - "name" => "cb_cpu", - "ng-model" => "vm.cb_cpu", - "ng-change" => "vm.cbChange()", - "switch-on-text" => _("Yes"), - "switch-off-text" => _("No")} - %br - #cpu_div{"ng-if" => "vm.cb_cpu", :style => "margin-left: 20px"} - %h3= _(' Processor Options') - - if @socket_options.length > 1 - .form-group{"ng-class" => "{'has-error': angularForm.socket_count.$invalid}"} - %label.col-md-2.control-label - = _('Sockets') - .col-md-2 - = select_tag('socket_count', - options_for_select([["<#{_('Choose')}>", '']] + @socket_options, disabled: ["<#{_('Choose')}>", nil]), - "ng-model" => "vm.reconfigureModel.socket_count", - "ng-change" => "vm.processorValueChanged()", - "miqrequired" => "", - "maxlength" => "100", - "checkchange" => "", - "selectpicker-for-select-tag" => "") - - if @socket_options.length <= 1 - @socket_options[0] - - if @cores_options.length > 1 - .form-group{"ng-class" => "{'has-error': angularForm.cores_per_socket_count.$invalid}"} - %label.col-md-2.control-label - = _('Cores Per Socket') - .col-md-2 - = select_tag('cores_per_socket_count', - options_for_select([["<#{_('Choose')}>", '']] + @cores_options, disabled: ["<#{_('Choose')}>", nil]), - "ng-model" => "vm.reconfigureModel.cores_per_socket_count", - "ng-change" => "vm.processorValueChanged()", - "ng-pattern" => "/^[-+]?[0-9]+$/", - "miqrequired" => "", - "maxlength" => "100", - "checkchange" => "", - "selectpicker-for-select-tag" => "") - - if @cores_options.length <= 1 - @cores_options[0] - %span.help-block{"ng-if" => "angularForm.cores_per_socket_count.$dirty"} - = _("Note: a restart of the virtual machine might be required for the changes to apply.") - .form-group{"ng-class" => "{'has-error': angularForm.total_cpus.$invalid}"} - %label.col-sm-2.control-label - = _('Total Processors') - .col-md-2 - %input.form-control{"type" => "text", - "id" => "total_cpus", - "name" => "total_cpus", - "ng-model" => "vm.reconfigureModel.total_cpus", - :readonly => '', - "maxlength" => "50", - "validate_total" => "", - "miqmax" => "#{@reconfig_limits[:max__total_vcpus]}", - "auto-focus" => ""} - %span{"style" => "color:red", "ng-show" => "angularForm.total_cpus.$invalid"} - = _(" Total processors value larger than the maximum allowed") - - if item_supports?(:reconfigure_disks) && role_allows?(:feature => 'vm_reconfigure_disks') - %hr - %div - %h3 - = _('Disks') - %table{:width => "100%", :align => "bottom"} - %tr - %td#buttons_on{:align => "right"} - %button.btn.btn-primary{:type => "button", - "ng-click" => "vm.enableDiskAdd()", - :align => "left", - "ng-show" => "!vm.reconfigureModel.addEnabled"}= _('Add Disk') - %button.btn.btn-default.btn-sm{:type => "button", - "ng-click" => "vm.hideAddDisk()", - "ng-show" => "vm.reconfigureModel.addEnabled"}= _('Cancel Add') - %table.table.table-striped.table-condensed.table-bordered - %thead - %th= _('Name') - %th= _('Type') - %th{"ng-if" => "vm.vm_vendor == 'vmware' && vm.vm_type.includes('InfraManager')"}= _('Mode') - %th{"ng-if" => "vm.vm_vendor == 'vmware' && vm.vm_type.includes('InfraManager')"}= _('Controller Type') - %th= _('Size') - %th= _('Unit') - %th{"ng-if" => "vm.vm_vendor == 'vmware' && vm.vm_type.includes('InfraManager')"}= _('Dependent') - %th{"ng-hide" => "vm.isVmwareCloud()"}= _('Delete Backing') - %th{"ng-if" => "vm.vm_vendor == 'redhat'"}= _('Bootable') - - if item_supports?(:reconfigure_disksize) - %th{:colspan => 2}= _('Actions') - - else - %th= _('Actions') - %tbody - %tr{"ng-form" => "trForm", "ng-repeat" => "disk in vm.reconfigureModel.vmdisks", "ng-class" => "{'danger': disk.add_remove == 'remove', 'active': disk.add_remove == 'add'}"} - %td - {{disk.hdFilename}} - %td - {{disk.hdType}} - %td{"ng-if" => "vm.vm_vendor == 'vmware' && vm.vm_type.includes('InfraManager')"} - {{disk.hdMode}} - %td{"ng-if" => "vm.vm_vendor == 'vmware' && vm.vm_type.includes('InfraManager')"} - {{disk.new_controller_type}} - %td{"ng-if" => "disk.add_remove != 'resizing'"} - {{disk.hdSize}} - %td{"ng-if" => "disk.add_remove == 'resizing'"} - %input.form-control{"type" => "text", - "id" => "dvcResize", - "name" => "dvcResize", - "ng-model" => "disk.hdSize", - "required" => "", - "ng-pattern" => "hdpattern", - "placeholder" => _("Enter Size"), - "validate-multiple" => "1", - :miqmin => "{{ (disk.orgHdUnit === 'GB') ? (1024 * disk.orgHdSize + 1) : (1 * disk.orgHdSize + 1) }}", - :memtype => "{{disk.hdUnit}}"} - %span{"style" => "color:red", "ng-show" => "trForm.dvcResize.$invalid"} - = _("Disk size has to be greater than {{1*disk.orgHdSize+1}} {{disk.orgHdUnit}}") - %td{"ng-if" => "disk.add_remove != 'resizing'"} - {{disk.hdUnit}} - %td{"ng-if" => "disk.add_remove == 'resizing'"} - = select_tag('hdUnit', - options_for_select(%w(MB GB)), - "ng-model" => "disk.hdUnit", - "ng-change" => "vm.resizeDiskUnitChanged(disk)", - "data-width" => "auto", - "required" => "", - "selectpicker-for-select-tag" => "") - %td{"ng-if" => "vm.vm_vendor == 'vmware' && vm.vm_type.includes('InfraManager')"} - %input{"bs-switch" => "", - :data => {:on_text => _('Yes'), :off_text => _('No'), :size => 'mini'}, - "type" => "checkbox", - "name" => "vm.cb_dependent", - "ng-model" => "disk.cb_dependent", - "switch-active" => "{{disk.add_remove!='add'}}", - "ng-readonly" => "disk.add_remove=='add'", - "ng-if" => "disk.add_remove=='add'"} - %td{"ng-hide" => "vm.isVmwareCloud()"} - %input{"bs-switch" => "", - :data => {:on_text => _('Yes'), :off_text => _('No'), :size => 'mini'}, - "type" => "checkbox", - "name" => "cb_deletebacking", - "ng-model" => "disk.delete_backing", - "ng-readonly" => "disk.add_remove=='remove'", - "switch-active" => "{{disk.add_remove!='remove'}}", - "ng-if" => "disk.add_remove!='add'"} - %td{"ng-if" => @reconfigitems.first.vendor == 'redhat'} - %input{"bs-switch" => "", - :data => {:on_text => _('Yes'), :off_text => _('No'), :size => 'mini'}, - "type" => "checkbox", - "name" => "cb_bootable", - "ng-model" => "disk.cb_bootable", - "ng-readonly" => true, - "switch-active" => false} - - if item_supports?(:reconfigure_disksize) - %td.action-cell - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "disk.add_remove == ''", - "ng-click" => "vm.enableResizeDisk(disk)"}= _('Resize') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "disk.add_remove == 'resizing'", - "ng-disabled" => "trForm.dvcResize.$invalid || disk.hdSize == disk.orgHdSize", - "ng-click" => "vm.resizeDisk(disk)"}= _('Confirm Resize') - %td.action-cell - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "disk.add_remove == ''", - "ng-click" => "vm.deleteDisk(disk.hdFilename)"}= _('Delete') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "disk.add_remove == 'remove'", - "ng-click" => "vm.cancelAddRemoveDisk(disk)"}= _('Cancel Delete') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "disk.add_remove == 'add'", - "ng-click" => "vm.cancelAddRemoveDisk(disk)"}= _('Cancel Add') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "disk.add_remove == 'resizing'", - "ng-click" => "vm.cancelAddRemoveDisk(disk)"}= _('Cancel Resize') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "disk.add_remove == 'resize'", - "ng-click" => "vm.cancelAddRemoveDisk(disk)"}= _('Cancel Resize') - %tr{"ng-if" => "vm.reconfigureModel.addEnabled", - "ng-form" => "rowForm"} - %td - %td - - options = @reconfigitems.first.try(:disk_types) || %w(thick thin) - - default_option = @reconfigitems.first.try(:disk_default_type) || 'thin' - = select_tag('hdType', - options_for_select(options, :selected => default_option), - "ng-model" => "vm.reconfigureModel.hdType", - "ng-change" => "", - "data-width" => "auto", - "required" => "", - "selectpicker-for-select-tag" => "") - %td{"ng-if" => "vm.vm_vendor == 'vmware' && vm.vm_type.includes('InfraManager')"} - = select_tag('hdMode', - options_for_select(%w(persistent nonpersistent)), - "ng-model" => "vm.reconfigureModel.hdMode", - "ng-change" => "vm.hdModeChanged()", - "data-width" => "auto", - "required" => "", - "selectpicker-for-select-tag" => "", - "width" => "10") - %td{"ng-if" => "vm.vm_vendor == 'vmware' && vm.vm_type.includes('InfraManager')"} - - options = @reconfigitems.first.try(:scsi_controller_types) || {} - = select_tag('Controller', - options_for_select(options), - "ng-model" => "vm.reconfigureModel.new_controller_type", - "data-width" => "auto", - "required" => "", - "selectpicker-for-select-tag" => "") - %td - %input.form-control{"type" => "text", - "id" => "dvcSize", - "name" => "dvcSize", - "ng-model" => "vm.reconfigureModel.hdSize", - "required" => "", - "ng-pattern" => "hdpattern", - "placeholder" => _("Enter New Size"), - "validate-multiple" => "1", - :miqmin => "1", - :memtype => "{{vm.reconfigureModel.hdUnit}}"} - %span{"style" => "color:red", "ng-show" => "rowForm.dvcSize.$invalid"} - = _("Disk size has to be greater than 1 MB") - %td - = select_tag('hdUnit', - options_for_select(%w(MB GB)), - "ng-model" => "vm.reconfigureModel.hdUnit", - "ng-change" => "vm.resizeDiskUnitChanged(vm.reconfigureModel)", - "data-width" => "auto", - "required" => "", - "selectpicker-for-select-tag" => "") - %td{"ng-if" => "vm.vm_vendor == 'vmware' && vm.vm_type.includes('InfraManager')"} - %input{"bs-switch" => "", - :data => {:on_text => _('Yes'), :off_text => _('No'), :size => 'mini'}, - "type" => "checkbox", - "name" => "vm.cb_dependent", - "ng-model" => "vm.reconfigureModel.cb_dependent"} - %td{"ng-hide" => "vm.isVmwareCloud()"} - %td{"ng-if" => @reconfigitems.first.vendor == 'redhat'} - %input{"bs-switch" => "", - :data => {:on_text => _('Yes'), :off_text => _('No'), :size => 'mini'}, - "type" => "checkbox", - "name" => "vm.cb_bootable", - "ng-model" => "vm.reconfigureModel.cb_bootable"} - %td.action-cell - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-click" => "vm.addDisk()", - "ng-disabled" => "rowForm.dvcSize.$invalid"}= _(' Add ') - - if item_supports?(:reconfigure_disksize) - %td.action-cell - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-click" => "vm.hideAddDisk()"}= _('Cancel Add') - - if item_supports?(:reconfigure_network_adapters) && role_allows?(:feature => 'vm_reconfigure_networks') - %hr - %div - %h3 - = _('Network Adapters') - %table{:width => "100%", :align => "bottom"} - %tr - %td#buttons_on_nics{:align => "right"} - %button.btn.btn-primary{:type => "button", - "ng-click" => "vm.enableAddNetworkAdapter()", - :align => "left", - "ng-show" => "!vm.reconfigureModel.nicsEnabled", - "ng-disabled" => "!vm.reconfigureModel.enableAddNetworkAdapterButton"}= _('Add Network') - %button.btn.btn-default.btn-sm{:type => "button", - "ng-click" => "vm.hideAddNetworkAdapter()", - "ng-show" => "vm.reconfigureModel.nicsEnabled"}= _('Cancel Add') - %table.table.table-striped.table-condensed.table-bordered - %thead - %th= _('Name') - %th{"ng-if" => "!vm.isVmwareCloud()"}= _('vLan') - %th{"ng-if" => "vm.isVmwareCloud()"}= _('Network') - %th= _('MAC Address') - %th{:colspan => 2}= _('Actions') - %tr{"ng-repeat" => "networkAdapter in vm.reconfigureModel.vmNetworkAdapters", - "ng-class" => "{'danger': networkAdapter.add_remove == 'remove', 'active': networkAdapter.add_remove == 'add'}"} - %td - {{networkAdapter.name}} - %td{"ng-if" => "!vm.isVmwareCloud() && networkAdapter.add_remove == 'update'"} - - default_option = [("{{networkAdapter.vlan}}"),''] - = select_tag('vLan', - options_for_select([default_option] + @vlan_options, default_option), - "ng-model" => "networkAdapter.vLan_edit_requested", - "ng-change" => "", - "data-width" => "auto", - "required" => "", - "selectpicker-for-select-tag" => "") - %td{"ng-if" => "!vm.isVmwareCloud() && networkAdapter.add_remove != 'update'"} - {{networkAdapter.vlan}} - %td{"ng-if" => "vm.isVmwareCloud()"} - {{networkAdapter.network || "#{_('None')}"}} - %td.narrow - {{networkAdapter.mac}} - %td.action-cell - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "!vm.isVmwareCloud() && networkAdapter.add_remove == ''", - "ng-disabled" => "vm.checkEditNetworkAdapter()", - "ng-click" => "vm.editExistingNetworkAdapter(networkAdapter)"}= _('Edit') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "networkAdapter.add_remove == 'update'", - "ng-disabled" => "!vm.validateEditSelectedNetwork(networkAdapter)", - "ng-click" => "vm.confirmEditSelectedNetworkAdapter(networkAdapter)"}= _('Confirm Edit') - %td.action-cell - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "networkAdapter.add_remove == ''", - "ng-click" => "vm.removeExistingNetworkAdapter(networkAdapter)"}= _('Delete') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "networkAdapter.add_remove == 'remove'", - "ng-disabled" => "!vm.reconfigureModel.enableAddNetworkAdapterButton", - "ng-click" => "vm.cancelAddRemoveNetworkAdapter(networkAdapter)"}= _('Cancel Delete') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "networkAdapter.add_remove == 'add'", - "ng-click" => "vm.cancelAddRemoveNetworkAdapter(networkAdapter)"}= _('Cancel Add') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "networkAdapter.add_remove == 'update' || networkAdapter.add_remove == 'edit'", - "ng-click" => "vm.cancelChangeExistingNetworkAdapter(networkAdapter)"}= _('Cancel Edit') - %tr{"ng-if" => "vm.reconfigureModel.showDropDownNetwork", - "ng-form" => "rowForm"} - %td{"ng-if" => "!vm.isVmwareCloud()"} - %td{"ng-if" => "vm.isVmwareCloud()"} - = select_tag('adapterIdx', - options_for_select([["<#{_('Choose')}>", '']] + @avail_adapter_names, :disabled => ["<#{_('Choose')}>", nil]), - "ng-model" => "vm.reconfigureModel.name", - "ng-change" => "", - "data-width" => "auto", - "required" => "true", - "selectpicker-for-select-tag" => "") - %td{"ng-if" => "vm.isVmwareCloud()"} - %select{'name' => 'adapterNetwork', - 'ng-model' => 'vm.reconfigureModel.adapterNetwork', - 'ng-options' => 'network for network in vm.reconfigureModel.availableAdapterNetworks', - 'miq-select' => true, - 'selectpicker-for-select-tag' => ''} - %option{"value" => ""} - = "<#{_('Choose')}>" - %td{"ng-hide" => "vm.isVmwareCloud()"} - = select_tag('vLan', - options_for_select([["<#{_('Choose')}>", '']] + @vlan_options, :disabled => ["<#{_('Choose')}>", nil]), - "ng-model" => "vm.reconfigureModel.vLan_requested", - "ng-change" => "", - "data-width" => "auto", - "required" => "", - "selectpicker-for-select-tag" => "") - %td - %td.action-cell - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-click" => "vm.processAddSelectedNetwork();rowForm.vLan.selectionpicker('refresh')", - "ng-disabled" => "!vm.validateAddSelectedNetwork()"}= _('Confirm Add') - %td.action-cell - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-click" => "vm.hideAddNetworkAdapter()"}= _('Cancel Add') - - %hr - - - if item_supports?(:reconfigure_cdroms) && role_allows?(:feature => 'vm_reconfigure_drives') - %div{"ng-if" => "vm.reconfigureModel.vmCDRoms"} - %h3 - = _('CD/DVD Drives') - %table.table.table-striped.table-condensed.table-bordered - %thead - %th= _('Name') - %th= _('Host File') - %th{:colspan => 3}= _('Actions') - %tr{"ng-repeat" => "cdRom in vm.reconfigureModel.vmCDRoms", - "ng-class" => "{'danger': cdRom.connected_status == 'disconnected', 'active': cdRom.connected_status == 'connected'}"} - %td - {{cdRom.device_name}} - %td{"ng-if" => "cdRom.connect_disconnect != 'connecting'"} - {{cdRom.filename}} - %td{"ng-if" => "cdRom.connect_disconnect == 'connecting'"} - = select_tag('isoName', - options_for_select([["<#{_('Choose')}>", '']] + @iso_options, :disabled => ["<#{_('Choose')}>", nil]), - "ng-model" => "vm.selected_iso", - "ng-change" => "", - "data-width" => "auto", - "required" => "true", - "selectpicker-for-select-tag" => "") - %td.action-cell - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "cdRom.connect_disconnect != 'connecting' && cdRom.connect_disconnect != 'disconnecting'", - "ng-click" => "vm.enableConnectCDRom(cdRom)"}= _('Connect') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "cdRom.connect_disconnect == 'connecting'", - "ng-disabled" => "cdRom.filename == cdRom.orgfilename", - "ng-click" => "vm.connectCDRom(cdRom)"}= _('Confirm Connect') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "cdRom.filename != ''", - "ng-click" => "vm.enableDisconnectCDRom(cdRom)"}= _('Disconnect') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "cdRom.connect_disconnect == 'disconnecting'", - "ng-disabled" => "cdRom.connect_disconnect != 'disconnecting'", - "ng-click" => "vm.disconnectCDRom(cdRom)"}= _('Confirm') - %td.action-cell - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "cdRom.connect_disconnect == 'connect'", - "ng-click" => "vm.cancelCDRomConnectDisconnect(cdRom)"}= _('Cancel Connect') - %button.btn.btn-default.btn-block.btn-sm{:type => "button", - "ng-if" => "cdRom.connect_disconnect == 'disconnect'", - "ng-click" => "vm.cancelCDRomConnectDisconnect(cdRom)"}= _('Cancel Disconnect') - - %hr{"ng-if" => "vm.reconfigureModel.vmCDRoms"} - - - %table{:width => "100%", :align => "bottom"} - %tr - %td#buttons_on{:align => "right"} - %miq-button{:name => t = _('Submit'), - :title => t, - :alt => t, - :enabled => "!((angularForm.$pristine && !vm.cb_disks && !vm.cb_networkAdapters && !vm.cb_cdRoms) || angularForm.$invalid || (!vm.cb_memory && !vm.cb_cpu && !vm.cb_disks && !vm.cb_networkAdapters && !vm.cb_cdRoms))", - 'on-click' => "vm.submitClicked()", - :primary => 'true'} - %miq-button{:name => t = _('Reset'), - :title => t, - :alt => t, - :enabled => "!(angularForm.$pristine && !vm.cb_disks)", - 'on-click' => "vm.resetClicked()", - 'ng-show' => '!newRecord'} - %miq-button{:name => t = _('Cancel'), - :title => t, - :alt => t, - :enabled => "true", - 'on-click' => "vm.cancelClicked()"} %h3= _('Affected VMs') - if @reconfigitems - @edit ||={} - @edit[:object_ids] = @reconfigitems.collect(&:id) - @embedded = true - = render :partial => "layouts/gtl" - -:javascript - ManageIQ.angular.app.value('reconfigureFormId', '#{@request_id || "new"}'); - ManageIQ.angular.app.value('objectIds', #{ @reconfigitems.collect(&:id) }); - miq_bootstrap('#form_div'); + = render :partial => "layouts/gtl", :locals => {:no_flash_div => false} diff --git a/spec/controllers/vm_infra_controller_spec.rb b/spec/controllers/vm_infra_controller_spec.rb index e32c6007066..0cd858fbaf2 100644 --- a/spec/controllers/vm_infra_controller_spec.rb +++ b/spec/controllers/vm_infra_controller_spec.rb @@ -1,3 +1,5 @@ +require 'capybara/rspec' + describe VmInfraController do let(:host_1x1) { FactoryBot.create(:host_vmware_esx, :hardware => FactoryBot.create(:hardware, :cpu1x1, :ram1GB)) } let(:host_2x2) { FactoryBot.create(:host_vmware_esx, :hardware => FactoryBot.create(:hardware, :cpu2x2, :ram1GB)) } @@ -512,78 +514,6 @@ expect(response.status).to eq(200) end - it 'the reconfigure tab for a vm with max_cpu_cores_per_socket <= 1 should not display the cpu_cores_per_socket dropdown' do - vm = FactoryBot.create(:vm_vmware, - :host => host_1x1, - :hardware => FactoryBot.create(:hardware, :cpu1x1, :ram1GB, :virtual_hw_version => '04')) - allow(controller).to receive(:x_node).and_return("v-#{vm.id}") - - get :show, :params => {:id => vm.id} - expect(response).to redirect_to(:action => 'explorer') - - post :explorer - expect(response.status).to eq(200) - - post :x_button, :params => {:pressed => 'vm_reconfigure', :id => vm.id} - expect(response.status).to eq(200) - expect(response.body).to_not include('Total Processors') - end - - it 'the reconfigure tab for a vm with max_cpu_cores_per_socket > 1 should display the cpu_cores_per_socket dropdown' do - vm = FactoryBot.create(:vm_vmware, - :ext_management_system => FactoryBot.create(:ems_infra), - :host => host_2x2, - :hardware => FactoryBot.create(:hardware, :cpu1x1, :ram1GB, :virtual_hw_version => "07")) - allow(controller).to receive(:x_node).and_return("v-#{vm.id}") - - get :show, :params => {:id => vm.id} - expect(response).to redirect_to(:action => 'explorer') - - post :explorer - expect(response.status).to eq(200) - - post :x_button, :params => {:pressed => 'vm_reconfigure', :id => vm.id} - expect(response.status).to eq(200) - expect(response.body).to include('Total Processors') - end - - it 'the reconfigure tab for a single vmware vm should display the list of disks' do - vm = FactoryBot.create(:vm_vmware, - :ext_management_system => FactoryBot.create(:ems_infra), - :host => host_2x2, - :hardware => FactoryBot.create(:hardware, :cpu1x1, :ram1GB, :virtual_hw_version => "07")) - allow(controller).to receive(:x_node).and_return("v-#{vm.id}") - - get :show, :params => {:id => vm.id} - expect(response).to redirect_to(:action => 'explorer') - - post :explorer - expect(response.status).to eq(200) - - post :x_button, :params => {:pressed => 'vm_reconfigure', :id => vm.id} - expect(response.status).to eq(200) - expect(response.body).to include('Disks') - end - - it 'the reconfigure tab displays the submit and cancel buttons' do - vm = FactoryBot.create(:vm_vmware, - :ext_management_system => FactoryBot.create(:ems_infra), - :host => host_2x2, - :hardware => FactoryBot.create(:hardware, :cpu1x1, :ram1GB, :virtual_hw_version => "07")) - allow(controller).to receive(:x_node).and_return("v-#{vm.id}") - - get :show, :params => {:id => vm.id} - expect(response).to redirect_to(:action => 'explorer') - - post :explorer - expect(response.status).to eq(200) - - post :x_button, :params => {:pressed => 'vm_reconfigure', :id => vm.id} - expect(response.status).to eq(200) - expect(response.body).to include("miq-button alt='Submit'") - expect(response.body).to include("miq-button alt='Cancel'") - end - context "breadcrumbs" do subject { controller.instance_variable_get(:@breadcrumbs) } diff --git a/spec/javascripts/controllers/reconfigure/reconfigure_form_controller_spec.js b/spec/javascripts/controllers/reconfigure/reconfigure_form_controller_spec.js deleted file mode 100644 index f42969ce82c..00000000000 --- a/spec/javascripts/controllers/reconfigure/reconfigure_form_controller_spec.js +++ /dev/null @@ -1,125 +0,0 @@ -describe('reconfigureFormController', function() { - var $scope, vm, $httpBackend, miqService; - - beforeEach(module('ManageIQ')); - - beforeEach(inject(function($rootScope, _$controller_, _$httpBackend_, _miqService_) { - miqService = _miqService_; - spyOn(miqService, 'miqFlash'); - spyOn(miqService, 'miqAjaxButton'); - spyOn(miqService, 'sparkleOn'); - spyOn(miqService, 'sparkleOff'); - $scope = $rootScope.$new(); - var reconfigureFormResponse = {cb_memory: 'on', - memory: '4196', - memory_type: 'MB', - cb_cpu: 'on', - socket_count: '2', - cores_per_socket_count: '3', - disks: [{hdFilename: "test_disk.vmdk", hdType: "thick", hdMode: "persistent", new_controller_type: "VirtualLsiLogicController", hdSize: "0", hdUnit: "MB", add_remove: ""}], - network_adapters: [{name: "Network adapter 1", vlan: "test_network", mac: "00:00:00:00:00:00", add_remove: ""}], - cdroms: [{device_name: "CDROM 1", filename: "test_filename.iso", storage_id: '5', connect_disconnect: ""}], - vm_vendor: 'vm-vendor', - vm_type: 'vm-type', - disk_default_type: 'disk-default-type'}; - - $httpBackend = _$httpBackend_; - $httpBackend.whenGET('reconfigure_form_fields/1000000000003,1000000000001,1000000000002').respond(reconfigureFormResponse); - vm = _$controller_('reconfigureFormController', { - $scope: $scope, - reconfigureFormId: '1000000000003', - cb_memory: false, - cb_cpu: false, - objectIds: [1000000000001,1000000000002], - miqService: miqService - }); - $httpBackend.flush(); - })); - - afterEach(function() { - $httpBackend.verifyNoOutstandingExpectation(); - $httpBackend.verifyNoOutstandingRequest(); - }); - - describe('initialization', function() { - it('sets the reconfigure memory value to the value returned with http request', function() { - expect(vm.reconfigureModel.memory).toEqual('4196'); - }); - - it('sets the reconfigure socket count to the value returned with http request', function() { - expect(vm.reconfigureModel.socket_count).toEqual('2'); - }); - - it('sets the reconfigure cores per socket count to the value returned with http request', function() { - expect(vm.reconfigureModel.cores_per_socket_count).toEqual('3'); - }); - - it('sets the total socket count to the value calculated from the http request data', function() { - expect(vm.reconfigureModel.total_cpus).toEqual('6'); - }); - - it('initializes the delete_backing flag to false if not retrived', function() { - expect(vm.reconfigureModel.vmdisks[0].delete_backing).toEqual(false); - }); - it('sets the network adapter data to the network adapter data returned with the http request', function() { - expect(vm.reconfigureModel.vmNetworkAdapters).toEqual([{name: "Network adapter 1", vlan: "test_network", mac: "00:00:00:00:00:00", add_remove: ""}]); - }); - - it('sets the vm vendor data to the data returned with the http request', function() { - expect(vm.vm_vendor).toEqual('vm-vendor'); - }); - - it('sets the vm type data to the data returned with the http request', function() { - expect(vm.vm_type).toEqual('vm-type'); - }); - - it('sets the vm disk_default_type to the data returned with the http request', function() { - expect(vm.disk_default_type).toEqual('disk-default-type'); - }); - }); - - describe('#cancelClicked', function() { - beforeEach(function() { - $scope.angularForm = { - $setPristine: function(value) {} - }; - vm.cancelClicked(); - }); - - it('turns the spinner on via the miqService', function() { - expect(miqService.sparkleOn).toHaveBeenCalled(); - }); - - it('delegates to miqService.miqAjaxButton', function() { - expect(miqService.miqAjaxButton).toHaveBeenCalledWith('reconfigure_update?button=cancel'); - }); - }); - - describe('#submitClicked', function() { - beforeEach(function() { - $scope.angularForm = { - $setPristine: function (value){} - }; - vm.submitClicked(); - }); - - it('turns the spinner on via the miqService', function() { - expect(miqService.sparkleOn).toHaveBeenCalled(); - }); - - it('delegates to miqService.miqAjaxButton', function() { - var submitContent = {objectIds: vm.objectIds, - cb_memory: vm.cb_memory, - cb_cpu: vm.cb_cpu, - memory: vm.reconfigureModel.memory, - memory_type: vm.reconfigureModel.memory_type, - socket_count: vm.reconfigureModel.socket_count, - cores_per_socket_count: vm.reconfigureModel.cores_per_socket_count, - vmAddDisks: [ ], vmRemoveDisks: [ ], vmResizeDisks: [ ], - vmAddNetworkAdapters: [ ], vmRemoveNetworkAdapters: [ ], vmEditNetworkAdapters: [ ], - vmConnectCDRoms: [ ], vmDisconnectCDRoms: [ ]}; - - expect(miqService.miqAjaxButton).toHaveBeenCalledWith('reconfigure_update/1000000000003?button=submit', submitContent); - }); - }); -}); diff --git a/spec/views/vm_common/_reconfigure.html.haml_spec.rb b/spec/views/vm_common/_reconfigure.html.haml_spec.rb new file mode 100644 index 00000000000..e56fa9f17dc --- /dev/null +++ b/spec/views/vm_common/_reconfigure.html.haml_spec.rb @@ -0,0 +1,52 @@ +describe 'vm_common/_reconfigure.html.haml' do + before do + helper_data = { + :recordId => [12], + :requestId => 'new', + :roles => [ + :allowMemoryChange => true, + :allowCpuChange => true, + :allowDiskChange => true, + :allowDiskSizeChange => true, + :allowNetworkChange => true, + :allowCdromsChange => true, + :isVmwareInfra => true, + :isVmwareCloud => false, + :isRedhat => false, + ], + :memory => [ + :min => 4, + :max => 40, + :max_cpu => 14, + ], + :options => [ + :controller_types => [], + :vlan_options => [], + :avail_adapter_names => [], + :host_file_options => [], + :socket_options => ['1', '2', '3'], + :cores_options => ['1', '2', '3'], + ] + } + allow(view).to receive(:reconfigure_form_data) { helper_data } + allow(view).to receive(:render_gtl_outer) { true } + end + context 'render vm reconfigure page', :js => true do + let(:host_2x2) { FactoryBot.create(:host_vmware_esx, :hardware => FactoryBot.create(:hardware, :cpu2x2, :ram1GB)) } + let(:vm) do + FactoryBot.create(:vm_vmware, + :id => 12, + :ext_management_system => FactoryBot.create(:ems_infra), + :host => host_2x2, + :hardware => FactoryBot.create(:hardware, :cpu1x1, :ram1GB, :virtual_hw_version => "07")) + end + + it 'the reconfigure tab displays reconfigure form', :js => true do + view.instance_variable_set(:@edit, :roles => %w[fred wilma]) + view.instance_variable_set(:@reconfigitems, [vm]) + + render :partial => 'vm_common/reconfigure' + expect(response).to include('ReconfigureVmForm') + end + end +end