diff --git a/src/fireedge/src/client/components/Status/Circle.js b/src/fireedge/src/client/components/Status/Circle.js
new file mode 100644
index 0000000000..5df405de29
--- /dev/null
+++ b/src/fireedge/src/client/components/Status/Circle.js
@@ -0,0 +1,44 @@
+import * as React from 'react'
+import PropTypes from 'prop-types'
+
+import { Tooltip, Typography } from '@material-ui/core'
+
+const StatusCircle = ({ color, tooltip, size }) => (
+ {tooltip}}
+ >
+
+
+)
+
+StatusCircle.propTypes = {
+ tooltip: PropTypes.string,
+ color: PropTypes.string,
+ size: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number
+ ])
+}
+
+StatusCircle.defaultProps = {
+ tooltip: undefined,
+ color: undefined,
+ size: 12
+}
+
+StatusCircle.displayName = 'StatusCircle'
+
+export default StatusCircle
diff --git a/src/fireedge/src/client/components/Status/index.js b/src/fireedge/src/client/components/Status/index.js
index 3ac225cdd1..1a1a5153dd 100644
--- a/src/fireedge/src/client/components/Status/index.js
+++ b/src/fireedge/src/client/components/Status/index.js
@@ -1,9 +1,11 @@
import StatusBadge from 'client/components/Status/Badge'
import StatusChip from 'client/components/Status/Chip'
+import StatusCircle from 'client/components/Status/Circle'
import LinearProgressWithLabel from 'client/components/Status/LinearProgressWithLabel'
export {
StatusBadge,
StatusChip,
+ StatusCircle,
LinearProgressWithLabel
}
diff --git a/src/fireedge/src/client/components/Tables/Vms/columns.js b/src/fireedge/src/client/components/Tables/Vms/columns.js
index 4d3959f146..4528662152 100644
--- a/src/fireedge/src/client/components/Tables/Vms/columns.js
+++ b/src/fireedge/src/client/components/Tables/Vms/columns.js
@@ -1,63 +1,8 @@
-import * as React from 'react'
-
-import { StatusBadge } from 'client/components/Status'
-import * as VirtualMachineModel from 'client/models/VirtualMachine'
-
export default [
- /* {
- id: 'selection',
- // The header can use the table's getToggleAllRowsSelectedProps method
- // to render a checkbox.
- // Pagination is a problem since this will select all rows even though
- // not all rows are on the current page.
- // The solution should be server side pagination.
- // For one, the clients should not download all rows in most cases.
- // The client should only download data for the current page.
- // In that case, getToggleAllRowsSelectedProps works fine.
- Header: ({ getToggleAllRowsSelectedProps }) => (
-
- ),
- // The cell can use the individual row's getToggleRowSelectedProps method
- // to the render a checkbox
- Cell: ({ row }) => (
-
- )
- }, */
- {
- Header: '',
- id: 'STATE',
- width: 50,
- accessor: row => {
- const state = VirtualMachineModel.getState(row)
-
- return (
-
- )
- }
- // Cell: ({ value: { name, color } = {} }) => name && (
- //
- // ),
- // Filter: ({ column }) => (
- //
- // ),
- // filter: (rows, id, filterValue) =>
- // rows.filter(row => row.values[id]?.name === filterValue)
- },
- { Header: '#', accessor: 'ID', width: 45 },
- { Header: 'Name', accessor: 'NAME' },
- {
- Header: 'Owner/Group',
- accessor: row => `${row.UNAME}/${row.GNAME}`
- },
- {
- Header: 'Ips',
- accessor: row => VirtualMachineModel.getIps(row).join(',')
- // Cell: ({ value }) => value.map(nic => (
- //
- // ))
- }
+ { Header: '', accessor: 'ID' },
+ { Header: '', accessor: 'NAME' },
+ { Header: '', accessor: 'STATE' },
+ { Header: '', accessor: 'LCM_STATE' },
+ { Header: '', accessor: 'UID' },
+ { Header: '', accessor: 'GID' }
]
diff --git a/src/fireedge/src/client/components/Tables/Vms/detail.js b/src/fireedge/src/client/components/Tables/Vms/detail.js
new file mode 100644
index 0000000000..448db43ceb
--- /dev/null
+++ b/src/fireedge/src/client/components/Tables/Vms/detail.js
@@ -0,0 +1,207 @@
+import React, { useEffect } from 'react'
+import { LinearProgress, Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core'
+
+import Tabs from 'client/components/Tabs'
+import { StatusBadge } from 'client/components/Status'
+
+import { useFetch, useSocket } from 'client/hooks'
+import { useVmApi } from 'client/features/One'
+
+import * as VirtualMachine from 'client/models/VirtualMachine'
+import * as Helper from 'client/models/Helper'
+import { prettyBytes } from 'client/utils'
+
+const NavArrowDown = {'>'}
+
+const VmDetail = ({ id }) => {
+ const { getVm } = useVmApi()
+ const { getHooksSocketTemporal } = useSocket()
+ const socketTemporal = getHooksSocketTemporal({ resource: 'vm', id })
+
+ const { data, fetchRequest, loading, error } = useFetch(getVm)
+ const isLoading = (!data && !error) || loading
+
+ useEffect(() => {
+ fetchRequest(id)
+ }, [id])
+
+ useEffect(() => {
+ if (!isLoading && data) {
+ console.log('connect???')
+ socketTemporal.connect(console.log)
+ }
+
+ return () => {
+ socketTemporal.disconnect()
+ }
+ }, [isLoading, data])
+
+ if (isLoading) {
+ return
+ }
+
+ if (error) {
+ return
{error}
+ }
+
+ const { ID, NAME, UNAME, GNAME, RESCHED, STIME, ETIME, LOCK, DEPLOY_ID, TEMPLATE, USER_TEMPLATE } = data
+
+ const isVCenter = VirtualMachine.isVCenter(data)
+ const { name: stateName, color: stateColor } = VirtualMachine.getState(data)
+
+ const { HID: hostId, HOSTNAME: hostname = '--', CID: clusterId } = VirtualMachine.getLastHistory(data)
+ const clusterName = clusterId === '-1' ? 'default' : '--' // TODO: get from cluster list
+
+ const ips = VirtualMachine.getIps(data)
+ const { nics, alias } = VirtualMachine.splitNicAlias(data)
+
+ const disks = VirtualMachine.getDisks(data)
+
+ const tabs = [
+ {
+ name: 'info',
+ renderContent: (
+
+
+
+
+ {`#${ID} - ${NAME}`}
+
+
+
+
Owner: {UNAME}
+
Group: {GNAME}
+
Reschedule: {Helper.booleanToString(+RESCHED)}
+
Locked: {Helper.levelLockToString(LOCK?.LOCKED)}
+
IP: {ips.join(', ') || '--'}
+
Start time: {Helper.timeToString(STIME)}
+
End time: {Helper.timeToString(ETIME)}
+
Host: {`#${hostId} ${hostname}`}
+
Cluster: {`#${clusterId} ${clusterName}`}
+
Deploy ID: {DEPLOY_ID}
+
+
+ )
+ },
+ {
+ name: 'capacity',
+ renderContent: (
+
+
Physical CPU: {TEMPLATE?.CPU}
+
Virtual CPU: {TEMPLATE?.VCPU ?? '-'}
+ {isVCenter && (
+
Virtual Cores: {`
+ Cores x ${TEMPLATE?.TOPOLOGY?.CORES || '-'} |
+ Sockets ${TEMPLATE?.TOPOLOGY?.SOCKETS || '-'}
+ `}
+ )}
+
Memory: {prettyBytes(+TEMPLATE?.MEMORY, 'MB')}
+
Cost / CPU: {TEMPLATE?.CPU_COST}
+
Cost / MByte: {TEMPLATE?.MEMORY_COST}
+
+ )
+ },
+ {
+ name: 'storage',
+ renderContent: (
+
+
VM DISKS
+ {disks.map(({
+ DISK_ID,
+ DATASTORE = '-',
+ TARGET = '-',
+ IMAGE,
+ TYPE,
+ FORMAT,
+ SIZE,
+ MONITOR_SIZE,
+ READONLY,
+ SAVE = 'No',
+ CLONE
+ }) => {
+ const size = +SIZE ? prettyBytes(+SIZE, 'MB') : '-'
+ const monitorSize = +MONITOR_SIZE ? prettyBytes(+MONITOR_SIZE, 'MB') : '-'
+
+ const type = String(TYPE).toLowerCase()
+
+ const image = IMAGE ?? ({
+ fs: `${FORMAT} - ${size}`,
+ swap: size
+ }[type])
+
+ return (
+
+ {`${DISK_ID} | ${DATASTORE} | ${TARGET} | ${image} | ${monitorSize}/${size} | ${type} | ${READONLY} | ${SAVE} | ${CLONE}`}
+
+ )
+ })}
+
+ )
+ },
+ {
+ name: 'network',
+ renderContent: (
+
+
+
VM NICS
+ {nics.map(({ NIC_ID, NETWORK = '-', BRIDGE = '-', IP = '-', MAC = '-', PCI_ID = '' }) => (
+
+ {`${NIC_ID} | ${NETWORK} | ${BRIDGE} | ${IP} | ${MAC} | ${PCI_ID}`}
+
+ ))}
+
+
+
+
VM ALIAS
+ {alias.map(({ NIC_ID, NETWORK = '-', BRIDGE = '-', IP = '-', MAC = '-' }) => (
+
+ {`${NIC_ID} | ${NETWORK} | ${BRIDGE} | ${IP} | ${MAC}`}
+
+ ))}
+
+
+ )
+ },
+ {
+ name: 'template',
+ renderContent: (
+
+
+
+ User Template
+
+
+
+
+ {JSON.stringify(USER_TEMPLATE, null, 2)}
+
+
+
+
+
+
+ Template
+
+
+
+
+ {JSON.stringify(TEMPLATE, null, 2)}
+
+
+
+
+
+ )
+ }
+ ]
+
+ return (
+
+ )
+}
+
+export default VmDetail
diff --git a/src/fireedge/src/client/components/Tables/Vms/index.js b/src/fireedge/src/client/components/Tables/Vms/index.js
index 31a8382866..e835d479d9 100644
--- a/src/fireedge/src/client/components/Tables/Vms/index.js
+++ b/src/fireedge/src/client/components/Tables/Vms/index.js
@@ -5,16 +5,17 @@ import { useFetch } from 'client/hooks'
import { useVm, useVmApi } from 'client/features/One'
import { EnhancedTable } from 'client/components/Tables'
-import { VirtualMachineCard } from 'client/components/Cards'
-import Columns from 'client/components/Tables/Vms/columns'
+import VmColumns from 'client/components/Tables/Vms/columns'
+import VmRow from 'client/components/Tables/Vms/row'
+import VmDetail from 'client/components/Tables/Vms/detail'
const INITIAL_ELEMENT = 0
-const NUMBER_OF_INTERVAL = 6
+const NUMBER_OF_INTERVAL = 10
const VmsTable = () => {
const [[start, end], setPage] = useState([INITIAL_ELEMENT, -NUMBER_OF_INTERVAL])
- const columns = React.useMemo(() => Columns, [])
+ const columns = React.useMemo(() => VmColumns, [])
const vms = useVm()
const { getVms } = useVmApi()
@@ -44,9 +45,11 @@ const VmsTable = () => {
pageSize={NUMBER_OF_INTERVAL / 2}
isLoading={loading || reloading}
showPageCount={false}
+ getRowId={row => String(row.ID)}
+ RowComponent={VmRow}
+ renderDetail={row => }
canFetchMore={canFetchMore}
fetchMore={fetchMore}
- MobileComponentRow={VirtualMachineCard}
/>
)
}
diff --git a/src/fireedge/src/client/components/Tables/Vms/multiple.js b/src/fireedge/src/client/components/Tables/Vms/multiple.js
new file mode 100644
index 0000000000..369d26ab67
--- /dev/null
+++ b/src/fireedge/src/client/components/Tables/Vms/multiple.js
@@ -0,0 +1,40 @@
+import * as React from 'react'
+import PropTypes from 'prop-types'
+
+import { Tooltip, Typography } from '@material-ui/core'
+
+import { StatusChip } from 'client/components/Status'
+
+const Multiple = ({ tags, limitTags = 1 }) => {
+ if (tags?.length === 0) {
+ return null
+ }
+
+ const more = tags.length - limitTags
+
+ const Tags = tags.splice(0, limitTags).map(tag => (
+
+ ))
+
+ return [
+ ...Tags,
+ (more > 0 && (
+ (
+ {tag}
+ ))}
+ >
+
+ {`+${more} more`}
+
+
+ ))
+ ]
+}
+
+Multiple.propTypes = {
+ tags: PropTypes.array,
+ limitTags: PropTypes.number
+}
+
+export default Multiple
diff --git a/src/fireedge/src/client/components/Tables/Vms/row.js b/src/fireedge/src/client/components/Tables/Vms/row.js
new file mode 100644
index 0000000000..fe14da171f
--- /dev/null
+++ b/src/fireedge/src/client/components/Tables/Vms/row.js
@@ -0,0 +1,66 @@
+import * as React from 'react'
+import PropTypes from 'prop-types'
+
+import { User, Group, Lock, HardDrive } from 'iconoir-react'
+import { Typography } from '@material-ui/core'
+
+import { StatusCircle } from 'client/components/Status'
+import Multiple from 'client/components/Tables/Vms/multiple'
+import { rowStyles } from 'client/components/Tables/styles'
+
+import * as VirtualMachineModel from 'client/models/VirtualMachine'
+import * as Helper from 'client/models/Helper'
+
+const Row = ({ value, ...props }) => {
+ const classes = rowStyles()
+ const { ID, NAME, UNAME, GNAME, STIME, ETIME, LOCK } = value
+
+ const state = VirtualMachineModel.getState(value)
+ const ips = VirtualMachineModel.getIps(value)
+ const { HOSTNAME = '--' } = VirtualMachineModel.getLastHistory(value)
+
+ const time = Helper.timeFromMilliseconds(+ETIME || +STIME)
+ const timeAgo = `${+ETIME ? 'done' : 'started'} ${time.toRelative()}`
+
+ return (
+
+
+
+
+
+
+ {NAME}
+ {LOCK && }
+
+
+
+ {`#${ID} ${timeAgo}`}
+
+
+
+ {` ${UNAME}`}
+
+
+
+ {` ${GNAME}`}
+
+
+
+ {` ${HOSTNAME}`}
+
+
+
+
+
+
+
+ )
+}
+
+Row.propTypes = {
+ value: PropTypes.object,
+ isSelected: PropTypes.bool,
+ handleClick: PropTypes.func
+}
+
+export default Row
diff --git a/src/fireedge/src/client/components/Tables/index.js b/src/fireedge/src/client/components/Tables/index.js
index 59a66bad8f..d6ca395ab1 100644
--- a/src/fireedge/src/client/components/Tables/index.js
+++ b/src/fireedge/src/client/components/Tables/index.js
@@ -1,13 +1,20 @@
import DatastoresTable from 'client/components/Tables/Datastores'
import EnhancedTable from 'client/components/Tables/Enhanced'
import HostsTable from 'client/components/Tables/Hosts'
+import ImagesTable from 'client/components/Tables/Images'
+import MarketplaceAppsTable from 'client/components/Tables/MarketplaceApps'
+import MarketplacesTable from 'client/components/Tables/Marketplaces'
import VirtualizedTable from 'client/components/Tables/Virtualized'
import VmsTable from 'client/components/Tables/Vms'
export {
- DatastoresTable,
EnhancedTable,
- HostsTable,
VirtualizedTable,
+
+ DatastoresTable,
+ HostsTable,
+ ImagesTable,
+ MarketplaceAppsTable,
+ MarketplacesTable,
VmsTable
}
diff --git a/src/fireedge/src/client/components/Tables/styles.js b/src/fireedge/src/client/components/Tables/styles.js
new file mode 100644
index 0000000000..a23634c8d8
--- /dev/null
+++ b/src/fireedge/src/client/components/Tables/styles.js
@@ -0,0 +1,40 @@
+import { makeStyles } from '@material-ui/core'
+
+export const rowStyles = makeStyles(
+ ({ palette, typography, breakpoints }) => ({
+ main: {
+ flex: 'auto'
+ },
+ title: {
+ color: palette.text.primary,
+ display: 'flex',
+ alignItems: 'center'
+ },
+ labels: {
+ display: 'inline-flex',
+ gap: 6,
+ marginLeft: 6
+ },
+ caption: {
+ ...typography.caption,
+ color: palette.text.secondary,
+ marginTop: 4,
+ display: 'flex',
+ gap: 8,
+ wordWrap: 'break-word'
+ },
+ secondary: {
+ width: '25%',
+ flexShrink: 0,
+ whiteSpace: 'nowrap',
+ textAlign: 'right',
+ [breakpoints.down('sm')]: {
+ display: 'none'
+ },
+ '& > *': {
+ flexShrink: 0,
+ whiteSpace: 'nowrap'
+ }
+ }
+ })
+)
diff --git a/src/fireedge/src/client/components/Tabs/index.js b/src/fireedge/src/client/components/Tabs/index.js
new file mode 100644
index 0000000000..9bbb330086
--- /dev/null
+++ b/src/fireedge/src/client/components/Tabs/index.js
@@ -0,0 +1,69 @@
+import React, { useState, useMemo, memo } from 'react'
+import PropTypes from 'prop-types'
+
+import { Tabs as MTabs, Tab as MTab } from '@material-ui/core'
+
+const Content = memo(({ name, renderContent, hidden }) => (
+
+ {typeof renderContent === 'function' ? renderContent() : renderContent}
+
+), (prev, next) => prev.hidden === next.hidden)
+
+const Tabs = ({ tabs = [] }) => {
+ const [tabSelected, setTab] = useState(0)
+
+ const renderTabs = useMemo(() => (
+ setTab(tab)}
+ >
+ {tabs.map(({ value, name, icon: Icon }, idx) =>
+ }
+ value={value ?? idx}
+ label={String(name).toUpperCase()}
+ />
+ )}
+
+ ), [tabSelected])
+
+ const renderTabContent = useMemo(() =>
+ tabs.map((tabProps, idx) => {
+ const { name, value = idx } = tabProps
+ const hidden = tabSelected !== value
+
+ return
+ }), [tabSelected])
+
+ return (
+ <>
+ {renderTabs}
+ {renderTabContent}
+ >
+ )
+}
+
+Tabs.displayName = 'Tabs'
+Content.displayName = 'Content'
+
+Content.propTypes = {
+ name: PropTypes.string,
+ renderContent: PropTypes.oneOfType([
+ PropTypes.object,
+ PropTypes.func
+ ]),
+ hidden: PropTypes.bool
+}
+
+export default Tabs
diff --git a/src/fireedge/src/client/constants/states.js b/src/fireedge/src/client/constants/states.js
index 77f14da6d2..4e184b48ba 100644
--- a/src/fireedge/src/client/constants/states.js
+++ b/src/fireedge/src/client/constants/states.js
@@ -13,10 +13,12 @@ export const BOOT_UNKNOWN = 'BOOT_UNKNOWN'
export const CANCEL = 'CANCEL'
export const CLEANUP_DELETE = 'CLEANUP_DELETE'
export const CLEANUP_RESUBMIT = 'CLEANUP_RESUBMIT'
+export const CLONE = 'CLONE'
export const CLONING = 'CLONING'
export const CLONING_FAILURE = 'CLONING_FAILURE'
export const CONFIGURING = 'CONFIGURING'
export const COOLDOWN = 'COOLDOWN'
+export const DELETE = 'DELETE'
export const DELETING = 'DELETING'
export const DEPLOYING = 'DEPLOYING'
export const DISABLED = 'DISABLED'
@@ -60,6 +62,9 @@ export const HOTPLUG_SAVEAS_UNDEPLOYED = 'HOTPLUG_SAVEAS_UNDEPLOYED'
export const HOTPLUG_SNAPSHOT = 'HOTPLUG_SNAPSHOT'
export const INIT = 'INIT'
export const LCM_INIT = 'LCM_INIT'
+export const LOCKED = 'LOCKED'
+export const LOCKED_USED = 'LOCKED_USED'
+export const LOCKED_USED_PERS = 'LOCKED_USED_PERS'
export const MIGRATE = 'MIGRATE'
export const MONITORED = 'MONITORED'
export const MONITORING_DISABLED = 'MONITORING_DISABLED'
@@ -94,7 +99,9 @@ export const SHUTDOWN_POWEROFF = 'SHUTDOWN_POWEROFF'
export const SHUTDOWN_UNDEPLOY = 'SHUTDOWN_UNDEPLOY'
export const STOPPED = 'STOPPED'
export const SUSPENDED = 'SUSPENDED'
-export const UNKNOWN = 'UNKNOWN'
export const UNDEPLOYED = 'UNDEPLOYED'
export const UNDEPLOYING = 'UNDEPLOYING'
+export const UNKNOWN = 'UNKNOWN'
+export const USED = 'USED'
+export const USED_PERS = 'USED_PERS'
export const WARNING = 'WARNING'
diff --git a/src/fireedge/src/client/constants/translates.js b/src/fireedge/src/client/constants/translates.js
index 1e673c22bf..2442ff7e9b 100644
--- a/src/fireedge/src/client/constants/translates.js
+++ b/src/fireedge/src/client/constants/translates.js
@@ -1,6 +1,7 @@
module.exports = {
/* pagination / stepper */
Back: 'Back',
+ Previous: 'Previous',
Next: 'Next',
/* actions */
@@ -41,6 +42,8 @@ module.exports = {
/* errors */
CannotConnectOneFlow: 'Cannot connect to OneFlow server',
CannotConnectOneProvision: 'Cannot connect to OneProvision server',
+ ErrorOneProvisionGUI: 'FireEdge is not correctly configured to operate the OneProvision GUI',
+ ContactYourAdmin: 'Please contact your system administrator',
NotFound: 'Not found',
None: 'None',
Empty: 'Empty',
diff --git a/src/fireedge/src/client/models/Helper.js b/src/fireedge/src/client/models/Helper.js
new file mode 100644
index 0000000000..cb098eb806
--- /dev/null
+++ b/src/fireedge/src/client/models/Helper.js
@@ -0,0 +1,17 @@
+import { DateTime } from 'luxon'
+
+export const booleanToString = bool => bool ? 'Yes' : 'No'
+
+export const timeToString = time =>
+ +time ? new Date(+time * 1000).toLocaleString() : '-'
+
+export const timeFromMilliseconds = time =>
+ DateTime.fromMillis(+time * 1000)
+
+export const levelLockToString = level => ({
+ 0: 'None',
+ 1: 'Use',
+ 2: 'Manage',
+ 3: 'Admin',
+ 4: 'All'
+}[level] || '-')
diff --git a/src/fireedge/src/client/models/VirtualMachine.js b/src/fireedge/src/client/models/VirtualMachine.js
index 354788c6cb..2c6aa07151 100644
--- a/src/fireedge/src/client/models/VirtualMachine.js
+++ b/src/fireedge/src/client/models/VirtualMachine.js
@@ -20,45 +20,116 @@ const NIC_ALIAS_IP_ATTRS = [
'VROUTER_IP6_ULA'
]
+/**
+ * @param {Array} vms List of virtual machines
+ * @returns {Array} Clean list of vms with done state
+ */
export const filterDoneVms = (vms = []) =>
vms.filter(({ STATE }) => VM_STATES[STATE]?.name !== STATES.DONE)
+/**
+ * @param {Object} vm Virtual machine
+ * @returns {Object} Last history record from resource
+ */
+export const getLastHistory = vm => {
+ const history = vm?.HISTORY_RECORDS?.HISTORY ?? {}
+
+ return Array.isArray(history) ? history[history.length - 1] : history
+}
+
+/**
+ * @param {Object} vm Virtual machine
+ * @returns {String} Resource type: VR, FLOW or VM
+ */
+export const getType = vm => vm.TEMPLATE?.VROUTER_ID
+ ? 'VR' : vm?.USER_TEMPLATE?.USER_TEMPLATE?.SERVICE_ID ? 'FLOW' : 'VM'
+
+/**
+ * @param {Object} vm Virtual machine
+ * @returns {String} Resource hypervisor
+ */
+export const getHypervisor = vm => String(getLastHistory(vm)?.VM_MAD).toLowerCase()
+
+/**
+ * @param {Object} vm Virtual machine
+ * @returns {Boolean} If the hypervisor is vCenter
+ */
+export const isVCenter = vm => getHypervisor(vm) === 'vcenter'
+
+/**
+ * @type {{color: string, name: string, meaning: string}} StateInfo
+ *
+ * @param {Object} vm Virtual machine
+ * @returns {StateInfo} State information from resource
+ */
export const getState = ({ STATE, LCM_STATE } = {}) => {
const state = VM_STATES[+STATE]
return state?.name === STATES.ACTIVE ? VM_LCM_STATES[+LCM_STATE] : state
}
-export const getIps = ({ TEMPLATE = {} } = {}) => {
- const { NIC = [], PCI = [] } = TEMPLATE
- // TODO: add monitoring ips
+/**
+ * @param {Object} vm Virtual machine
+ * @returns {Array} List of disks from resource
+ */
+export const getDisks = ({ TEMPLATE = {}, MONITORING = {}, ...vm } = {}) => {
+ const contextDisk = TEMPLATE.CONTEXT && !isVCenter(vm) && {
+ ...TEMPLATE.CONTEXT,
+ IMAGE: 'CONTEXT',
+ DATASTORE: '-',
+ TYPE: '-',
+ READONLY: '-',
+ SAVE: '-',
+ CLONE: '-',
+ SAVE_AS: '-'
+ }
- const nics = [NIC, PCI].flat()
+ const addMonitoringData = disk => ({
+ ...disk,
+ // get monitoring data
+ MONITOR_SIZE: MONITORING.DISK_SIZE
+ ?.find(({ ID }) => ID === disk.DISK_ID)?.SIZE || '-'
+ })
- return nics
- .map(nic => NIC_ALIAS_IP_ATTRS.map(attr => nic[attr]).filter(Boolean))
+ return [TEMPLATE.DISK, contextDisk]
.flat()
+ .filter(Boolean)
+ .map(addMonitoringData)
}
-const getNicsFromMonitoring = ({ ID }) => {
- const monitoringPool = {} // _getMonitoringPool()
- const monitoringVM = monitoringPool[ID]
+/**
+ * @param {Object} vm Virtual machine
+ * @returns {Array} List of nics from resource
+ */
+export const getNics = ({ TEMPLATE = {}, MONITORING = {} } = {}) => {
+ const { NIC = [], NIC_ALIAS = [], PCI = [] } = TEMPLATE
+ const { GUEST_IP, GUEST_IP_ADDRESSES = '' } = MONITORING
- if (!monitoringPool || Object.keys(monitoringPool).length === 0 || !monitoringVM) return []
+ const extraIps = [GUEST_IP, ...GUEST_IP_ADDRESSES?.split(',')]
+ .filter(Boolean)
+ .map(ip => ({ NIC_ID: '-', IP: ip, NETWORK: 'Additional IP', BRIDGE: '-' }))
- return EXTERNAL_IP_ATTRS.reduce(function (externalNics, attr) {
- const monitoringValues = monitoringVM[attr]
-
- if (monitoringValues) {
- monitoringValues.split(',').forEach((_, ip) => {
- const exists = externalNics.some(nic => nic.IP === ip)
-
- if (!exists) {
- externalNics.push({ NIC_ID: '_', IP: ip })
- }
- })
- }
-
- return externalNics
- }, [])
+ return [NIC, NIC_ALIAS, PCI, extraIps].flat().filter(Boolean)
}
+
+/**
+ * @param {Object} vm Virtual machine
+ * @returns {Array} List of ips from resource
+ */
+export const getIps = vm => {
+ const getIpsFromNic = nic => NIC_ALIAS_IP_ATTRS.map(attr => nic[attr]).filter(Boolean)
+
+ return getNics(vm).map(getIpsFromNic).flat()
+}
+
+/**
+ * @type {{nics: Array, alias: Array}} Nics&Alias
+ *
+ * @param {Object} vm Virtual machine
+ * @returns {Nics&Alias} Lists of nics and alias from resource
+ */
+export const splitNicAlias = vm => getNics(vm).reduce((result, nic) => {
+ result[nic?.PARENT !== undefined ? 'alias' : 'nics'].push(nic)
+
+ return result
+}, { nics: [], alias: [] })