-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce Storage Connections management dialog
Storage Connections management dialog is opened by clicking the Connections button in the Storage Domains table when iSCSI Storage Domain is selected. The dialog displays storage connections, attached to the domain, and also has a switch to show all the iSCSI connections. It allows 5 actions to be performed on the connections: 1. Add new connection 2. Edit connection 3. Remove connection 4. Attach connection to the domain 5. Detach connection from the domain Which provides UI for the existing storage connections API Live changes are not supported, thus the domain should be in maintenance mode to perform actions (4),(5), and also (2),(3) for attached connections.
- Loading branch information
Showing
10 changed files
with
917 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import React from 'react' | ||
import { renderComponent } from '_/utils/react-modals' | ||
|
||
import StorageConnectionsModal from '_/modals/storage-connections/StorageConnectionsModal' | ||
import StorageConnectionsDataProvider from '_/modals/storage-connections/StorageConnectionsDataProvider' | ||
|
||
export function showStorageConnectionsModal (storageDomain) { | ||
renderComponent( | ||
({ unmountComponent }) => ( | ||
<StorageConnectionsDataProvider storageDomain={storageDomain}> | ||
<StorageConnectionsModal | ||
onClose={unmountComponent} | ||
/> | ||
</StorageConnectionsDataProvider> | ||
) | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
src/modals/storage-connections/StorageConnectionsDataProvider.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import React from 'react' | ||
import PropTypes from 'prop-types' | ||
import getPluginApi from '_/plugin-api' | ||
import { engineGet, enginePost, enginePut, engineDelete } from '_/utils/fetch' | ||
import DataProvider from '_/components/helper/DataProvider' | ||
import { webadminToastTypes } from '_/constants' | ||
import { msg } from '_/intl-messages' | ||
|
||
const createConnection = async (connection) => { | ||
return await enginePost( | ||
'api/storageconnections', | ||
JSON.stringify(connection) | ||
) | ||
} | ||
|
||
const editConnection = async (connection, connectionId) => { | ||
return await enginePut( | ||
`api/storageconnections/${connectionId}`, | ||
JSON.stringify(connection) | ||
) | ||
} | ||
|
||
const deleteConnection = async (connectionId) => { | ||
return await engineDelete(`api/storageconnections/${connectionId}`) | ||
} | ||
|
||
const attachConnection = async (connectionId, domainId) => { | ||
return await enginePost( | ||
`api/storagedomains/${domainId}/storageconnections`, | ||
JSON.stringify({ id: connectionId }) | ||
) | ||
} | ||
|
||
const detachConnection = async (connectionId, domainId) => { | ||
return await engineDelete(`api/storagedomains/${domainId}/storageconnections/${connectionId}`) | ||
} | ||
|
||
const fetchData = async (stgDomain) => { | ||
if (!stgDomain?.id || !stgDomain?.dataCenterId) { | ||
throw new Error('StorageConnectionsDataProvider: invalid Storage Domain') | ||
} | ||
const [allConnectionsJson, storageDomain, domainConnectionsJson] = await Promise.all([ | ||
engineGet('api/storageconnections'), | ||
engineGet(`api/datacenters/${stgDomain.dataCenterId}/storagedomains/${stgDomain.id}`), | ||
engineGet(`api/storagedomains/${stgDomain.id}/storageconnections`), | ||
]) | ||
|
||
if (!storageDomain) { | ||
throw new Error('StorageConnectionsDataProvider: failed to fetch storage domain') | ||
} | ||
|
||
const allConnections = allConnectionsJson?.storage_connection | ||
const domainConnections = domainConnectionsJson?.storage_connection | ||
|
||
if (!allConnections || allConnections.error) { | ||
throw new Error('StorageConnectionsDataProvider: failed to fetch storage connections') | ||
} | ||
|
||
if (!domainConnections || domainConnections.error) { | ||
throw new Error('StorageConnectionsDataProvider: failed to fetch storage connections' + | ||
'for storage domain ' + stgDomain.id) | ||
} | ||
|
||
const domainConnectionsIds = new Set(domainConnections.map(connection => connection.id)) | ||
const allConnectionsByTypeSorted = allConnections | ||
.filter(connection => connection.type === storageDomain.storage?.type) | ||
.map((conn) => { | ||
return { ...conn, isAttachedToDomain: domainConnectionsIds.has(conn.id) } | ||
}) | ||
.sort((conn1, conn2) => { | ||
return (conn1.isAttachedToDomain === conn2.isAttachedToDomain) ? 0 : conn1.isAttachedToDomain ? -1 : 1 | ||
}) | ||
|
||
return { | ||
storageDomain: storageDomain, | ||
connections: allConnectionsByTypeSorted, | ||
} | ||
} | ||
|
||
const StorageConnectionsDataProvider = ({ children, storageDomain }) => ( | ||
<DataProvider fetchData={() => fetchData(storageDomain)}> | ||
{({ data, fetchError, lastUpdated, fetchAndUpdateData }) => { | ||
// expecting single child component | ||
const child = React.Children.only(children) | ||
|
||
// handle data loading and error scenarios | ||
if (fetchError) { | ||
getPluginApi().showToast(webadminToastTypes.danger, msg.storageConnectionsDataError()) | ||
return null | ||
} | ||
|
||
if (!data) { | ||
return React.cloneElement(child, { isLoading: true }) | ||
} | ||
|
||
const { storageDomain, connections } = data | ||
|
||
return React.cloneElement(child, { | ||
storageDomain, | ||
connections, | ||
lastUpdated, | ||
doConnectionCreate: createConnection, | ||
doConnectionEdit: editConnection, | ||
doConnectionDelete: deleteConnection, | ||
doConnectionAttach: attachConnection, | ||
doConnectionDetach: detachConnection, | ||
doRefreshConnections: () => { fetchAndUpdateData() }, | ||
}) | ||
}} | ||
</DataProvider> | ||
) | ||
|
||
StorageConnectionsDataProvider.propTypes = { | ||
children: PropTypes.element.isRequired, | ||
storageDomain: PropTypes.object.isRequired, | ||
} | ||
|
||
export default StorageConnectionsDataProvider |
Oops, something went wrong.