mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-16 22:50:10 +03:00
F OpenNebula/one#5422: Add sched actions tab (#1379)
This commit is contained in:
parent
54e1c43a1b
commit
494aa50781
@ -151,6 +151,7 @@ info-tabs:
|
||||
enabled: true
|
||||
actions:
|
||||
sched_action_create: true
|
||||
sched_action_update: true
|
||||
sched_action_delete: true
|
||||
charter_create: true
|
||||
|
||||
|
@ -151,6 +151,7 @@ info-tabs:
|
||||
enabled: true
|
||||
actions:
|
||||
sched_action_create: true
|
||||
sched_action_update: true
|
||||
sched_action_delete: true
|
||||
charter_create: true
|
||||
|
||||
|
@ -45,7 +45,7 @@ const VmNetworkTab = ({ tabProps = {} }) => {
|
||||
<>
|
||||
{actionsAvailable?.includes?.(VM_ACTIONS.ATTACH_NIC) && (
|
||||
<Button
|
||||
data-cy='resize'
|
||||
data-cy='attach-nic'
|
||||
size='small'
|
||||
color='secondary'
|
||||
onClick={show}
|
||||
|
118
src/fireedge/src/client/components/Tabs/Vm/SchedActions/Item.js
Normal file
118
src/fireedge/src/client/components/Tabs/Vm/SchedActions/Item.js
Normal file
@ -0,0 +1,118 @@
|
||||
/* ------------------------------------------------------------------------- *
|
||||
* Copyright 2002-2021, OpenNebula Project, OpenNebula Systems *
|
||||
* *
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
|
||||
* not use this file except in compliance with the License. You may obtain *
|
||||
* a copy of the License at *
|
||||
* *
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 *
|
||||
* *
|
||||
* Unless required by applicable law or agreed to in writing, software *
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, *
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
|
||||
* See the License for the specific language governing permissions and *
|
||||
* limitations under the License. *
|
||||
* ------------------------------------------------------------------------- */
|
||||
/* eslint-disable jsdoc/require-jsdoc */
|
||||
import * as React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { Edit, Trash, WarningTriangleOutline } from 'iconoir-react'
|
||||
import { useTheme, Typography, Paper } from '@material-ui/core'
|
||||
|
||||
// import { useVmApi } from 'client/features/One'
|
||||
import { Action } from 'client/components/Cards/SelectCard'
|
||||
import { StatusChip } from 'client/components/Status'
|
||||
import { rowStyles } from 'client/components/Tables/styles'
|
||||
|
||||
import * as VirtualMachine from 'client/models/VirtualMachine'
|
||||
import * as Helper from 'client/models/Helper'
|
||||
import { VM_ACTIONS } from 'client/constants'
|
||||
|
||||
const SchedulingItem = ({ vmStartTime, schedule, actions = [] }) => {
|
||||
const classes = rowStyles()
|
||||
const { palette } = useTheme()
|
||||
|
||||
const { ID, ACTION, TIME, MESSAGE, DONE, WARNING } = schedule
|
||||
|
||||
const isRelative = String(TIME).includes('+')
|
||||
|
||||
const time = Helper.timeFromMilliseconds(
|
||||
isRelative ? (+vmStartTime + +TIME) : +TIME
|
||||
)
|
||||
|
||||
const doneTime = Helper.timeFromMilliseconds(+DONE)
|
||||
|
||||
const now = Math.round(Date.now() / 1000)
|
||||
const isWarning = WARNING && (now - +vmStartTime) > +WARNING
|
||||
|
||||
const labels = [...new Set([
|
||||
Helper.stringToBoolean(MESSAGE)
|
||||
])].filter(Boolean)
|
||||
|
||||
const { repeat, end } = VirtualMachine.periodicityToString(schedule)
|
||||
|
||||
return (
|
||||
<Paper variant='outlined' className={classes.root}>
|
||||
<div className={classes.main}>
|
||||
<div className={classes.title}>
|
||||
<Typography component='span'>
|
||||
{`#${ID} ${ACTION}`}
|
||||
</Typography>
|
||||
{!!labels.length && (
|
||||
<span className={classes.labels}>
|
||||
{labels.map(label => (
|
||||
<StatusChip key={label} text={label} />
|
||||
))}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className={classes.caption}>
|
||||
{repeat && <span>{repeat}</span>}
|
||||
{end && <span>{`| ${end}`}</span>}
|
||||
{DONE && (
|
||||
<span title={doneTime.toFormat('ff')}>
|
||||
{`| done ${doneTime.toRelative()}`}
|
||||
</span>
|
||||
)}
|
||||
<span style={{ display: 'flex', gap: '0.5em' }}>
|
||||
<span title={time.toFormat('ff')}>
|
||||
{`| ${time.toRelative()}`}
|
||||
</span>
|
||||
{isWarning && (
|
||||
<WarningTriangleOutline size={18} color={palette.warning.main} />
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{!!actions.length && (
|
||||
<div className={classes.actions}>
|
||||
{actions?.includes?.(VM_ACTIONS.SCHED_ACTION_UPDATE) && (
|
||||
<Action
|
||||
cy={`${VM_ACTIONS.SCHED_ACTION_UPDATE}-${ID}`}
|
||||
icon={<Edit size={18} />}
|
||||
handleClick={() => undefined}
|
||||
/>
|
||||
)}
|
||||
{actions?.includes?.(VM_ACTIONS.SCHED_ACTION_DELETE) && (
|
||||
<Action
|
||||
cy={`${VM_ACTIONS.SCHED_ACTION_DELETE}-${ID}`}
|
||||
icon={<Trash size={18} />}
|
||||
handleClick={() => undefined}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
|
||||
SchedulingItem.propTypes = {
|
||||
vmStartTime: PropTypes.string.isRequired,
|
||||
schedule: PropTypes.object.isRequired,
|
||||
actions: PropTypes.arrayOf(PropTypes.string)
|
||||
}
|
||||
|
||||
SchedulingItem.displayName = 'SchedulingItem'
|
||||
|
||||
export default SchedulingItem
|
@ -15,15 +15,29 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
/* eslint-disable jsdoc/require-jsdoc */
|
||||
import * as React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const VmSchedulingTab = data => {
|
||||
return (
|
||||
<div>
|
||||
<p>WIP - SCHED ACTIONS</p>
|
||||
</div>
|
||||
)
|
||||
import SchedulingItem from 'client/components/Tabs/Vm/SchedActions/Item'
|
||||
|
||||
const SchedulingList = ({ vmStartTime, scheduling, actions }) => (
|
||||
<div style={{ display: 'grid', gap: '1em', paddingBlock: '0.8em' }}>
|
||||
{scheduling.map((schedule, idx) => (
|
||||
<SchedulingItem
|
||||
key={idx}
|
||||
vmStartTime={vmStartTime}
|
||||
schedule={schedule}
|
||||
actions={actions}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
|
||||
SchedulingList.propTypes = {
|
||||
vmStartTime: PropTypes.string,
|
||||
scheduling: PropTypes.array,
|
||||
actions: PropTypes.arrayOf(PropTypes.string)
|
||||
}
|
||||
|
||||
VmSchedulingTab.displayName = 'VmSchedulingTab'
|
||||
SchedulingList.displayName = 'SchedulingList'
|
||||
|
||||
export default VmSchedulingTab
|
||||
export default SchedulingList
|
@ -0,0 +1,92 @@
|
||||
/* ------------------------------------------------------------------------- *
|
||||
* Copyright 2002-2021, OpenNebula Project, OpenNebula Systems *
|
||||
* *
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
|
||||
* not use this file except in compliance with the License. You may obtain *
|
||||
* a copy of the License at *
|
||||
* *
|
||||
* http://www.apache.org/licenses/LICENSE-2.0 *
|
||||
* *
|
||||
* Unless required by applicable law or agreed to in writing, software *
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, *
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
|
||||
* See the License for the specific language governing permissions and *
|
||||
* limitations under the License. *
|
||||
* ------------------------------------------------------------------------- */
|
||||
/* eslint-disable jsdoc/require-jsdoc */
|
||||
import * as React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { ClockOutline } from 'iconoir-react'
|
||||
import { Button } from '@material-ui/core'
|
||||
|
||||
import { useDialog } from 'client/hooks'
|
||||
import { TabContext } from 'client/components/Tabs/TabProvider'
|
||||
import { DialogConfirmation } from 'client/components/Dialogs'
|
||||
import SchedulingList from 'client/components/Tabs/Vm/SchedActions/List'
|
||||
import { SubmitButton } from 'client/components/FormControl'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
|
||||
import * as VirtualMachine from 'client/models/VirtualMachine'
|
||||
import * as Helper from 'client/models/Helper'
|
||||
import { T, VM_ACTIONS } from 'client/constants'
|
||||
|
||||
const VmSchedulingTab = ({ tabProps = {} }) => {
|
||||
const { display, show, hide } = useDialog()
|
||||
const { data: vm } = React.useContext(TabContext)
|
||||
const { actions = [] } = tabProps
|
||||
|
||||
const scheduling = VirtualMachine.getScheduleActions(vm)
|
||||
|
||||
const hypervisor = VirtualMachine.getHypervisor(vm)
|
||||
const actionsAvailable = Helper.getActionsAvailable(actions, hypervisor)
|
||||
|
||||
return (
|
||||
<>
|
||||
{actionsAvailable?.includes?.(VM_ACTIONS.SCHED_ACTION_CREATE) && (
|
||||
<Button
|
||||
data-cy='sched-action-create'
|
||||
size='small'
|
||||
color='secondary'
|
||||
onClick={show}
|
||||
variant='contained'
|
||||
>
|
||||
{Tr(T.AddAction)}
|
||||
</Button>
|
||||
)}
|
||||
{actionsAvailable?.includes?.(VM_ACTIONS.CHARTER_CREATE) && (
|
||||
<SubmitButton
|
||||
data-cy='charter-create'
|
||||
color='secondary'
|
||||
icon
|
||||
label={<ClockOutline />}
|
||||
onClick={show}
|
||||
/>
|
||||
)}
|
||||
|
||||
<SchedulingList
|
||||
actions={actionsAvailable}
|
||||
scheduling={scheduling}
|
||||
vmStartTime={vm?.STIME}
|
||||
/>
|
||||
|
||||
{display && (
|
||||
<DialogConfirmation
|
||||
title={T.AddAction}
|
||||
handleAccept={hide}
|
||||
handleCancel={hide}
|
||||
>
|
||||
<p>TODO: should define in view yaml ??</p>
|
||||
</DialogConfirmation>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
VmSchedulingTab.propTypes = {
|
||||
tabProps: PropTypes.object
|
||||
}
|
||||
|
||||
VmSchedulingTab.displayName = 'VmSchedulingTab'
|
||||
|
||||
export default VmSchedulingTab
|
@ -42,7 +42,7 @@ const VmStorageTab = ({ tabProps = {} }) => {
|
||||
<>
|
||||
{actionsAvailable?.includes?.(VM_ACTIONS.ATTACH_DISK) && (
|
||||
<Button
|
||||
data-cy='resize'
|
||||
data-cy='attach-disk'
|
||||
size='small'
|
||||
color='secondary'
|
||||
onClick={show}
|
||||
|
@ -21,6 +21,7 @@ module.exports = {
|
||||
SortBy: 'Sort by',
|
||||
Filter: 'Filter',
|
||||
All: 'All',
|
||||
On: 'On',
|
||||
|
||||
/* actions */
|
||||
Accept: 'Accept',
|
||||
@ -50,10 +51,32 @@ module.exports = {
|
||||
AttachNic: 'Attach nic',
|
||||
Detach: 'Detach',
|
||||
TakeSnapshot: 'Take snapshot',
|
||||
AddAction: 'Add action',
|
||||
|
||||
/* questions */
|
||||
DoYouWantProceed: 'Do you want proceed?',
|
||||
|
||||
/* Scheduling */
|
||||
Mon: 'Mon',
|
||||
Monday: 'Monday',
|
||||
Tue: 'Tue',
|
||||
Tuesday: 'Tuesday',
|
||||
Wed: 'Wed',
|
||||
Wednesday: 'Wednesday',
|
||||
Thu: 'Thu',
|
||||
Thursday: 'Thursday',
|
||||
Fri: 'Fri',
|
||||
Friday: 'Friday',
|
||||
Sat: 'Sat',
|
||||
Saturday: 'Saturday',
|
||||
Sun: 'Sun',
|
||||
Sunday: 'Sunday',
|
||||
Weekly: 'Weekly',
|
||||
Monthly: 'Monthly',
|
||||
Yearly: 'Yearly',
|
||||
EachHours: 'Each %s hours',
|
||||
AfterTimes: 'After %s times',
|
||||
|
||||
/* dashboard */
|
||||
InTotal: 'In Total',
|
||||
Used: 'Used',
|
||||
|
@ -494,6 +494,7 @@ export const VM_ACTIONS = {
|
||||
|
||||
// SCHEDULING ACTION
|
||||
SCHED_ACTION_CREATE: 'sched_action_create',
|
||||
SCHED_ACTION_UPDATE: 'sched_action_update',
|
||||
SCHED_ACTION_DELETE: 'sched_action_delete',
|
||||
CHARTER_CREATE: 'charter_create',
|
||||
|
||||
|
@ -46,13 +46,14 @@ export const vmService = ({
|
||||
* @param {string} data.filter - Filter flag
|
||||
* @param {number} data.start - Range start ID
|
||||
* @param {number} data.end - Range end ID
|
||||
* @param {string|number} data.state - Filter state
|
||||
* @returns {Array} List of VMs
|
||||
* @throws Fails when response isn't code 200
|
||||
*/
|
||||
getVms: async ({ filter, start, end }) => {
|
||||
getVms: async ({ filter, start, end, state }) => {
|
||||
const name = Actions.VM_POOL_INFO
|
||||
const command = { name, ...Commands[name] }
|
||||
const config = requestConfig({ filter, start, end }, command)
|
||||
const config = requestConfig({ filter, start, end, state }, command)
|
||||
|
||||
const res = await RestClient.request(config)
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
* limitations under the License. *
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { getSecurityGroupsFromResource, prettySecurityGroup } from 'client/models/SecurityGroup'
|
||||
import { timeToString } from 'client/models/Helper'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
|
||||
import {
|
||||
STATES,
|
||||
@ -21,15 +23,10 @@ import {
|
||||
VM_LCM_STATES,
|
||||
NIC_ALIAS_IP_ATTRS,
|
||||
HISTORY_ACTIONS,
|
||||
T,
|
||||
StateInfo
|
||||
} from 'client/constants'
|
||||
|
||||
/**
|
||||
* @param {string|number} action - Action code
|
||||
* @returns {HISTORY_ACTIONS} History action name
|
||||
*/
|
||||
export const getHistoryAction = action => HISTORY_ACTIONS[+action]
|
||||
|
||||
/**
|
||||
* This function removes, from the given list,
|
||||
* the Virtual machines in state DONE.
|
||||
@ -40,6 +37,12 @@ export const getHistoryAction = action => HISTORY_ACTIONS[+action]
|
||||
export const filterDoneVms = (vms = []) =>
|
||||
vms.filter(({ STATE }) => VM_STATES[STATE]?.name !== STATES.DONE)
|
||||
|
||||
/**
|
||||
* @param {string|number} action - Action code
|
||||
* @returns {HISTORY_ACTIONS} History action name
|
||||
*/
|
||||
export const getHistoryAction = action => HISTORY_ACTIONS[+action]
|
||||
|
||||
/**
|
||||
* @param {object} vm - Virtual machine
|
||||
* @returns {object} History records from resource
|
||||
@ -195,5 +198,43 @@ export const splitNicAlias = vm =>
|
||||
export const getSnapshotList = vm => {
|
||||
const { TEMPLATE = {} } = vm ?? {}
|
||||
|
||||
return [TEMPLATE.SNAPSHOT].flat()
|
||||
return [TEMPLATE.SNAPSHOT].filter(Boolean).flat()
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} vm - Virtual machine
|
||||
* @returns {Array} List of schedule actions from resource
|
||||
*/
|
||||
export const getScheduleActions = vm => {
|
||||
const { TEMPLATE = {} } = vm ?? {}
|
||||
|
||||
return [TEMPLATE.SCHED_ACTION].filter(Boolean).flat()
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the periodicity of the action to string value.
|
||||
*
|
||||
* @param {object} scheduleAction - Schedule action
|
||||
* @returns {{repeat: string|string[], end: string}} - Periodicity of the action.
|
||||
*/
|
||||
export const periodicityToString = scheduleAction => {
|
||||
const { REPEAT, DAYS = '', END_TYPE, END_VALUE = '' } = scheduleAction ?? {}
|
||||
|
||||
const daysOfWeek = [T.Sun, T.Mon, T.Tue, T.Wed, T.Thu, T.Fri, T.Sat]
|
||||
const days = DAYS?.split(',')?.map(day => Tr(daysOfWeek[day])) ?? []
|
||||
|
||||
const repeat = {
|
||||
0: `${Tr(T.Weekly)} ${days.join(',')}`,
|
||||
1: `${Tr(T.Monthly)} ${DAYS}`,
|
||||
2: `${Tr(T.Yearly)} ${DAYS}`,
|
||||
3: Tr([T.EachHours, DAYS])
|
||||
}[+REPEAT]
|
||||
|
||||
const end = {
|
||||
0: Tr(T.None),
|
||||
1: Tr([T.AfterTimes, END_VALUE]),
|
||||
2: `${Tr(T.On)} ${timeToString(END_VALUE)}`
|
||||
}[+END_TYPE]
|
||||
|
||||
return { repeat, end }
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user