New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New VM from template flow #6937
New VM from template flow #6937
Conversation
37e0e5a
to
5e8542e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
small review
CLONE: 'Clone existing PVC', | ||
}; | ||
|
||
const DATA_SOURCES = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should probably create a new SelectDropdownObjectEnum
for this object.
see storage-ui-source.ts
for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!
|
||
<Form> | ||
<FormRow fieldId="form-data-source" title="Data source type" isRequired> | ||
<Select |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use the new <FormPFSelect />
instead of all new <Select />
.
It handles the isOpen
state for you
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's handy. Fixed.
4969457
to
1b5e13c
Compare
</FormRow> | ||
{state.dataSource?.value === DataSource.UPLOAD && ( | ||
<FormRow fieldId="form-ds-file" title="Upload source" isRequired> | ||
<FileUpload |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should add type restrictions and onDropReject handlers
dropzoneProps={{
accept: '.iso,.img,.qcow2,.gz,.xz',
onDropRejected: () => setIsFileRejected(true),
onDropAccepted: () => setIsFileRejected(false),
}}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About the filetypes, heads up:
https://bugzilla.redhat.com/show_bug.cgi?id=1894374
ebe9bc6
to
c4f193f
Compare
946e923
to
eabe015
Compare
[dispatch, storageClasses], | ||
); | ||
|
||
React.useEffect(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is still crashing the page
Uncaught error Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
at http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:403810:28
at checkForNestedUpdates (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:403813:7)
at scheduleUpdateOnFiber (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:402084:3)
at dispatchAction (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:396511:5)
at http://localhost:9000/static/kubevirt~kubevirt-create-vm-836eedccd7f68b69d796.js:533:5
at http://localhost:9000/static/kubevirt~kubevirt-create-vm-836eedccd7f68b69d796.js:550:7
at commitHookEffectList (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:400681:26)
at commitPassiveHookEffects (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:400711:11)
at HTMLUnknownElement.callCallback (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:381042:14)
at Object.invokeGuardedCallbackDev (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:381092:16)
window.onerror @
Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
at http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:403810:28
at checkForNestedUpdates (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:403813:7)
at scheduleUpdateOnFiber (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:402084:3)
at dispatchAction (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:396511:5)
at http://localhost:9000/static/kubevirt~kubevirt-create-vm-836eedccd7f68b69d796.js:533:5
at http://localhost:9000/static/kubevirt~kubevirt-create-vm-836eedccd7f68b69d796.js:550:7
at commitHookEffectList (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:400681:26)
at commitPassiveHookEffects (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:400711:11)
at HTMLUnknownElement.callCallback (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:381042:14)
at Object.invokeGuardedCallbackDev (http://localhost:9000/static/vendors~main-e7b448dfa7e4529ddc20.js:381092:16)
The above error occurred in the <BootSourceForm> component:
in BootSourceForm (created by BootSource)
in div (created by GridItem)
in GridItem (created by BootSource)
in div (created by Grid)
in Grid (created by BootSource)
in div (created by StackItem)
in StackItem (created by BootSource)
in div (created by Stack)
in Stack (created by BootSource)
in div (created by Data)
in Data (created by StatusBox)
in StatusBox (created by BootSource)
in BootSource (created by CreateVM)
in div (created by WizardBody)
in div (created by WizardBody)
in WizardBody (created by WizardToggle)
in div (created by WizardToggle)
in div (created by WizardToggle)
in WizardToggle (created by Wizard)
in div (created by Wizard)
in Wizard (created by CreateVM)
in div (created by CreateVM)
in CreateVM (created by AsyncComponent)
in AsyncComponent (created by Context.Consumer)
in Route (created by LazyRoute)
in LazyRoute (created by AppContents_)
in Switch (created by AppContents_)
in div (created by AppContents_)
in div (created by AppContents_)
in section (created by PageSection)
in PageSection (created by AppContents_)
in AppContents_ (created by ConnectFunction)
in ConnectFunction (created by App_)
in div (created by DrawerContent)
in div (created by DrawerMain)
in DrawerMain (created by DrawerContent)
in DrawerContent (created by NotificationDrawer)
in div (created by Drawer)
in Drawer (created by NotificationDrawer)
in NotificationDrawer (created by ConnectedNotificationDrawer_)
in ConnectedNotificationDrawer_ (created by ConnectFunction)
in ConnectFunction (created by App_)
in main (created by Page)
in div (created by Page)
in Page (created by App_)
in div (created by DrawerContentBody)
in DrawerContentBody (created by QuickStartDrawer)
in div (created by DrawerContent)
in div (created by DrawerMain)
in DrawerMain (created by DrawerContent)
in DrawerContent (created by QuickStartDrawer)
in div (created by Drawer)
in Drawer (created by QuickStartDrawer)
in QuickStartDrawer (created by ConnectFunction)
in ConnectFunction (created by App_)
in EnhancedProvider (created by App_)
in EnhancedProvider (created by App_)
in DetectPerspective (created by ConnectFunction)
in ConnectFunction (created by App_)
in App_ (created by withExtensions(App_))
in withExtensions(App_) (created by withI18nextTranslation(withExtensions(App_)))
in withI18nextTranslation(withExtensions(App_)) (created by Context.Consumer)
in Route
in Switch
in Router
in Provider
in Suspense
const name = (userMode === VMWizardMode.VM && searchParams.get('name')) || ''; | ||
const commonTemplateName = searchParams.get('common-template') || ''; | ||
const startVM = searchParams.get('startVM') === 'true' || false; | ||
let source: BootSourceParams; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better, although I think it would be more compact/readable and extensible if we passed all of the initialData in JSON.
and we can guard the whole initial data with userMode === VMWizardMode.VM
and se it to empty otherwise
@@ -266,12 +279,31 @@ export const DirectCommonDataProps = new Set<ChangedCommonDataProp>([ | |||
VMWizardProps.openshiftCNVBaseImages, | |||
]); | |||
|
|||
export enum URLParams { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we make the name more explicit and move it to src/constants? as it serves more as an interface and there is no need for the consumer of this to import the create-vm-wizard
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved to src/constants/url-params
. Is that ok with you ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
sourceType = ProvisionSource.DISK.getValue(); | ||
} | ||
|
||
dispatch( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should just set the value as else branch does instead of a dispatch. So we have just one atomic dispatch at the end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
const hasCustomSource = | ||
source?.url || source?.container || (source?.pvcName && source?.pvcNamespace); | ||
if (hasCustomSource) { | ||
let sourceType: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be of type ProvisionSource and getValue can be called just before we use the value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
return getUrlStorage(toShallowJS(iStorageClassConfigMap, undefined, true)); | ||
if (provisionSource === ProvisionSource.URL) { | ||
if (source?.url) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find two issue with current approach which might be confusing to the user.
There are actually 4 different Container types
classic containerDisk:
- create template -> container source
- create simple vm from base template -> container source -> switch to advanced wizard
container(registry) dataVolume
- create simple vm from base template -> container source
container(registry) dataVolume + additional disk
- create simple vm from base template -> container source + cdrom
classic containerDisk + additional disk:
- create simple vm from base template -> container source + cdrom -> switch to advanced wizard
I think it might seem to the user that s/he is getting the same thing, but the underlying representation is different each time.
Also I think the user would expect that the final result would not change by simply changing the view from simple to advanced.
Anyway this is not an easy topic. Maybe we should discuss this in a meeting or in a standup?
dispatch( | ||
vmWizardInternalActions[InternalActionType.UpdateStorage](id, { | ||
id: oldSourceStorage ? oldSourceStorage.id : getNextIDResolver(getStorages(state, id))(), | ||
...newSourceStorage, | ||
}), | ||
); | ||
if (newSourceStorage.disk.cdrom && !additionalStorage) { | ||
const emptyDisk = { | ||
id: getNextIDResolver(getStorages(getState(), id))(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets reuse and save the nextIDResolver so we dont have to call getStorages
twice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
const rootDisk = new DiskWrapper( | ||
vmWrapper.getDisks().find((d) => d.name === ROOT_DISK_NAME), | ||
true, | ||
).init({ bootOrder: 1 }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In #6937 (comment) I meant that we could call the setters from the init.
I would keep the setters and rather call setBootOrder here instead of init. Init should be meant for initializing empty wrappers, but this disk has been already initialized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, done
import '../create-vm-wizard/create-vm-wizard.scss'; | ||
import './create-vm.scss'; | ||
|
||
enum WIZARD_STEPS { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. I also meant the enum itself as WIZARD_STEPS is quite generic name.
We might also choose a better name for create-vm as we also have create-vm-wizard and both are wizard.
Thoughts?
@rawagner ok, let's resolve the other issues in followups |
e179b3d
to
d94c68e
Compare
} | ||
|
||
const paramsString = params.toString() ? `?${params}` : ''; | ||
|
||
return `/k8s/ns/${namespace || 'default'}/virtualization/${type}${paramsString}`; | ||
}; | ||
|
||
export const parseInitialData = (searchParams: URLSearchParams): InitialData => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks much better +1 for having the functions in the same place
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here parseVMWizardInitialData
?
@@ -266,12 +279,21 @@ export const DirectCommonDataProps = new Set<ChangedCommonDataProp>([ | |||
VMWizardProps.openshiftCNVBaseImages, | |||
]); | |||
|
|||
export type InitialData = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer if we could move this outside of the wizard since it is a general structure shared with outside as well (same as url params)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved outside together with BootSourceParams type.
@@ -266,12 +279,31 @@ export const DirectCommonDataProps = new Set<ChangedCommonDataProp>([ | |||
VMWizardProps.openshiftCNVBaseImages, | |||
]); | |||
|
|||
export enum URLParams { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did a quick pass. Looks pretty good, if we omit the postponed issues.
regarding this issue: #6937 (comment)
Are we going to fix this here or in a followup ?
Thanks Filip! i I will fix #6937 (comment). Regarding #6937 (comment) lets meet this week and fix it in a followup |
d94c68e
to
cf44d4f
Compare
@@ -0,0 +1,17 @@ | |||
export type InitialData = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could work on the naming a bit. What about VMWizardInitialData
and VMWizardBootSourceParams
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good, renamed all
} | ||
|
||
const paramsString = params.toString() ? `?${params}` : ''; | ||
|
||
return `/k8s/ns/${namespace || 'default'}/virtualization/${type}${paramsString}`; | ||
}; | ||
|
||
export const parseInitialData = (searchParams: URLSearchParams): InitialData => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here parseVMWizardInitialData
?
/retest |
cf44d4f
to
da79087
Compare
/lgtm |
/retest |
da79087
to
705ad0d
Compare
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: glekner, rawagner, suomiy The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
@rawagner: The following test failed, say
Full PR test history. Your PR dashboard. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
/retest Please review the full test history for this PR and help us cut down flakes. |
TODO (for followups):