xva-store v1
This commit is contained in:
@@ -20,7 +20,8 @@ class XoServerCloud {
|
||||
}
|
||||
|
||||
async load() {
|
||||
const getResourceCatalog = ({ hub } = {}) => this._getCatalog({ hub })
|
||||
const getResourceCatalog = ({ filters } = {}) =>
|
||||
this._getCatalog({ filters })
|
||||
getResourceCatalog.description =
|
||||
"Get the list of user's available resources"
|
||||
getResourceCatalog.permission = 'admin'
|
||||
@@ -67,8 +68,8 @@ class XoServerCloud {
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
async _getCatalog({ hub } = {}) {
|
||||
const catalog = await this._updater.call('getResourceCatalog', { hub })
|
||||
async _getCatalog({ filters } = {}) {
|
||||
const catalog = await this._updater.call('getResourceCatalog', { filters })
|
||||
|
||||
if (!catalog) {
|
||||
throw new Error('cannot get catalog')
|
||||
@@ -79,8 +80,8 @@ class XoServerCloud {
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
async _getNamespaces({ hub } = {}) {
|
||||
const catalog = await this._getCatalog({ hub })
|
||||
async _getNamespaces() {
|
||||
const catalog = await this._getCatalog()
|
||||
|
||||
if (!catalog._namespaces) {
|
||||
throw new Error('cannot get namespaces')
|
||||
@@ -108,7 +109,9 @@ class XoServerCloud {
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
async _getNamespaceCatalog(namespace, hub) {
|
||||
const namespaceCatalog = (await this._getCatalog({ hub }))[namespace]
|
||||
const namespaceCatalog = (await this._getCatalog({ filters: { hub } }))[
|
||||
namespace
|
||||
]
|
||||
|
||||
if (!namespaceCatalog) {
|
||||
throw new Error(`cannot get catalog: ${namespace} not registered`)
|
||||
@@ -120,12 +123,12 @@ class XoServerCloud {
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
async _requestResource(namespace, id, version, hub) {
|
||||
const _namespace = (await this._getNamespaces({ hub }))[namespace]
|
||||
const _namespace = (await this._getNamespaces())[namespace]
|
||||
const { _token: token } = await this._getNamespaceCatalog(namespace, hub)
|
||||
|
||||
if (!hub && (!_namespace || !_namespace.registered)) {
|
||||
throw new Error(`cannot get resource: ${namespace} not registered`)
|
||||
}
|
||||
const { _token: token } = await this._getNamespaceCatalog(namespace, hub)
|
||||
|
||||
// 2018-03-20 Extra check: getResourceDownloadToken seems to be called without a token in some cases
|
||||
if (token === undefined) {
|
||||
@@ -136,8 +139,6 @@ class XoServerCloud {
|
||||
token,
|
||||
id,
|
||||
version,
|
||||
namespace,
|
||||
hub,
|
||||
})
|
||||
|
||||
if (!downloadToken) {
|
||||
|
||||
@@ -2146,6 +2146,9 @@ const messages = {
|
||||
// Hub
|
||||
hubPage: 'Hub',
|
||||
hubInstallXva: 'Install',
|
||||
hubSuccessfulInstallMsg: 'VM installed successfuly',
|
||||
hubVmNoAvailableMsg: 'No VMs available ',
|
||||
hubNoDefaultSrMessage: "There's no default SR for {pool} pool",
|
||||
hubCreateXva: 'Create',
|
||||
hubDeployXva: 'Deploy',
|
||||
hubSortBy: 'Sort by',
|
||||
|
||||
@@ -58,3 +58,7 @@ export const setHomeVmIdsSelection = createAction(
|
||||
'SET_HOME_VM_IDS_SELECTION',
|
||||
homeVmIdsSelection => homeVmIdsSelection
|
||||
)
|
||||
export const setHubInstallLoadingState = createAction(
|
||||
'SET_HUB_INSTALL_LOADING_STATE',
|
||||
hubInstallLoadingState => hubInstallLoadingState
|
||||
)
|
||||
|
||||
@@ -92,6 +92,15 @@ export default {
|
||||
homeVmIdsSelection,
|
||||
}),
|
||||
|
||||
// This state is used temporarily to keep loading state in hub
|
||||
hubInstallLoadingState: combineActionHandlers(
|
||||
{},
|
||||
{
|
||||
[actions.setHubInstallLoadingState]: (_, hubInstallLoadingState) =>
|
||||
hubInstallLoadingState,
|
||||
}
|
||||
),
|
||||
|
||||
objects: combineActionHandlers(
|
||||
{
|
||||
all: {}, // Mutable for performance!
|
||||
|
||||
@@ -345,8 +345,8 @@ export const subscribeRoles = createSubscription(
|
||||
|
||||
export const subscribeIpPools = createSubscription(() => _call('ipPool.getAll'))
|
||||
|
||||
export const subscribeResourceCatalog = ({ hub }) =>
|
||||
createSubscription(() => _call('cloud.getResourceCatalog', { hub }))
|
||||
export const subscribeResourceCatalog = ({ filters } = {}) =>
|
||||
createSubscription(() => _call('cloud.getResourceCatalog', { filters }))
|
||||
|
||||
const getNotificationCookie = () => {
|
||||
const notificationCookie = cookies.get(
|
||||
@@ -2896,8 +2896,8 @@ export const fixHostNotInXosanNetwork = (xosanSr, host) =>
|
||||
|
||||
// XOSAN packs -----------------------------------------------------------------
|
||||
|
||||
export const getResourceCatalog = ({ hub } = {}) =>
|
||||
_call('cloud.getResourceCatalog', { hub: Boolean(hub) })
|
||||
export const getResourceCatalog = ({ filters } = {}) =>
|
||||
_call('cloud.getResourceCatalog', { filters })
|
||||
|
||||
export const getAllResourceCatalog = () => _call('cloud.getAllResourceCatalog')
|
||||
|
||||
@@ -2909,7 +2909,7 @@ const downloadAndInstallXosanPack = (pack, pool, { version }) =>
|
||||
})
|
||||
|
||||
export const downloadAndInstallResource = ({ namespace, id, version, sr }) =>
|
||||
_call('resource.downloadAndInstallResource', {
|
||||
_call('hub.downloadAndInstallResource', {
|
||||
namespace,
|
||||
id,
|
||||
version,
|
||||
|
||||
@@ -6,7 +6,7 @@ import React from 'react'
|
||||
import { Container, Col, Row } from 'grid'
|
||||
import { addSubscriptions } from 'utils'
|
||||
import { injectState, provideState } from 'reaclette'
|
||||
import { map, mapValues, orderBy } from 'lodash'
|
||||
import { isEmpty, map, mapValues, orderBy } from 'lodash'
|
||||
import { subscribeResourceCatalog } from 'xo'
|
||||
|
||||
import Resource from './resource'
|
||||
@@ -29,7 +29,7 @@ const HEADER = (
|
||||
|
||||
export default decorate([
|
||||
addSubscriptions({
|
||||
catalog: subscribeResourceCatalog({ hub: true }),
|
||||
catalog: subscribeResourceCatalog({ filters: { hub: true } }),
|
||||
}),
|
||||
provideState({
|
||||
initialState: () => ({
|
||||
@@ -52,18 +52,24 @@ export default decorate([
|
||||
}),
|
||||
injectState,
|
||||
({ state: { resources } }) => (
|
||||
<Page
|
||||
header={HEADER}
|
||||
title='hubPage'
|
||||
formatTitle
|
||||
className='background-page'
|
||||
>
|
||||
<Page header={HEADER} title='hubPage' formatTitle>
|
||||
<Row>
|
||||
{map(resources, (info, namespace) => (
|
||||
<Col key={namespace} mediumSize={3}>
|
||||
<Resource className='card-style' namespace={namespace} {...info} />
|
||||
</Col>
|
||||
))}
|
||||
{isEmpty(resources) ? (
|
||||
<h2 className='text-muted'>
|
||||
{_('hubVmNoAvailableMsg')}
|
||||
<Icon icon='alarm' color='yellow' />
|
||||
</h2>
|
||||
) : (
|
||||
map(resources, (info, namespace) => (
|
||||
<Col key={namespace} mediumSize={3}>
|
||||
<Resource
|
||||
className='card-style'
|
||||
namespace={namespace}
|
||||
{...info}
|
||||
/>
|
||||
</Col>
|
||||
))
|
||||
)}
|
||||
</Row>
|
||||
</Page>
|
||||
),
|
||||
|
||||
@@ -5,6 +5,7 @@ import Icon from 'icon'
|
||||
import React from 'react'
|
||||
import Tooltip from 'tooltip'
|
||||
import { Container } from 'grid'
|
||||
import { error } from 'notification'
|
||||
import { SelectPool } from 'select-objects'
|
||||
import { injectState, provideState } from 'reaclette'
|
||||
|
||||
@@ -14,13 +15,26 @@ export default decorate([
|
||||
pools: multi ? [] : undefined,
|
||||
}),
|
||||
effects: {
|
||||
handlePools(_, pools) {
|
||||
this.props.onChange({
|
||||
pools,
|
||||
pool: pools,
|
||||
})
|
||||
return {
|
||||
pools,
|
||||
handlePools(__, pools) {
|
||||
let noDefaultSrPool
|
||||
for (const pool of pools) {
|
||||
if (pool.default_SR === undefined) {
|
||||
noDefaultSrPool = pool
|
||||
}
|
||||
}
|
||||
if (noDefaultSrPool) {
|
||||
error(
|
||||
'Error',
|
||||
_('hubNoDefaultSrMessage', { pool: noDefaultSrPool.name_label })
|
||||
)
|
||||
} else {
|
||||
this.props.onChange({
|
||||
pools,
|
||||
pool: pools,
|
||||
})
|
||||
return {
|
||||
pools,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -36,6 +36,7 @@ export default decorate([
|
||||
return {
|
||||
templates: getTemplates,
|
||||
pools: getPools,
|
||||
hubInstallLoadingState: state => state.hubInstallLoadingState,
|
||||
}
|
||||
}),
|
||||
provideState({
|
||||
@@ -46,7 +47,12 @@ export default decorate([
|
||||
effects: {
|
||||
initialize: () => {},
|
||||
async install(__, { name, namespace, id, version }) {
|
||||
const { isFromSources, installPoolPredicate } = this.state
|
||||
const { setHubInstallLoadingState } = this.props
|
||||
const {
|
||||
isFromSources,
|
||||
hubInstallLoadingState,
|
||||
installPoolPredicate,
|
||||
} = this.state
|
||||
if (isFromSources) {
|
||||
subscribeAlert()
|
||||
} else {
|
||||
@@ -70,7 +76,10 @@ export default decorate([
|
||||
},
|
||||
})
|
||||
|
||||
this.state.loading = true
|
||||
setHubInstallLoadingState({
|
||||
...hubInstallLoadingState,
|
||||
[id]: true,
|
||||
})
|
||||
for (const pool of resourceParams.pools) {
|
||||
try {
|
||||
await downloadAndInstallResource({
|
||||
@@ -79,12 +88,15 @@ export default decorate([
|
||||
version,
|
||||
sr: pool.default_SR,
|
||||
})
|
||||
success('XVA import', 'XVA installed successfuly')
|
||||
success('XVA import', _('hubSuccessfulInstallMsg'))
|
||||
} catch (_error) {
|
||||
error('Error', _error.message)
|
||||
}
|
||||
}
|
||||
this.state.loading = false
|
||||
setHubInstallLoadingState({
|
||||
...hubInstallLoadingState,
|
||||
[id]: false,
|
||||
})
|
||||
}
|
||||
},
|
||||
async create(__, { name }) {
|
||||
@@ -160,6 +172,8 @@ export default decorate([
|
||||
poolName: ({ pool }) => pool && pool.name_label,
|
||||
installedTemplates: (_, { id, templates }) =>
|
||||
filter(templates, ['other.xva_id', id]),
|
||||
installLoadingState: (_, { hubInstallLoadingState, id }) =>
|
||||
hubInstallLoadingState[id],
|
||||
isTemplateInstalledOnAllPools: ({ installedTemplates }, { pools }) => {
|
||||
let _isTemplateInstalledOnAllPools = true
|
||||
if (isEmpty(installedTemplates)) {
|
||||
@@ -251,6 +265,7 @@ export default decorate([
|
||||
handler={effects.install}
|
||||
icon={'add'}
|
||||
size='meduim'
|
||||
pending={state.installLoadingState}
|
||||
>
|
||||
{_('hubInstallXva')}
|
||||
</ActionButton>
|
||||
|
||||
Reference in New Issue
Block a user