-
Notifications
You must be signed in to change notification settings - Fork 265
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
feat(xo-server/xo-web): in host advanced tab, display mdadm status #8190
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,10 @@ const CACHE_2CRSI = new TTLCache({ | |
ttl: 6e4, | ||
}) | ||
|
||
const CACHE_MDADM = new TTLCache({ | ||
ttl: 6e5, | ||
}) | ||
|
||
const log = createLogger('xo:api:host') | ||
|
||
// =================================================================== | ||
|
@@ -624,6 +628,20 @@ getSmartctlInformation.resolve = { | |
host: ['id', 'host', 'view'], | ||
} | ||
|
||
export function getMdadmHealth({ host }) { | ||
return this.getXapi(host).getHostMdadmHealth(host._xapiId, { cache: CACHE_MDADM }) | ||
} | ||
|
||
getMdadmHealth.description = 'get mdadm health status' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
getMdadmHealth.params = { | ||
id: { type: 'string' }, | ||
} | ||
|
||
getMdadmHealth.resolve = { | ||
host: ['id', 'host', 'view'], | ||
} | ||
|
||
export async function getBlockdevices({ host }) { | ||
const xapi = this.getXapi(host) | ||
if (host.productBrand !== 'XCP-ng') { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1569,4 +1569,24 @@ export default class Xapi extends XapiBase { | |
|
||
return { currentBiosVersion, latestBiosVersion, biosLink, isUpToDate } | ||
} | ||
|
||
async getHostMdadmHealth(hostId, { cache } = {}) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why put a cache in this method? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was suggested by Olivier in the issue |
||
if (cache?.has(hostId)) { | ||
return cache.get(hostId) | ||
} | ||
try { | ||
const result = await this.call('host.call_plugin', this.getObject(hostId).$ref, 'raid.py', 'check_raid_pool', {}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the call take more than a second, use |
||
const parsedResult = JSON.parse(result) | ||
|
||
cache?.set(hostId, parsedResult) | ||
|
||
return parsedResult | ||
} catch (error) { | ||
if (error.code === 'XENAPI_MISSING_PLUGIN' || error.code === 'UNKNOWN_XENAPI_PLUGIN_FUNCTION') { | ||
return null | ||
} else { | ||
throw error | ||
} | ||
} | ||
} | ||
Comment on lines
+1573
to
+1591
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMHO, this method can be moved into |
||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -15,6 +15,7 @@ import { | |||||||||||||
addTag, | ||||||||||||||
editHost, | ||||||||||||||
fetchHostStats, | ||||||||||||||
getMdadmHealth, | ||||||||||||||
isHostTimeConsistentWithXoaTime, | ||||||||||||||
isPubKeyTooShort, | ||||||||||||||
removeTag, | ||||||||||||||
|
@@ -63,6 +64,7 @@ export default class HostItem extends Component { | |||||||||||||
state = { | ||||||||||||||
isHostTimeConsistentWithXoaTime: true, | ||||||||||||||
isPubKeyTooShort: false, | ||||||||||||||
mdadmHealth: null, | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why initialize as |
||||||||||||||
} | ||||||||||||||
|
||||||||||||||
componentWillMount() { | ||||||||||||||
|
@@ -72,6 +74,13 @@ export default class HostItem extends Component { | |||||||||||||
isHostTimeConsistentWithXoaTime: value, | ||||||||||||||
}) | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
this.fetchMdadmHealth() | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not using |
||||||||||||||
} | ||||||||||||||
|
||||||||||||||
async fetchMdadmHealth() { | ||||||||||||||
const mdadmHealth = await getMdadmHealth(this.props.item).catch(() => null) | ||||||||||||||
this.setState({ mdadmHealth }) | ||||||||||||||
Comment on lines
+82
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
} | ||||||||||||||
|
||||||||||||||
get _isRunning() { | ||||||||||||||
|
@@ -144,14 +153,16 @@ export default class HostItem extends Component { | |||||||||||||
this._getAreHostsVersionsEqual, | ||||||||||||||
() => this.props.state.hostsByPoolId[this.props.item.$pool], | ||||||||||||||
() => this.state.isPubKeyTooShort, | ||||||||||||||
() => this.state.mdadmHealth, | ||||||||||||||
( | ||||||||||||||
needsRestart, | ||||||||||||||
host, | ||||||||||||||
isMaintained, | ||||||||||||||
isHostTimeConsistentWithXoaTime, | ||||||||||||||
areHostsVersionsEqual, | ||||||||||||||
poolHosts, | ||||||||||||||
isPubKeyTooShort | ||||||||||||||
isPubKeyTooShort, | ||||||||||||||
mdadmHealth | ||||||||||||||
) => { | ||||||||||||||
const alerts = [] | ||||||||||||||
|
||||||||||||||
|
@@ -262,6 +273,17 @@ export default class HostItem extends Component { | |||||||||||||
}) | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
if (mdadmHealth?.raid?.State && !['clean', 'active'].includes(mdadmHealth.raid.State)) { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Always explicit condition. Exepct for
Suggested change
|
||||||||||||||
alerts.push({ | ||||||||||||||
level: 'danger', | ||||||||||||||
render: ( | ||||||||||||||
<span> | ||||||||||||||
<Icon icon='alarm' className='text-danger' /> {_('raidStateWarning', { state: mdadmHealth.raid.State })} | ||||||||||||||
</span> | ||||||||||||||
), | ||||||||||||||
}) | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
return alerts | ||||||||||||||
} | ||||||||||||||
) | ||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -37,6 +37,7 @@ import { | |||||
isPciHidden, | ||||||
isPciPassthroughAvailable, | ||||||
isNetDataInstalledOnHost, | ||||||
getMdadmHealth, | ||||||
getPlugin, | ||||||
getSmartctlHealth, | ||||||
getSmartctlInformation, | ||||||
|
@@ -319,13 +320,17 @@ export default class extends Component { | |||||
) | ||||||
} | ||||||
|
||||||
const mdadmHealth = await getMdadmHealth(host).catch(console.error) | ||||||
|
||||||
this.setState({ | ||||||
isHtEnabled: await isHyperThreadingEnabledHost(host).catch(() => null), | ||||||
isSmartctlHealthEnabled, | ||||||
pciStateById, | ||||||
smartctlUnhealthyDevices, | ||||||
unhealthyDevicesAlerts, | ||||||
isPciPassthroughAvailable: _isPciPassthroughAvailable, | ||||||
mdadmHealthAvailable: mdadmHealth?.raid ? mdadmHealth : null, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
mdadmState: mdadmHealth.raid?.State, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mdadmState: mdadmHealthAvailable ? mdadmHealth.raid?.State : undefined, |
||||||
}) | ||||||
} | ||||||
|
||||||
|
@@ -394,6 +399,8 @@ export default class extends Component { | |||||
isSmartctlHealthEnabled, | ||||||
unhealthyDevicesAlerts, | ||||||
smartctlUnhealthyDevices, | ||||||
mdadmHealthAvailable, | ||||||
mdadmState, | ||||||
} = this.state | ||||||
|
||||||
const _isXcpNgHost = host.productBrand === 'XCP-ng' | ||||||
|
@@ -688,6 +695,12 @@ export default class extends Component { | |||||
))} | ||||||
</td> | ||||||
</tr> | ||||||
{mdadmHealthAvailable && ( | ||||||
<tr> | ||||||
<th>{_('raidStatus')}</th> | ||||||
<td>{mdadmState === 'clean' || mdadmState === 'active' ? _('raidHealthy') : mdadmState}</td> | ||||||
</tr> | ||||||
)} | ||||||
Comment on lines
+698
to
+703
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid to hide information, add a message that explain "Why mdadmHealthAvailable is false". |
||||||
</tbody> | ||||||
</table> | ||||||
<br /> | ||||||
|
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.