diff --git a/jest.config.ts b/jest.config.ts index 9adf0b6d..ee7b1c48 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -22,7 +22,6 @@ export default { // An array of glob patterns indicating a set of files for which coverage information should be collected collectCoverageFrom: [ "**/*.tsx", // Include all .tsx files - "!**/AssessmentModule/**", // Exclude files within the AssessmentModule directory (this is a module that is not used in the app) "!**/story.tsx", // Exclude all storybook files "!**/test.tsx", // Exclude old test files "!**/plugins/**", // Exclude files within the plugins directory diff --git a/src/@types/Assessment.ts b/src/@types/Assessment.ts deleted file mode 100644 index ea13eaa8..00000000 --- a/src/@types/Assessment.ts +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import type { Endpoint } from "./Endpoint"; -import type { Instance } from "./Instance"; -import type { NetworkMap } from "./Network"; - -export type VmSize = { - name: string; - size?: string; -}; - -export type AzureLocation = { - id: string; - name: string; -}; - -export type Group = { - id: string; - name: string; -}; - -export type VmItem = { - id: string; - properties: { - recommendedSize: string; - disks: { - [diskName: string]: { - recommendedDiskType: string; - }; - }; - datacenterManagementServerName: string; - datacenterMachineArmId: string; - displayName: string; - operatingSystemName: string; - }; -}; - -export type Assessment = { - name: string; - id: string; - projectName: string; - resourceGroupName: string; - groupName: string; - assessmentName: string; - location: string; - project: { - name: string; - }; - group: Group; - properties: { - status: string; - updatedTimestamp: string; - azureLocation: string; - numberOfMachines: string; - }; - connectionInfo: { subscription_id: string } & Endpoint["connection_info"]; -}; - -export type MigrationInfo = { - source: Endpoint | null; - target: Endpoint; - selectedInstances: Instance[]; - fieldValues: { [fieldValue: string]: any }; - networks: NetworkMap[]; - vmSizes: { [vmSize: string]: VmSize }; -}; diff --git a/src/components/App.tsx b/src/components/App.tsx index 3f60eb92..29e73f96 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -29,8 +29,6 @@ import DeploymentDetailsPage from "@src/components/smart/DeploymentDetailsPage"; import MetalHubServersPage from "@src/components/smart/MetalHubServersPage"; import EndpointsPage from "@src/components/smart/EndpointsPage"; import EndpointDetailsPage from "@src/components/smart/EndpointDetailsPage"; -import AssessmentsPage from "@src/components/smart/AssessmentsPage"; -import AssessmentDetailsPage from "@src/components/smart/AssessmentDetailsPage"; import UsersPage from "@src/components/smart/UsersPage"; import UserDetailsPage from "@src/components/smart/UserDetailsPage"; import ProjectsPage from "@src/components/smart/ProjectsPage"; @@ -225,15 +223,6 @@ class App extends React.Component, State> { {renderRoute("/bare-metal-servers", MetalHubServersPage, true)} {renderRoute("/bare-metal-servers/:id", MetalHubServerDetailsPage)} {renderRoute("/wizard/:type", WizardPage)} - {renderOptionalRoute({ - name: "planning", - component: AssessmentsPage, - })} - {renderOptionalRoute({ - name: "planning", - component: AssessmentDetailsPage, - path: "/assessment/:info", - })} {renderOptionalRoute({ name: "users", component: UsersPage, diff --git a/src/components/modules/AssessmentModule/AssessedVmListItem/AssessedVmListItem.tsx b/src/components/modules/AssessmentModule/AssessedVmListItem/AssessedVmListItem.tsx deleted file mode 100644 index 1354efe5..00000000 --- a/src/components/modules/AssessmentModule/AssessedVmListItem/AssessedVmListItem.tsx +++ /dev/null @@ -1,149 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import React from "react"; -import { observer } from "mobx-react"; -import styled, { css } from "styled-components"; - -import Checkbox from "@src/components/ui/Checkbox"; -import InfoIcon from "@src/components/ui/InfoIcon"; -import DropdownLink from "@src/components/ui/Dropdowns/DropdownLink"; -import type { VmItem } from "@src/@types/Assessment"; -import { ThemePalette } from "@src/components/Theme"; - -const Wrapper = styled.div` - position: relative; - width: 100%; -`; -const Content = styled.div` - display: flex; - margin-left: -32px; - - & > div { - margin-left: 32px; - } - - opacity: ${(props: any) => (props.disabled ? 0.6 : 1)}; -`; -const columnWidth = (width: string) => css` - width: 100%; - max-width: ${width}; -`; -const DisplayName = styled.div` - display: flex; - ${(props: any) => columnWidth(props.width)} -`; -const Value = styled.div` - color: ${ThemePalette.grayscale[4]}; - ${(props: any) => columnWidth(props.width)} -`; -const DisplayNameLabel = styled.div` - margin-left: 8px; - word-break: break-word; -`; -const InfoIconStyled = styled(InfoIcon)` - position: absolute; - left: -36px; - top: 0px; - z-index: 10000; -`; - -type Props = { - item: VmItem; - selected: boolean; - onSelectedChange: (item: VmItem, isChecked: boolean) => void; - disabled: boolean; - loadingVmSizes: boolean; - vmSizes: string[]; - onVmSizeChange: (size: string) => void; - selectedVmSize: string | null; - recommendedVmSize: string; -}; -@observer -class AssessedVmListItem extends React.Component { - renderInfoIcon() { - if (!this.props.disabled) { - return null; - } - - return ( - - ); - } - - render() { - const { disks } = this.props.item.properties; - let standardCount = 0; - let premiumCount = 0; - Object.keys(disks).forEach(diskKey => { - if (disks[diskKey].recommendedDiskType === "Standard") { - standardCount += 1; - } - if (disks[diskKey].recommendedDiskType === "Premium") { - premiumCount += 1; - } - }); - - return ( - - {this.renderInfoIcon()} - - - { - this.props.onSelectedChange(this.props.item, checked); - }} - disabled={this.props.disabled} - /> - {`${this.props.item.properties.displayName}`} - - - {this.props.item.properties.operatingSystemName} - - - {standardCount} Standard, {premiumCount} Premium - - - ({ value: s, label: s })) - } - selectedItem={this.props.selectedVmSize || ""} - listWidth="200px" - onChange={item => { - this.props.onVmSizeChange(item.value); - }} - disabled={this.props.disabled} - highlightedItem={this.props.recommendedVmSize} - /> - - - - ); - } -} - -export default AssessedVmListItem; diff --git a/src/components/modules/AssessmentModule/AssessedVmListItem/package.json b/src/components/modules/AssessmentModule/AssessedVmListItem/package.json deleted file mode 100644 index 96e6715f..00000000 --- a/src/components/modules/AssessmentModule/AssessedVmListItem/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "AssessedVmListItem", - "version": "0.0.0", - "private": true, - "main": "./AssessedVmListItem.tsx" -} diff --git a/src/components/modules/AssessmentModule/AssessmentDetailsContent/AssessmentDetailsContent.tsx b/src/components/modules/AssessmentModule/AssessmentDetailsContent/AssessmentDetailsContent.tsx deleted file mode 100644 index 3dfde0a3..00000000 --- a/src/components/modules/AssessmentModule/AssessmentDetailsContent/AssessmentDetailsContent.tsx +++ /dev/null @@ -1,618 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import { observer } from "mobx-react"; -import React from "react"; -import styled, { css } from "styled-components"; - -import AssessedVmListItem from "@src/components/modules/AssessmentModule/AssessedVmListItem"; -import DetailsNavigation from "@src/components/modules/NavigationModule/DetailsNavigation"; -import { ThemePalette, ThemeProps } from "@src/components/Theme"; -import Button from "@src/components/ui/Button"; -import Checkbox from "@src/components/ui/Checkbox"; -import DropdownFilter from "@src/components/ui/Dropdowns/DropdownFilter"; -import DropdownLink from "@src/components/ui/Dropdowns/DropdownLink"; -import SmallLoading from "@src/components/ui/SmallLoading"; -import StatusImage from "@src/components/ui/StatusComponents/StatusImage"; -import Table from "@src/components/ui/Table"; -import DateUtils from "@src/utils/DateUtils"; - -import arrowImage from "./images/arrow.svg"; -import azureMigrateImage from "./images/logo.svg"; - -import type { Assessment, VmItem, AzureLocation } from "@src/@types/Assessment"; -import type { Endpoint } from "@src/@types/Endpoint"; -import type { Instance, Nic } from "@src/@types/Instance"; -import type { Network, NetworkMap } from "@src/@types/Network"; -const Wrapper = styled.div` - display: flex; - justify-content: center; -`; -const Buttons = styled.div` - margin-top: 46px; - display: flex; - flex-direction: column; - - button:first-child { - margin-bottom: 16px; - } -`; -const DetailsBody = styled.div` - ${ThemeProps.exactWidth(ThemeProps.contentWidth)} - margin-bottom: 32px; -`; -const Columns = styled.div` - display: flex; - margin-left: -32px; -`; -const Column = styled.div` - width: 50%; - margin-left: 32px; -`; -const Row = styled.div` - margin-bottom: 32px; -`; -const Field = styled.div` - display: flex; - flex-direction: column; -`; -const Label = styled.div` - font-size: 10px; - color: ${ThemePalette.grayscale[3]}; - font-weight: ${ThemeProps.fontWeights.medium}; - text-transform: uppercase; -`; -const Value = styled.div` - display: ${props => (props.flex ? "flex" : "inline-table")}; - margin-top: 3px; - ${props => (props.capitalize ? "text-transform: capitalize;" : "")} -`; -const AzureMigrateLogo = styled.div` - width: 208px; - height: 32px; - background: url("${azureMigrateImage}") center no-repeat; -`; -const LoadingWrapper = styled.div` - display: flex; - flex-direction: column; - align-items: center; - margin: 32px 0; -`; -const LoadingText = styled.div` - font-size: 18px; - margin-top: 32px; -`; -const SmallLoadingWrapper = styled.div` - display: flex; - align-items: center; - justify-content: center; -`; -const SmallLoadingText = styled.div` - font-size: 14px; - margin-left: 16px; -`; -const TableStyled = styled(Table)` - margin-top: 62px; - ${props => - props.addWidthPadding - ? css` - margin-left: -24px; - &:after { - margin-left: 24px; - } - ` - : ""} -`; -const TableHeaderStyle = css` - margin-left: 24px; -`; -const TableBodyStyle = css` - padding-left: 24px; -`; -const NetworkItem = styled.div` - display: flex; - width: 100%; -`; -const column = () => css` - padding-right: 32px; - width: 100%; - max-width: 25%; -`; -const NetworkName = styled.div` - ${column()} -`; -const Arrow = styled.div` - width: 32px; - height: 16px; - position: absolute; - right: 0; - background: url("${arrowImage}") no-repeat; - background-position-y: center; -`; -const ColumnStub = styled.div` - ${column()} - position: relative; - &:last-child { - padding-right: 0; - } -`; -const VmHeaderItem = styled.div` - display: flex; - font-size: 14px; -`; -const VmHeaderItemLabel = styled.div` - font-size: 10px; - margin-left: 8px; -`; - -const NavigationItems = [ - { - label: "Details", - value: "", - }, -]; - -type Props = { - item: Assessment | null; - detailsLoading: boolean; - instancesDetailsLoading: boolean; - instancesLoading: boolean; - networksLoading: boolean; - instancesDetailsProgress: number | null; - targetEndpoint: Endpoint; - targetEndpoints: Endpoint[]; - onTargetEndpointChange: (endpoint: Endpoint) => void; - targetEndpointsLoading: boolean; - sourceEndpoints: Endpoint[]; - sourceEndpoint: Endpoint | null; - sourceEndpointsLoading: boolean; - locations: AzureLocation[]; - selectedLocation: string | null; - onLocationChange: (locationName: string) => void; - selectedResourceGroup: string; - resourceGroups: string[]; - onResourceGroupChange: (resourceGroupName: string) => void; - targetOptionsLoading: boolean; - assessedVmsCount: number; - filteredAssessedVms: VmItem[]; - selectedVms: string[]; - instancesDetails: Instance[]; - instances: Instance[]; - loadingVmSizes: boolean; - vmSizes: string[]; - onVmSizeChange: (vmId: string, size: string) => void; - onGetSelectedVmSize: (vm: VmItem) => string | null; - networks: Network[]; - page: string; - onSourceEndpointChange: (endpoint: Endpoint) => void; - onVmSearchValueChange: (value: string) => void; - vmSearchValue: string; - onVmSelectedChange: (vm: VmItem, selected: boolean) => void; - onNetworkChange: (sourceNic: Nic, targetNetwork: Network) => void; - onRefresh: () => void; - onMigrateClick: () => void; - selectedNetworks: NetworkMap[]; - selectAllVmsChecked: boolean; - onSelectAllVmsChange: (selected: boolean) => void; -}; -@observer -class AssessmentDetailsContent extends React.Component { - static defaultProps = { - page: "", - }; - - doesVmMatchSource(vm: VmItem) { - if ( - !this.props.sourceEndpoint || - !this.props.sourceEndpoint.connection_info - ) { - return false; - } - - if ( - this.props.instances.length > 0 && - !this.props.instances.find( - i => - i.name === vm.properties.displayName || - i.instance_name === vm.properties.displayName - ) - ) { - return false; - } - - return ( - this.props.sourceEndpoint.connection_info.host === - vm.properties.datacenterManagementServerName - ); - } - - renderMainDetails() { - if (this.props.page !== "" || !this.props.item || !this.props.item.id) { - return null; - } - - const status = this.props.item - ? this.props.item.properties.status === "Completed" - ? "Ready for Migration" - : this.props.item.properties.status - : ""; - - const locationItem: AzureLocation | undefined = this.props.locations.find( - l => l.id === this.props.selectedLocation - ); - - return ( - - - - - - - - - - {this.props.item - ? DateUtils.getLocalDate( - this.props.item.properties.updatedTimestamp - ).toFormat("yyyy-LL-dd HH:mm:ss") - : "-"} - - - - - - - - {this.props.item ? this.props.item.projectName : ""} - - - - - - - {this.props.item ? this.props.item.groupName : ""} - - - - - - {status} - - - - - - - - - ({ - label: endpoint.name, - value: endpoint.id, - endpoint, - }))} - onChange={item => { - this.props.onSourceEndpointChange(item.endpoint); - }} - selectItemLabel="Select Endpoint" - noItemsLabel={ - this.props.sourceEndpointsLoading - ? "Loading ...." - : "No matching endpoints" - } - /> - - - - - - - - ({ - label: endpoint.name, - value: endpoint.id, - endpoint, - }))} - onChange={item => { - this.props.onTargetEndpointChange(item.endpoint); - }} - selectItemLabel="Select Endpoint" - noItemsLabel={ - this.props.targetEndpointsLoading - ? "Loading ...." - : "No Azure endpoints" - } - /> - - - - - - - - ({ - label: group, - value: group, - }))} - onChange={item => { - this.props.onResourceGroupChange(item.value); - }} - noItemsLabel={ - this.props.targetOptionsLoading - ? "Loading ...." - : "No Resource Groups found" - } - /> - - - - - - - - ({ - label: location.name, - value: location.id, - }))} - onChange={item => { - this.props.onLocationChange(item.value); - }} - noItemsLabel={ - this.props.targetOptionsLoading - ? "Loading ...." - : "No Locations found" - } - /> - - - - - - ); - } - - renderVmsTable() { - const loading = this.props.instancesLoading; - - const items = this.props.filteredAssessedVms.map(vm => ( - m === vm.properties.displayName) - .length > 0 - } - onSelectedChange={(selectedVm, selected) => { - this.props.onVmSelectedChange(selectedVm, selected); - }} - disabled={!this.doesVmMatchSource(vm)} - loadingVmSizes={this.props.loadingVmSizes} - recommendedVmSize={vm.properties.recommendedSize} - vmSizes={this.props.vmSizes} - selectedVmSize={this.props.onGetSelectedVmSize(vm)} - onVmSizeChange={size => { - this.props.onVmSizeChange(vm.properties.displayName, size); - }} - /> - )); - - const vmCountLabel = `(${ - this.props.filteredAssessedVms.length === this.props.assessedVmsCount - ? this.props.assessedVmsCount - : `${this.props.filteredAssessedVms.length} OUT OF ${this.props.assessedVmsCount}` - })`; - const vmHeaderItem = ( - - {loading ? null : ( - { - this.props.onSelectAllVmsChange(checked); - }} - /> - )} - Virtual Machine {vmCountLabel} - { - this.props.onVmSearchValueChange(value); - }} - /> - - ); - - return ( - - ); - } - - renderNetworkTable() { - const loading = - this.props.networksLoading || this.props.instancesDetailsLoading; - - if (loading) { - return ( - - ); - } - - const nics: Nic[] = []; - this.props.instancesDetails.forEach(instance => { - if (!instance.devices || !instance.devices.nics) { - return; - } - instance.devices.nics.forEach(nic => { - if (nics.find(n => n.network_name === nic.network_name)) { - return; - } - nics.push(nic); - }); - }); - - if (nics.length === 0) { - return null; - } - - const items = nics.map(nic => { - let selectedNetworkName: string | undefined; - const selectedNetwork = - this.props.selectedNetworks && - this.props.selectedNetworks.find( - n => n.sourceNic.network_name === nic.network_name - ); - if (selectedNetwork) { - selectedNetworkName = selectedNetwork.targetNetwork?.name; - } - - return ( - - {nic.network_name} - - - - - - { - this.props.onNetworkChange(nic, item.network); - }} - items={this.props.networks.map(network => ({ - value: network.name || "", - label: network.name || "", - network, - }))} - /> - - - ); - }); - return ( - - ); - } - - renderNetworksLoading() { - let loadingProgress = -1; - if (this.props.instancesDetailsLoading) { - if (this.props.instancesDetailsProgress != null) { - loadingProgress = Math.round(this.props.instancesDetailsProgress * 100); - } - } - - return ( - - - Loading networks, please wait ... - - ); - } - - renderButtons() { - return ( - - - - - ); - } - - renderLoading(message: string) { - return ( - - - {message} - - ); - } - - render() { - return ( - - "#"} - /> - - {this.props.detailsLoading ? null : this.renderMainDetails()} - {this.props.detailsLoading - ? this.renderLoading("Loading assessment...") - : null} - {this.props.detailsLoading ? null : this.renderVmsTable()} - {this.props.detailsLoading || this.props.instancesLoading - ? null - : this.renderNetworkTable()} - {this.props.detailsLoading ? null : this.renderButtons()} - - - ); - } -} - -export default AssessmentDetailsContent; diff --git a/src/components/modules/AssessmentModule/AssessmentDetailsContent/images/arrow.svg b/src/components/modules/AssessmentModule/AssessmentDetailsContent/images/arrow.svg deleted file mode 100644 index 57678840..00000000 --- a/src/components/modules/AssessmentModule/AssessmentDetailsContent/images/arrow.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Created with Sketch. - - - - - - - - diff --git a/src/components/modules/AssessmentModule/AssessmentDetailsContent/images/logo.svg b/src/components/modules/AssessmentModule/AssessmentDetailsContent/images/logo.svg deleted file mode 100644 index 893ff1b9..00000000 --- a/src/components/modules/AssessmentModule/AssessmentDetailsContent/images/logo.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Created with Sketch. - - - diff --git a/src/components/modules/AssessmentModule/AssessmentDetailsContent/package.json b/src/components/modules/AssessmentModule/AssessmentDetailsContent/package.json deleted file mode 100644 index 73c83330..00000000 --- a/src/components/modules/AssessmentModule/AssessmentDetailsContent/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "AssessmentDetailsContent", - "version": "0.0.0", - "private": true, - "main": "./AssessmentDetailsContent.tsx" -} diff --git a/src/components/modules/AssessmentModule/AssessmentListItem/AssessmentListItem.tsx b/src/components/modules/AssessmentModule/AssessmentListItem/AssessmentListItem.tsx deleted file mode 100644 index 2584a4f5..00000000 --- a/src/components/modules/AssessmentModule/AssessmentListItem/AssessmentListItem.tsx +++ /dev/null @@ -1,142 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import React from "react"; -import { observer } from "mobx-react"; -import styled from "styled-components"; - -import StatusPill from "@src/components/ui/StatusComponents/StatusPill"; - -import type { Assessment } from "@src/@types/Assessment"; - -import { ThemePalette, ThemeProps } from "@src/components/Theme"; -import assessmentImage from "./images/assessment.svg"; -import azureMigrateImage from "./images/azure-migrate.svg"; - -const Content = styled.div` - display: flex; - align-items: center; - border-top: 1px solid ${ThemePalette.grayscale[1]}; - padding: 8px 16px; - cursor: pointer; - flex-grow: 1; - transition: all ${ThemeProps.animations.swift}; - min-width: 785px; - - &:hover { - background: ${ThemePalette.grayscale[1]}; - } -`; -const Wrapper = styled.div` - display: flex; - align-items: center; - - &:last-child ${Content} { - border-bottom: 1px solid ${ThemePalette.grayscale[1]}; - } -`; -const Image = styled.div` - min-width: 48px; - height: 48px; - background: url("${(props: any) => props.image}") no-repeat center; - margin-right: 16px; -`; -const Title = styled.div` - flex-grow: 1; - overflow: hidden; - margin-right: 48px; - min-width: 100px; -`; -const TitleLabel = styled.div` - font-size: 16px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -`; -const AssessmentType = styled.div` - display: flex; - justify-content: center; - align-items: center; - margin-right: 46px; - ${ThemeProps.exactWidth("180px")} -`; -const AssessmentImage = styled.div` - width: 48px; - height: 32px; - background: url("${azureMigrateImage}") center no-repeat; - margin-right: 12px; -`; -const AssessmentLabel = styled.div` - font-size: 15px; - color: ${ThemePalette.grayscale[4]}; - width: 64px; -`; -const TotalVms = styled.div` - ${ThemeProps.exactWidth("96px")} - margin-right: 48px; -`; -const Project = styled.div` - ${ThemeProps.exactWidth("175px")} - margin-right: 48px; -`; -const ItemLabel = styled.div` - color: ${ThemePalette.grayscale[4]}; -`; -const ItemValue = styled.div` - color: ${ThemePalette.primary}; -`; - -type Props = { - item: Assessment; - onClick: () => void; -}; -@observer -class AssessmentListItem extends React.Component { - render() { - let status = this.props.item.properties.status.toUpperCase(); - let label = status; - if (status === "CREATED" || status === "RUNNING") { - status = "RUNNING"; - label = "CREATING"; - } else if (status === "COMPLETED") { - label = "READY"; - } - - return ( - - - - - <TitleLabel>{this.props.item.name}</TitleLabel> - <StatusPill status={status} label={label} /> - - - - Azure Migrate - - - Project - {this.props.item.project.name} - - - Instances - {this.props.item.properties.numberOfMachines} - - - - ); - } -} - -export default AssessmentListItem; diff --git a/src/components/modules/AssessmentModule/AssessmentListItem/images/assessment.svg b/src/components/modules/AssessmentModule/AssessmentListItem/images/assessment.svg deleted file mode 100644 index 96f44f1d..00000000 --- a/src/components/modules/AssessmentModule/AssessmentListItem/images/assessment.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Created with Sketch. - - - - - - - - - - - - - - - diff --git a/src/components/modules/AssessmentModule/AssessmentListItem/images/azure-migrate.svg b/src/components/modules/AssessmentModule/AssessmentListItem/images/azure-migrate.svg deleted file mode 100644 index 5c6b717c..00000000 --- a/src/components/modules/AssessmentModule/AssessmentListItem/images/azure-migrate.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Created with Sketch. - - - - - - - - - - - - - - - diff --git a/src/components/modules/AssessmentModule/AssessmentListItem/package.json b/src/components/modules/AssessmentModule/AssessmentListItem/package.json deleted file mode 100644 index 643b8af5..00000000 --- a/src/components/modules/AssessmentModule/AssessmentListItem/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "AssessmentListItem", - "version": "0.0.0", - "private": true, - "main": "./AssessmentListItem.tsx" -} diff --git a/src/components/modules/AssessmentModule/AssessmentMigrationOptions/AssessmentMigrationOptions.tsx b/src/components/modules/AssessmentModule/AssessmentMigrationOptions/AssessmentMigrationOptions.tsx deleted file mode 100644 index 5e7da9c3..00000000 --- a/src/components/modules/AssessmentModule/AssessmentMigrationOptions/AssessmentMigrationOptions.tsx +++ /dev/null @@ -1,321 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import * as React from "react"; -import { observer } from "mobx-react"; -import styled from "styled-components"; - -import Button from "@src/components/ui/Button"; -import FieldInput from "@src/components/ui/FieldInput"; -import ToggleButtonBar from "@src/components/ui/ToggleButtonBar"; - -import type { Field } from "@src/@types/Field"; - -import { ThemeProps } from "@src/components/Theme"; - -import LabelDictionary from "@src/utils/LabelDictionary"; - -import assessmentImage from "./images/assessment.svg"; - -const Wrapper = styled.div` - padding: 48px 32px 32px 32px; - display: flex; - flex-direction: column; - align-items: center; - min-height: 0; -`; -const Image = styled.div` - width: 96px; - height: 96px; - background: url("${assessmentImage}") center no-repeat; -`; -const ToggleButtonBarStyled = styled(ToggleButtonBar)` - margin-top: 48px; -`; -const Fields = styled.div` - display: flex; - margin-top: 32px; - flex-direction: column; - overflow: auto; - width: 100%; - min-height: 0; -`; -const FieldStyled = styled(FieldInput)` - ${ThemeProps.exactWidth(`${ThemeProps.inputSizes.large.width}px`)} - margin-bottom: 16px; -`; -const Row = styled.div` - display: flex; - flex-shrink: 0; - justify-content: space-between; -`; - -const Buttons = styled.div` - display: flex; - justify-content: space-between; - width: 100%; - margin-top: 32px; -`; - -const generalFields = [ - { - name: "use_replica", - type: "boolean", - }, - { - name: "separate_vm", - type: "boolean", - }, -]; -const replicaFields = [ - { - name: "shutdown_instances", - type: "boolean", - }, -]; -const migrationFields = [ - { - name: "skip_os_morphing", - type: "boolean", - }, -]; - -type Props = { - onCancelClick: () => void; - onExecuteClick: (fieldValues: { [prop: string]: any }) => void; - executeButtonDisabled: boolean; - replicaSchema: Field[]; - migrationSchema: Field[]; - onResizeUpdate?: (scrollableRef: HTMLElement, scrollOffset?: number) => void; -}; -type State = { - fieldValues: { [prop: string]: any }; - showAdvancedOptions: boolean; -}; -@observer -class AssessmentMigrationOptions extends React.Component { - state: State = { - fieldValues: { - separate_vm: true, - use_replica: false, - shutdown_instances: false, - skip_os_morphing: false, - }, - showAdvancedOptions: false, - }; - - // scrollableRef: HTMLElement | undefined | null - - getFieldValue(fieldName: string) { - if (this.state.fieldValues[fieldName] != null) { - return this.state.fieldValues[fieldName]; - } - return null; - } - - getObjectFieldValue(fieldName: string, propName: string) { - return ( - this.state.fieldValues[fieldName] && - this.state.fieldValues[fieldName][propName] - ); - } - - handleValueChange(fieldName: string, value: any) { - this.setState(prevState => { - const fieldValues = { ...prevState.fieldValues }; - if (value != null) { - fieldValues[fieldName] = value; - } else { - delete fieldValues[fieldName]; - } - return { fieldValues }; - }); - } - - // UNSAFE_componentDidUpdate(_: Props, prevState: State) { - // if (prevState.showAdvancedOptions !== this.state.showAdvancedOptions - // && this.props.onResizeUpdate && this.scrollableRef) { - // this.props.onResizeUpdate(this.scrollableRef) - // } - // } - - handleObjectValueChange(fieldName: string, propName: string, value: any) { - this.setState(prevState => { - const fieldValues = { ...prevState.fieldValues }; - if (!fieldValues[fieldName]) { - fieldValues[fieldName] = {}; - } - fieldValues[fieldName][propName] = value; - return { fieldValues }; - }); - } - - renderFields() { - let fields: any = generalFields; - const useReplica = this.getFieldValue("use_replica"); - const skipFields = [ - "location", - "resource_group", - "network_map", - "storage_map", - "vm_size", - "worker_size", - ]; - // eslint-disable-next-line no-shadow - const cleanup = (cleanupFields: any[]) => - cleanupFields - .filter((f: { name: string }) => !skipFields.find(n => n === f.name)) - .map((f: { type: string; nullableBoolean: boolean }) => { - if (f.type === "boolean") { - // eslint-disable-next-line no-param-reassign - f.nullableBoolean = true; - } - return { ...f }; - }); - - if (useReplica) { - fields = [...fields, ...replicaFields]; - if (this.state.showAdvancedOptions) { - fields = [...fields, ...cleanup(this.props.replicaSchema)]; - } - } else { - fields = [...fields, ...migrationFields]; - if (this.state.showAdvancedOptions) { - fields = [...fields, ...cleanup(this.props.migrationSchema)]; - } - } - - const sortPriority: any = { - boolean: 1, - string: 2, - object: 3, - }; - fields.sort((a: any, b: any) => { - if (sortPriority[a.type] && sortPriority[b.type]) { - return sortPriority[a.type] - sortPriority[b.type]; - } - if (sortPriority[a.type]) { - return -1; - } - if (sortPriority[b.type]) { - return 1; - } - return a.name.localeCompare(b.name); - }); - - const rows: JSX.Element[] = []; - let lastField: JSX.Element; - fields.forEach((field: any, index: number) => { - let additionalProps; - if (field.type === "object" && field.properties) { - additionalProps = { - valueCallback: (callbackField: { name: string }) => - this.getObjectFieldValue(field.name, callbackField.name), - onChange: (value: any, callbackField: { name: string }) => { - const propName = callbackField.name.substr( - callbackField.name.lastIndexOf("/") + 1 - ); - this.handleObjectValueChange(field.name, propName, value); - }, - properties: field.properties.map((p: any) => ({ - ...p, - required: false, - })), - }; - } else { - const value = this.getFieldValue(field.name); - additionalProps = { - value, - // eslint-disable-next-line no-shadow - onChange: (changeValue: any) => { - this.handleValueChange(field.name, changeValue); - }, - type: field.type, - }; - } - - const currentField = ( - - ); - const pushRow = (field1: React.ReactNode, field2?: React.ReactNode) => { - rows.push( - - {field1} - {field2} - - ); - }; - if (index === fields.length - 1 && index % 2 === 0) { - pushRow(currentField); - } else if (index % 2 !== 0) { - pushRow(lastField, currentField); - } else { - lastField = currentField; - } - }); - - return ( - // { this.scrollableRef = ref }}> - {rows} - ); - } - - render() { - return ( - - - { - this.setState({ showAdvancedOptions: item.value === "advanced" }); - }} - /> - {this.renderFields()} - - - - - - ); - } -} - -export default AssessmentMigrationOptions; diff --git a/src/components/modules/AssessmentModule/AssessmentMigrationOptions/images/assessment.svg b/src/components/modules/AssessmentModule/AssessmentMigrationOptions/images/assessment.svg deleted file mode 100644 index 20d28601..00000000 --- a/src/components/modules/AssessmentModule/AssessmentMigrationOptions/images/assessment.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - Created with Sketch. - - - - - - - - - - - - diff --git a/src/components/modules/AssessmentModule/AssessmentMigrationOptions/package.json b/src/components/modules/AssessmentModule/AssessmentMigrationOptions/package.json deleted file mode 100644 index e0811528..00000000 --- a/src/components/modules/AssessmentModule/AssessmentMigrationOptions/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "AssessmentMigrationOptions", - "version": "0.0.0", - "private": true, - "main": "./AssessmentMigrationOptions.tsx" -} diff --git a/src/components/smart/AssessmentDetailsPage/AssessmentDetailsPage.tsx b/src/components/smart/AssessmentDetailsPage/AssessmentDetailsPage.tsx deleted file mode 100644 index bd69b9e5..00000000 --- a/src/components/smart/AssessmentDetailsPage/AssessmentDetailsPage.tsx +++ /dev/null @@ -1,689 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import React from "react"; -import styled from "styled-components"; -import cookie from "js-cookie"; -import { observer } from "mobx-react"; - -import DetailsTemplate from "@src/components/modules/TemplateModule/DetailsTemplate"; -import DetailsPageHeader from "@src/components/modules/DetailsModule/DetailsPageHeader"; -import DetailsContentHeader from "@src/components/modules/DetailsModule/DetailsContentHeader"; -import AssessmentDetailsContent from "@src/components/modules/AssessmentModule/AssessmentDetailsContent"; -import Modal from "@src/components/ui/Modal"; -import AssessmentMigrationOptions from "@src/components/modules/AssessmentModule/AssessmentMigrationOptions"; -import type { Endpoint } from "@src/@types/Endpoint"; -import type { Nic } from "@src/@types/Instance"; -import type { VmItem } from "@src/@types/Assessment"; -import type { Field } from "@src/@types/Field"; -import type { Network, NetworkMap } from "@src/@types/Network"; - -import azureStore from "@src/stores/AzureStore"; -import type { LocalData } from "@src/stores/AzureStore"; -import endpointStore from "@src/stores/EndpointStore"; -import notificationStore from "@src/stores/NotificationStore"; -import replicaStore from "@src/stores/TransferStore"; -import instanceStore from "@src/stores/InstanceStore"; -import networkStore from "@src/stores/NetworkStore"; -import userStore from "@src/stores/UserStore"; -import assessmentStore from "@src/stores/AssessmentStore"; -import providerStore from "@src/stores/ProviderStore"; - -import DomUtils from "@src/utils/DomUtils"; -import assessmentImage from "./images/assessment.svg"; - -const Wrapper = styled.div``; - -type Props = { - match: any; - history: any; -}; -type State = { - selectedNetworks: NetworkMap[]; - showMigrationOptions: boolean; - executeButtonDisabled: boolean; - vmSearchValue: string; - loadingTargetVmSizes: boolean; - replicaSchema: Field[]; - migrationSchema: Field[]; -}; -@observer -class AssessmentDetailsPage extends React.Component { - state: State = { - selectedNetworks: [], - showMigrationOptions: false, - executeButtonDisabled: false, - vmSearchValue: "", - loadingTargetVmSizes: false, - replicaSchema: [], - migrationSchema: [], - }; - - UNSAFE_componentWillMount() { - document.title = "Assessment Details"; - const urlData: LocalData = DomUtils.decodeFromBase64Url( - this.props.match.params.info - ); - if (!azureStore.loadLocalData(urlData.assessmentName)) { - azureStore.setLocalData(urlData); - } - this.azureAuthenticate(); - } - - componentWillUnmount() { - azureStore.clearAssessmentDetails(); - azureStore.clearAssessedVms(); - instanceStore.clearInstancesDetails(); - } - - getLocalData(): LocalData { - // at this point we know for sure that at least URL data is there - const data: any = azureStore.localData; - return data; - } - - getUrlInfo() { - return DomUtils.decodeFromBase64Url(this.props.match.params.info); - } - - getSourceEndpoints() { - const vms = azureStore.assessedVms; - const connectionsInfo = endpointStore.connectionsInfo; - - if (vms.length === 0 || connectionsInfo.length === 0) { - return []; - } - const endpoints = connectionsInfo.filter(endpoint => - vms.find( - vm => - endpoint.connection_info.host && - endpoint.connection_info.host.toLowerCase() === - vm.properties.datacenterManagementServerName.toLowerCase() - ) - ); - return endpoints; - } - - getTargetEndpoints() { - const endpoints = endpointStore.endpoints; - return endpoints.filter(e => e.type === "azure"); - } - - getInstancesDetailsProgress() { - const count = instanceStore.instancesDetailsCount; - if (count < 5) { - return null; - } - const remaining = instanceStore.instancesDetailsRemaining; - return (count - remaining) / count; - } - - getFilteredAssessedVms(vms?: VmItem[]) { - let usableVms = vms; - if (!usableVms) { - usableVms = azureStore.assessedVms; - } - return usableVms.filter( - vm => - `${vm.properties.displayName}` - .toLowerCase() - .indexOf(this.state.vmSearchValue.toLowerCase()) > -1 - ); - } - - getSourceEndpointId() { - const localData = this.getLocalData(); - return localData.sourceEndpoint ? localData.sourceEndpoint.id : null; - } - - getEnabledVms() { - const sourceConnInfo = endpointStore.connectionsInfo.find( - e => e.id === this.getSourceEndpointId() - ); - if (!sourceConnInfo) { - return []; - } - - const sourceHost = sourceConnInfo.connection_info.host; - if (!sourceHost) { - return []; - } - return azureStore.assessedVms.filter(vm => { - if ( - vm.properties.datacenterManagementServerName.toLowerCase() === - sourceHost.toLowerCase() && - instanceStore.instances.find( - i => - i.name === vm.properties.displayName || - i.instance_name === vm.properties.displayName - ) - ) { - return true; - } - return false; - }); - } - - getSelectAllVmsChecked() { - if ( - this.getFilteredAssessedVms().length === 0 || - this.getEnabledVms().length === 0 - ) { - return false; - } - const selectedVms = this.getLocalData().selectedVms; - return ( - selectedVms.length === - this.getFilteredAssessedVms(this.getEnabledVms()).length - ); - } - - handleVmSelectedChange(vm: VmItem, selected: boolean) { - let selectedVms = this.getLocalData().selectedVms; - const instanceInfo = instanceStore.instances.find( - i => - i.name === vm.properties.displayName || - i.instance_name === vm.properties.displayName - ); - if (selected) { - selectedVms = [...selectedVms, vm.properties.displayName]; - azureStore.updateSelectedVms(selectedVms); - if (instanceStore.loadingInstancesDetails) { - this.loadInstancesDetails(); - return; - } - const sourceEndpointId = this.getSourceEndpointId(); - if (!sourceEndpointId || !instanceInfo) { - return; - } - const localData = this.getLocalData(); - instanceStore.addInstanceDetails({ - endpointId: sourceEndpointId, - instanceInfo, - cache: true, - env: { - location: localData.locationName, - resource_group: localData.resourceGroupName, - }, - targetProvider: "azure", - }); - } else { - selectedVms = selectedVms.filter(m => m !== vm.properties.displayName); - azureStore.updateSelectedVms(selectedVms); - if (instanceStore.loadingInstancesDetails) { - this.loadInstancesDetails(); - return; - } - if (instanceInfo) { - instanceStore.removeInstanceDetails(instanceInfo); - } - } - } - - handleSelectAllVmsChange(selected: boolean) { - const selectedVms = selected - ? [...this.getFilteredAssessedVms(this.getEnabledVms())] - : []; - azureStore.updateSelectedVms( - selectedVms.map(v => v.properties.displayName) - ); - this.loadInstancesDetails(); - } - - handleSourceEndpointChange(sourceEndpoint: Endpoint | null) { - this.setState({ selectedNetworks: [] }); - azureStore.updateSourceEndpoint(sourceEndpoint); - const sourceEndpointId = this.getSourceEndpointId(); - if (!sourceEndpointId) { - return; - } - instanceStore.loadInstances(sourceEndpointId).then(() => { - this.initSelectedVms(); - this.loadInstancesDetails(); - }); - } - - handleResourceGroupChange(resourceGroupName: string) { - azureStore.updateResourceGroup(resourceGroupName); - this.loadNetworks(); - this.loadTargetVmSizes(); - } - - handleLocationChange(locationName: string) { - azureStore.updateLocation(locationName); - this.loadNetworks(); - this.loadTargetVmSizes(); - } - - handleTargetEndpointChange(endpoint: Endpoint) { - azureStore.updateTargetEndpoint(endpoint); - this.loadTargetOptions().then(() => { - this.loadTargetVmSizes(); - this.loadNetworks(); - }); - } - - handleUserItemClick(item: { value: string }) { - switch (item.value) { - case "signout": - userStore.logout(); - break; - default: - } - } - - handleNetworkChange(sourceNic: Nic, targetNetwork: Network) { - this.setState(prevState => { - let selectedNetworks = prevState.selectedNetworks; - - selectedNetworks = selectedNetworks.filter( - n => n.sourceNic.network_name !== sourceNic.network_name - ); - selectedNetworks.push({ sourceNic, targetNetwork }); - return { selectedNetworks }; - }); - } - - handleRefresh() { - localStorage.removeItem("instances"); - localStorage.removeItem(`assessments-${cookie.get("projectId") || ""}`); - localStorage.removeItem("instancesDetails"); - localStorage.removeItem("networks"); - window.location.reload(); - } - - handleMigrateClick() { - const endpointType = this.getLocalData().endpoint.type; - providerStore - .loadOptionsSchema({ - providerName: endpointType, - optionsType: "destination", - }) - .then(() => { - this.setState({ replicaSchema: providerStore.destinationSchema }); - return providerStore.loadOptionsSchema({ - providerName: endpointType, - optionsType: "destination", - }); - }) - .then(() => { - this.setState({ migrationSchema: providerStore.destinationSchema }); - }); - this.setState({ showMigrationOptions: true }); - } - - handleCloseMigrationOptions() { - this.setState({ showMigrationOptions: false }); - } - - handleVmSizeChange(vmId: string, vmSize: string) { - azureStore.updateVmSize(vmId, vmSize); - } - - handleGetVmSize(vm: VmItem): string { - return this.getLocalData().selectedVmSizes[vm.properties.displayName]; - } - - handleVmSearchValueChange(vmSearchValue: string) { - this.setState({ vmSearchValue }); - } - - azureAuthenticate() { - const connectionInfo = this.getUrlInfo().connectionInfo; - azureStore.authenticate(connectionInfo).then(() => { - this.loadAssessmentDetails(); - }); - } - - loadEndpoints() { - endpointStore.getEndpoints({ showLoading: true }).then(() => { - this.loadSourceEndpointsInfo(); - }); - } - - loadSourceEndpointsInfo() { - endpointStore - .getConnectionsInfo( - endpointStore.endpoints.filter(e => e.type === "vmware_vsphere") - ) - .then(() => { - const endpoints = this.getSourceEndpoints(); - const sourceEndpoint = endpoints.find( - e => e.id === this.getSourceEndpointId() - ); - if (sourceEndpoint) { - this.handleSourceEndpointChange(sourceEndpoint); - } else if (endpoints.length > 0) { - this.handleSourceEndpointChange(endpoints[0]); - } else { - this.handleSourceEndpointChange(null); - } - }); - } - - loadAssessmentDetails() { - const urlInfo = this.getUrlInfo(); - azureStore.getAssessmentDetails({ ...urlInfo }).then(() => { - const location = azureStore.assessmentDetails - ? azureStore.assessmentDetails.properties.azureLocation - : ""; - azureStore.setLocation(location); - // azureStore.getVmSizes({ ...urlInfo, location }) - this.loadNetworks(); - this.loadTargetOptions(); - this.loadTargetVmSizes(); - }); - - azureStore.getAssessedVms({ ...urlInfo }).then(() => { - this.initVmSizes(); - this.loadEndpoints(); - }); - } - - async loadTargetOptions(): Promise { - const localData = this.getLocalData(); - const options = await providerStore.getOptionsValues({ - optionsType: "destination", - endpointId: localData.endpoint.id, - providerName: localData.endpoint.type, - allowMultiple: true, - }); - const locations = options.find(o => o.name === "location") as any; - if (locations && locations.values) { - const localDataFind = locations.values.find( - (l: { id: string }) => l.id === localData.locationName - ); - if (!localDataFind) { - azureStore.updateLocation(locations.values[0].id); - } - - azureStore.saveLocations(locations.values); - } - const resourceGroups = options.find( - o_1 => o_1.name === "resource_group" - ) as any; - if (resourceGroups && resourceGroups.values) { - const localDataFind = resourceGroups.values.find( - (g: string) => g === localData.resourceGroupName - ); - if (!localDataFind) { - azureStore.updateResourceGroup(resourceGroups.values[0] as string); - } - azureStore.saveResourceGroups(resourceGroups.values); - } - } - - loadTargetVmSizes() { - const localData = this.getLocalData(); - this.setState({ loadingTargetVmSizes: true }); - providerStore - .getOptionsValues({ - optionsType: "destination", - endpointId: localData.endpoint.id, - providerName: localData.endpoint.type, - envData: { - location: localData.locationName, - resource_group: localData.resourceGroupName, - }, - allowMultiple: true, - }) - .then(options => { - const vmSizes: any = options.find(o => o.name === "vm_size"); - if (vmSizes && vmSizes.values) { - azureStore.saveTargetVmSizes(vmSizes.values); - } - this.setState({ loadingTargetVmSizes: false }); - }); - } - - initSelectedVms() { - const localData = this.getLocalData(); - const enabledVms = this.getEnabledVms().map( - vm => vm.properties.displayName - ); - if (localData.selectedVms.length === 0) { - azureStore.updateSelectedVms(enabledVms); - } else { - azureStore.updateSelectedVms( - enabledVms.filter(id => localData.selectedVms.find(i => i === id)) - ); - } - } - - initVmSizes() { - const vmSizes: any = {}; - const vms = azureStore.assessedVms; - const localData = this.getLocalData(); - - vms.forEach(vm => { - vmSizes[vm.properties.displayName] = - localData.selectedVmSizes[vm.properties.displayName] || - vm.properties.recommendedSize || - "auto"; - }); - azureStore.updateVmSizes(vmSizes); - } - - loadNetworks() { - const localData = this.getLocalData(); - this.setState({ selectedNetworks: [] }); - networkStore.loadNetworks( - localData.endpoint.id, - { - location: localData.locationName, - resource_group: localData.resourceGroupName, - }, - { cache: true } - ); - } - - loadInstancesDetails() { - const localData = this.getLocalData(); - const selectedVms = localData.selectedVms; - const instancesInfo = instanceStore.instances.filter(i => - selectedVms.find(m => i.instance_name === m || i.name === m) - ); - instanceStore.clearInstancesDetails(); - const sourceEndpointId = this.getSourceEndpointId(); - if (!sourceEndpointId) { - return; - } - instanceStore.loadInstancesDetails({ - endpointId: sourceEndpointId, - instances: instancesInfo, - // cache: true, - skipLog: true, - env: { - location: localData.locationName, - resource_group: localData.resourceGroupName, - }, - targetProvider: "azure", - }); - } - - handleMigrationExecute(fieldValues: { [prop: string]: any }) { - const selectedVms = this.getLocalData().selectedVms; - const selectedInstances = instanceStore.instancesDetails.filter(i => - selectedVms.find(m => i.name === m || i.instance_name === m) - ); - const vmSizes: any = {}; - const localData = this.getLocalData(); - selectedInstances.forEach(i => { - const vm = selectedVms.find(m => i.name === m || i.instance_name === m); - const selectedVmSize = - localData.selectedVmSizes[i.instance_name || i.name]; - if (vm && azureStore.vmSizes.find(s => s === selectedVmSize)) { - vmSizes[i.instance_name || i.name] = selectedVmSize; - } - }); - - this.setState({ executeButtonDisabled: true }); - const fieldValuesLocal = fieldValues; - fieldValuesLocal.resource_group = localData.resourceGroupName; - fieldValuesLocal.location = localData.locationName; - - assessmentStore - .migrate({ - source: localData.sourceEndpoint, - target: localData.endpoint, - networks: [...this.state.selectedNetworks], - fieldValues: fieldValuesLocal, - vmSizes, - selectedInstances, - }) - .then(() => { - this.setState({ showMigrationOptions: false }); - const type = fieldValuesLocal.use_replica ? "Replica" : "Migration"; - notificationStore.alert(`${type} was succesfully created`, "success"); - - if (type === "Replica") { - assessmentStore.migrations.forEach(replica => { - replicaStore.execute(replica.id, [ - { - name: "shutdown_instances", - value: fieldValuesLocal.shutdown_instances || false, - }, - ]); - }); - } - - this.props.history.push(`/${type.toLowerCase()}s`); - }); - } - - render() { - const details = azureStore.assessmentDetails; - const loading = - azureStore.loadingAssessmentDetails || - azureStore.authenticating || - azureStore.loadingAssessedVms; - const endpointsLoading = - endpointStore.connectionsInfoLoading || endpointStore.loading; - const status = details ? details.properties.status.toUpperCase() : ""; - const statusLabel = status === "COMPLETED" ? "READY" : status; - const localData = this.getLocalData(); - - return ( - - { - this.handleUserItemClick(item); - }} - /> - } - contentHeaderComponent={ - - } - contentComponent={ - { - this.handleTargetEndpointChange(endpoint); - }} - sourceEndpoints={this.getSourceEndpoints()} - sourceEndpoint={localData.sourceEndpoint} - locations={azureStore.locations} - selectedLocation={localData.locationName} - onLocationChange={locationName => { - this.handleLocationChange(locationName); - }} - selectedResourceGroup={localData.resourceGroupName} - resourceGroups={azureStore.coriolisResourceGroups} - onResourceGroupChange={resourceGroupName => { - this.handleResourceGroupChange(resourceGroupName); - }} - assessedVmsCount={azureStore.assessedVms.length} - filteredAssessedVms={this.getFilteredAssessedVms()} - onSourceEndpointChange={endpoint => - this.handleSourceEndpointChange(endpoint) - } - selectedVms={localData.selectedVms} - onVmSelectedChange={(vm, selected) => { - this.handleVmSelectedChange(vm, selected); - }} - selectAllVmsChecked={this.getSelectAllVmsChecked()} - onSelectAllVmsChange={checked => { - this.handleSelectAllVmsChange(checked); - }} - instances={instanceStore.instances} - instancesDetails={instanceStore.instancesDetails} - networks={networkStore.networks} - selectedNetworks={this.state.selectedNetworks} - vmSizes={azureStore.vmSizes} - onVmSizeChange={(vmId, size) => { - this.handleVmSizeChange(vmId, size); - }} - onGetSelectedVmSize={vm => this.handleGetVmSize(vm)} - vmSearchValue={this.state.vmSearchValue} - onVmSearchValueChange={value => { - this.handleVmSearchValueChange(value); - }} - onNetworkChange={(sourceNic, targetNetwork) => { - this.handleNetworkChange(sourceNic, targetNetwork); - }} - onRefresh={() => this.handleRefresh()} - onMigrateClick={() => { - this.handleMigrateClick(); - }} - /> - } - /> - { - this.handleCloseMigrationOptions(); - }} - > - { - this.handleCloseMigrationOptions(); - }} - onExecuteClick={fieldValues => { - this.handleMigrationExecute(fieldValues); - }} - replicaSchema={this.state.replicaSchema} - migrationSchema={this.state.migrationSchema} - executeButtonDisabled={this.state.executeButtonDisabled} - /> - - - ); - } -} - -export default AssessmentDetailsPage; diff --git a/src/components/smart/AssessmentDetailsPage/images/assessment.svg b/src/components/smart/AssessmentDetailsPage/images/assessment.svg deleted file mode 100644 index bcc12bd3..00000000 --- a/src/components/smart/AssessmentDetailsPage/images/assessment.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Created with Sketch. - - - - - - - - - - - - - - - diff --git a/src/components/smart/AssessmentDetailsPage/package.json b/src/components/smart/AssessmentDetailsPage/package.json deleted file mode 100644 index 2a2d4cd4..00000000 --- a/src/components/smart/AssessmentDetailsPage/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "AssessmentDetailsPage", - "version": "0.0.0", - "private": true, - "main": "./AssessmentDetailsPage.tsx" -} diff --git a/src/components/smart/AssessmentsPage/AssessmentsPage.tsx b/src/components/smart/AssessmentsPage/AssessmentsPage.tsx deleted file mode 100644 index 754dbf6a..00000000 --- a/src/components/smart/AssessmentsPage/AssessmentsPage.tsx +++ /dev/null @@ -1,383 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import React from "react"; -import styled from "styled-components"; -import { observer } from "mobx-react"; - -import FilterList from "@src/components/ui/Lists/FilterList"; -import MainTemplate from "@src/components/modules/TemplateModule/MainTemplate"; -import PageHeader from "@src/components/smart/PageHeader"; -import Navigation from "@src/components/modules/NavigationModule/Navigation"; -import DropdownFilterGroup from "@src/components/ui/Dropdowns/DropdownFilterGroup"; -import AssessmentListItem from "@src/components/modules/AssessmentModule/AssessmentListItem"; -import type { Assessment } from "@src/@types/Assessment"; -import type { Endpoint } from "@src/@types/Endpoint"; - -import azureStore from "@src/stores/AzureStore"; -import assessmentStore from "@src/stores/AssessmentStore"; -import endpointStore from "@src/stores/EndpointStore"; -import projectStore from "@src/stores/ProjectStore"; -import userStore from "@src/stores/UserStore"; -import configLoader from "@src/utils/Config"; -import DropdownLink from "@src/components/ui/Dropdowns/DropdownLink"; -import DomUtils from "@src/utils/DomUtils"; - -const Wrapper = styled.div``; - -type Props = { history: any }; -type State = { modalIsOpen: boolean }; -@observer -class AssessmentsPage extends React.Component { - state = { - modalIsOpen: false, - }; - - disablePolling = false; - - pollTimeout = 0; - - UNSAFE_componentWillMount() { - document.title = "Coriolis Planning"; - - projectStore.getProjects(); - - if (!azureStore.isLoadedForCurrentProject()) { - assessmentStore.clearSelection(); - azureStore.clearAssessments(); - } - - this.disablePolling = false; - this.pollData(); - - endpointStore.getEndpoints({ showLoading: true }).then(() => { - const endpoints = endpointStore.endpoints.filter(e => e.type === "azure"); - if (endpoints.length > 0) { - this.chooseEndpoint( - assessmentStore.selectedEndpoint && - assessmentStore.selectedEndpoint.id - ? assessmentStore.selectedEndpoint - : endpoints[0] - ); - } - }); - } - - componentWillUnmount() { - this.disablePolling = true; - clearTimeout(this.pollTimeout); - } - - getEndpointsDropdownConfig(): DropdownLink["props"] & { key: string } { - const endpoints = endpointStore.endpoints.filter(e => e.type === "azure"); - return { - key: "endpoint", - selectedItem: assessmentStore.selectedEndpoint - ? assessmentStore.selectedEndpoint.id - : "", - items: endpoints.map(endpoint => ({ - label: endpoint.name, - value: endpoint.id, - endpoint, - })), - onChange: (item: any) => { - this.chooseEndpoint(item.endpoint, true); - }, - selectItemLabel: "Select Endpoint", - noItemsLabel: endpointStore.loading ? "Loading ..." : "No Endpoints", - }; - } - - getResourceGroupsDropdownConfig(): DropdownLink["props"] & { key: string } { - const groups = azureStore.assessmentResourceGroups; - return { - key: "resource-group", - selectedItem: assessmentStore.selectedResourceGroup - ? assessmentStore.selectedResourceGroup.id - : "", - items: groups.map(group => ({ - label: group.name, - value: group.id, - group, - })), - onChange: (item: any) => { - this.chooseResourceGroup(item.group); - }, - selectItemLabel: "Loading ...", - noItemsLabel: this.areResourceGroupsLoading() - ? "Loading ..." - : "No Resource Groups", - }; - } - - getFilterItems(): { label: string; value: string }[] { - const types = [{ label: "All projects", value: "all" }]; - const assessments = azureStore.assessments; - const uniqueProjects: { name: string }[] = []; - - assessments.forEach(a => { - if (uniqueProjects.findIndex(p => p.name === a.project.name) === -1) { - uniqueProjects.push(a.project); - } - }); - - const projects = uniqueProjects.map(p => ({ - label: p.name, - value: p.name, - })); - return types.concat(projects); - } - - handleReloadButtonClick() { - if (!endpointStore.connectionInfo) { - return; - } - - azureStore.getAssessments({ - subscriptionId: endpointStore.connectionInfo.subscription_id, - resourceGroupName: assessmentStore.selectedResourceGroup?.name || "", - projectId: userStore.loggedUser?.project.id || "", - }); - } - - handleItemClick(assessment: Assessment) { - if (assessment.properties.status.toUpperCase() !== "COMPLETED") { - return; - } - - const connectionInfo = endpointStore.connectionInfo; - const endpoint = assessmentStore.selectedEndpoint; - const resourceGroupName = assessmentStore.selectedResourceGroup - ? assessmentStore.selectedResourceGroup.name - : ""; - const projectName = assessment.project.name; - const groupName = assessment.group.name; - const assessmentName = assessment.name; - - const info = { - endpoint, - connectionInfo, - resourceGroupName, - projectName, - groupName, - assessmentName, - }; - - this.props.history.push( - `/assessment/${DomUtils.encodeToBase64Url({ ...info })}` - ); - } - - handleProjectChange() { - assessmentStore.clearSelection(); - azureStore.clearAssessments(); - endpointStore.getEndpoints({ showLoading: true }).then(() => { - const endpoints = endpointStore.endpoints.filter(e => e.type === "azure"); - if (endpoints.length > 0) { - this.chooseEndpoint( - assessmentStore.selectedEndpoint && - assessmentStore.selectedEndpoint.id - ? assessmentStore.selectedEndpoint - : endpoints[0] - ); - } - }); - } - - handleModalOpen() { - this.setState({ modalIsOpen: true }); - } - - handleModalClose() { - this.setState({ modalIsOpen: false }, () => { - this.pollData(); - }); - } - - areResourceGroupsLoading() { - return azureStore.authenticating || azureStore.loadingResourceGroups; - } - - pollData() { - if (this.disablePolling || this.state.modalIsOpen) { - return; - } - - const connectionInfo = endpointStore.connectionInfo; - const selectedResourceGroup = assessmentStore.selectedResourceGroup; - - if ( - !connectionInfo || - !connectionInfo.subscription_id || - !selectedResourceGroup || - !selectedResourceGroup.name - ) { - this.pollTimeout = window.setTimeout(() => { - this.pollData(); - }, configLoader.config.requestPollTimeout); - return; - } - - azureStore - .getAssessments({ - subscriptionId: connectionInfo.subscription_id, - resourceGroupName: selectedResourceGroup.name, - projectId: userStore.loggedUser?.project.id || "", - backgroundLoading: true, - skipLog: true, - }) - .then(() => { - this.pollTimeout = window.setTimeout(() => { - this.pollData(); - }, configLoader.config.requestPollTimeout); - }); - } - - chooseResourceGroup(selectedResourceGroup: Assessment["group"]) { - if (!endpointStore.connectionInfo) { - return; - } - - assessmentStore.updateSelectedResourceGroup(selectedResourceGroup); - azureStore.getAssessments({ - subscriptionId: endpointStore.connectionInfo.subscription_id, - resourceGroupName: selectedResourceGroup.name, - projectId: userStore.loggedUser?.project.id || "", - }); - } - - chooseEndpoint(selectedEndpoint: Endpoint, clearResourceGroup?: boolean) { - if ( - assessmentStore.selectedEndpoint && - assessmentStore.selectedEndpoint.id === selectedEndpoint.id - ) { - return; - } - - assessmentStore.updateSelectedEndpoint(selectedEndpoint); - - if (clearResourceGroup) { - assessmentStore.updateSelectedResourceGroup(null); - } - - endpointStore.getConnectionInfo(selectedEndpoint).then(() => { - const connectionInfo = endpointStore.connectionInfo; - if (!connectionInfo) { - return; - } - azureStore.authenticate(connectionInfo).then(() => { - azureStore - .getResourceGroups(connectionInfo.subscription_id) - .then(() => { - const groups = azureStore.assessmentResourceGroups; - const selectedGroup = assessmentStore.selectedResourceGroup; - - if ( - groups.filter((rg: any) => - rg.id === selectedGroup ? selectedGroup?.id : "" - ).length > 0 - ) { - return; - } - if (groups.length > 0) { - const defaultResourceGroup = - groups.find( - g => g.name === connectionInfo.default_resource_group - ) || groups[0]; - this.chooseResourceGroup(defaultResourceGroup); - } - }); - }); - }); - } - - itemFilterFunction( - item: any, - filterItem?: string | null, - filterText?: string - ) { - const assessment: Assessment = item; - if ( - (filterItem !== "all" && assessment.project.name !== filterItem) || - (item.name.toLowerCase().indexOf(filterText) === -1 && - assessment.id.toLowerCase().indexOf(filterText || "") === -1) - ) { - return false; - } - - return true; - } - - render() { - return ( - - } - listComponent={ - { - const itemAny: any = item; - const assessment: Assessment = itemAny; - this.handleItemClick(assessment); - }} - onReloadButtonClick={() => { - this.handleReloadButtonClick(); - }} - itemFilterFunction={(...args) => this.itemFilterFunction(...args)} - renderItemComponent={options => { - const optionsAny: any = options; - // eslint-disable-next-line react/jsx-props-no-spreading - return ; - }} - customFilterComponent={ - - } - emptyListImage={null} - emptyListMessage="You don’t have any Assessments." - emptyListExtraMessage="Try selecting a new Endpoint or a new Resource Group." - /> - } - headerComponent={ - { - this.handleProjectChange(); - }} - onModalOpen={() => { - this.handleModalOpen(); - }} - onModalClose={() => { - this.handleModalClose(); - }} - /> - } - /> - - ); - } -} - -export default AssessmentsPage; diff --git a/src/components/smart/AssessmentsPage/package.json b/src/components/smart/AssessmentsPage/package.json deleted file mode 100644 index 76aa24be..00000000 --- a/src/components/smart/AssessmentsPage/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "AssessmentsPage", - "version": "0.0.0", - "private": true, - "main": "./AssessmentsPage.tsx" -} diff --git a/src/sources/AssessmentSource.ts b/src/sources/AssessmentSource.ts deleted file mode 100644 index 14afdecf..00000000 --- a/src/sources/AssessmentSource.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import type { MigrationInfo } from "@src/@types/Assessment"; -import Api from "@src/utils/ApiCaller"; -import configLoader from "@src/utils/Config"; -import notificationStore from "@src/stores/NotificationStore"; -import ObjectUtils from "@src/utils/ObjectUtils"; -import { MigrationItem } from "@src/@types/MainItem"; - -class AssessmentSourceUtils { - static getNetworkMap(data: MigrationInfo) { - const networkMap: any = {}; - if (data.networks && data.networks.length) { - data.networks.forEach(mapping => { - networkMap[mapping.sourceNic.network_name] = - mapping.targetNetwork!.name; - }); - } - return networkMap; - } - - static getDestinationEnv(data: MigrationInfo) { - const env: any = {}; - const vmSize = - data.vmSizes[ - Object.keys(data.vmSizes).filter( - k => k === data.selectedInstances[0].instance_name - )[0] - ]; - if (vmSize) { - env.vm_size = vmSize; - } - const skipFields = [ - "use_replica", - "separate_vm", - "shutdown_instances", - "skip_os_morphing", - ]; - Object.keys(data.fieldValues) - .filter(f => !skipFields.find(sf => sf === f)) - .forEach(fieldName => { - if (data.fieldValues[fieldName] != null) { - env[fieldName] = data.fieldValues[fieldName]; - } - }); - - return env; - } -} - -class AssessmentSource { - static migrate(data: MigrationInfo): Promise { - const type = data.fieldValues.use_replica ? "replica" : "migration"; - const payload: any = {}; - payload[type] = { - origin_endpoint_id: data.source ? data.source.id : "null", - destination_endpoint_id: data.target.id, - destination_environment: AssessmentSourceUtils.getDestinationEnv(data), - instances: data.selectedInstances.map(i => i.instance_name), - network_map: AssessmentSourceUtils.getNetworkMap(data), - notes: "", - replication_count: 2, - }; - - if (type === "migration") { - payload[type].skip_os_morphing = data.fieldValues.skip_os_morphing; - } - return Api.send({ - url: `${configLoader.config.servicesUrls.coriolis}/${Api.projectId}/${type}s`, - method: "POST", - data: payload, - }).then(response => response.data[type]); - } - - static migrateMultiple(data: MigrationInfo): Promise { - return Promise.all( - data.selectedInstances.map(async instance => { - const newData = { ...data }; - newData.selectedInstances = [instance]; - try { - return await this.migrate(newData); - } catch (e) { - notificationStore.alert( - `Error while migrating instance ${instance.name}`, - "error" - ); - return null; - } - }) - ).then(items => items.filter(ObjectUtils.notEmpty).map(i => i)); - } -} - -export default AssessmentSource; diff --git a/src/sources/AzureSource.ts b/src/sources/AzureSource.ts deleted file mode 100644 index c32f3aaf..00000000 --- a/src/sources/AzureSource.ts +++ /dev/null @@ -1,253 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import Api from "@src/utils/ApiCaller"; -import DomUtils from "@src/utils/DomUtils"; - -import type { Assessment, VmItem, VmSize } from "@src/@types/Assessment"; - -const azureUrl = "https://management.azure.com/"; -const defaultApiVersion = "2019-10-01"; - -const resourceGroupsUrl = (opts: { subscriptionId: string }) => - `/subscriptions/${opts.subscriptionId}/resourceGroups`; -const projectsUrl = ({ resourceGroupName, ...other }: any) => - `${resourceGroupsUrl({ - ...other, - })}/${resourceGroupName}/providers/Microsoft.Migrate/assessmentprojects`; -const groupsUrl = ({ projectName, ...other }: any) => - `${projectsUrl({ ...other })}/${projectName}/groups`; -const assessmentsUrl = ({ groupName, ...other }: any) => - `${groupsUrl({ ...other })}/${groupName}/assessments`; -const assessmentDetailsUrl = ({ assessmentName, ...other }: any) => - `${assessmentsUrl({ ...other })}/${assessmentName}`; -const assessedVmsUrl = ({ ...other }) => - `${assessmentDetailsUrl({ ...other })}/assessedMachines`; - -class Util { - static buildUrl(baseUrl: string, apiVersion?: string): string { - const url = `/proxy/azure/${DomUtils.encodeToBase64Url( - `${azureUrl + baseUrl}?api-version=${apiVersion || defaultApiVersion}` - )}`; - return url; - } - - static sortAssessments(assessments: any[]) { - assessments.sort( - (a: any, b: any) => - new Date(b.properties.updatedTimestamp).getTime() - - new Date(a.properties.updatedTimestamp).getTime() - ); - return assessments; - } - - static checkQueues(queues: any[], requestIds: any, callback: any) { - if (requestIds[0] !== requestIds[1]) { - return; - } - - const doneQeues = queues.filter(q => q === 0).length; - if (doneQeues === queues.length) { - callback(); - } - } - - static isResponseValid(response: any): boolean { - if (response && response.data && response.data.error) { - const error = response.data.error; - console.error("%c", "color: #D0021B", `${error.code}: ${error.message}`); - return false; - } - return true; - } - - static validateResponse(response: any, resolveData: any): Promise { - if (!this.isResponseValid(response)) { - return Promise.reject(); - } - - if (resolveData) { - return Promise.resolve(resolveData); - } - return Promise.resolve(response); - } -} - -class AzureSource { - static authenticate(connectionInfo: any): Promise { - return Api.send({ - url: "/proxy/azure/login", - method: "POST", - data: connectionInfo, - }).then(response => { - const entries = Object.keys(response.data.tokenCache)[0]; - const accessToken = response.data.tokenCache[entries][0].accessToken; - Api.setDefaultHeader("Authorization", `Bearer ${accessToken}`); - return response.data; - }); - } - - static getResourceGroups( - subscriptionId: string - ): Promise { - return Api.get( - Util.buildUrl(resourceGroupsUrl({ subscriptionId }), "2017-08-01") - ).then(response => Util.validateResponse(response, response.data.value)); - } - - static previousReqId: string; - - static async getAssessments( - subscriptionId: string, - resourceGroupName: string, - skipLog?: boolean | null - ): Promise { - const cancelId = subscriptionId + resourceGroupName; - if (this.previousReqId) { - Api.cancelRequests(this.previousReqId); - } - this.previousReqId = cancelId; - - // Load Projects - let projects: any[] = []; - const projectsResponse = await Api.send({ - url: Util.buildUrl(projectsUrl({ resourceGroupName, subscriptionId })), - cancelId, - skipLog, - }); - if (!Util.isResponseValid(projectsResponse)) { - projects = []; - } - projects = projectsResponse.data.value.filter( - (p: any) => p.type === "Microsoft.Migrate/assessmentprojects" - ); - - // Load groups for each project - const groupsResponses = await Promise.all( - projects.map(async (project: any) => { - let groups: any[] | null = null; - - const groupsResponse = await Api.send({ - url: Util.buildUrl( - groupsUrl({ - projectName: project.name, - subscriptionId, - resourceGroupName, - }) - ), - cancelId, - }); - if (!Util.isResponseValid(groupsResponse)) { - groups = null; - } - groups = groupsResponse.data.value.map((group: any) => ({ - ...group, - project, - })); - return groups; - }) - ); - - let groups: any[] = []; - groupsResponses - .filter(r => r !== null) - .forEach(validGroupsReponse => { - groups = groups.concat(validGroupsReponse); - }); - - // Load assessments for each group - return Promise.all( - groups.map(group => - Api.send({ - url: Util.buildUrl( - assessmentsUrl({ - subscriptionId, - resourceGroupName, - projectName: group.project.name, - groupName: group.name, - }) - ), - cancelId, - }).then(assessmentResponse => { - if (!Util.isResponseValid(assessmentResponse)) { - return null; - } - return assessmentResponse.data.value.map( - (assessment: Assessment) => ({ - ...assessment, - group, - project: group.project, - properies: { - ...assessment.properties, - azureLocation: - assessment.properties.azureLocation.toLowerCase(), - }, - }) - ); - }) - ) - ); - } - - static async getAssessmentDetails(info: Assessment): Promise { - const response = await Api.get( - Util.buildUrl( - assessmentDetailsUrl({ - ...info, - subscriptionId: info.connectionInfo.subscription_id, - }) - ) - ); - const assessment: Assessment = await Util.validateResponse(response, { - ...response.data, - ...info, - }); - assessment.properties.azureLocation = - assessment.properties.azureLocation.toLowerCase(); - return assessment; - } - - static getAssessedVms(info: Assessment): Promise { - return Api.get( - Util.buildUrl( - assessedVmsUrl({ - ...info, - subscriptionId: info.connectionInfo.subscription_id, - }) - ) - ).then(response => { - if (!Util.isResponseValid(response)) { - return []; - } - - const vms = response.data.value; - vms.sort((a: any, b: any) => { - const getLabel = (item: any) => item.properties.displayName; - return getLabel(a).localeCompare(getLabel(b)); - }); - return vms; - }); - } - - static getVmSizes(info: Assessment): Promise { - return Api.get( - Util.buildUrl( - `/subscriptions/${info.connectionInfo.subscription_id}/providers/Microsoft.Compute/locations/${info.location}/vmSizes`, - "2017-12-01" - ) - ).then(response => Util.validateResponse(response, response.data.value)); - } -} - -export default AzureSource; diff --git a/src/sources/MigrationSource.ts b/src/sources/MigrationSource.ts deleted file mode 100644 index c2733f98..00000000 --- a/src/sources/MigrationSource.ts +++ /dev/null @@ -1,369 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import { - MigrationItem, - MigrationItemDetails, - MigrationItemOptions, - UserScriptData, -} from "@src/@types/MainItem"; -import { ProgressUpdate, Task } from "@src/@types/Task"; -import { INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS } from "@src/components/modules/WizardModule/WizardOptions"; -import { OptionsSchemaPlugin } from "@src/plugins"; -import DefaultOptionsSchemaPlugin from "@src/plugins/default/OptionsSchemaPlugin"; -import Api from "@src/utils/ApiCaller"; -import configLoader from "@src/utils/Config"; - -import { sortTasks } from "./TransferSource"; - -import type { InstanceScript } from "@src/@types/Instance"; -import type { Field } from "@src/@types/Field"; -import type { NetworkMap } from "@src/@types/Network"; -import type { Endpoint, StorageMap } from "@src/@types/Endpoint"; - -class MigrationSourceUtils { - static sortTaskUpdates(updates: ProgressUpdate[]) { - if (!updates) { - return; - } - updates.sort((a, b) => { - const sortNull = !a && b ? 1 : a && !b ? -1 : !a && !b ? 0 : false; - if (sortNull !== false) { - return sortNull; - } - return a.index - b.index; - }); - } - - static sortMigrations(migrations: any[]) { - migrations.sort( - (a: any, b: any) => - new Date(b.created_at).getTime() - new Date(a.created_at).getTime() - ); - - migrations.forEach((migration: { tasks: Task[] }) => { - sortTasks(migration.tasks, MigrationSourceUtils.sortTaskUpdates); - }); - } -} - -class MigrationSource { - async getMigrations(skipLog?: boolean): Promise { - const response = await Api.send({ - url: `${configLoader.config.servicesUrls.coriolis}/${Api.projectId}/migrations`, - skipLog, - }); - const migrations = response.data.migrations; - MigrationSourceUtils.sortMigrations(migrations); - return migrations; - } - - async getMigration( - migrationId: string, - skipLog?: boolean - ): Promise { - const response = await Api.send({ - url: `${configLoader.config.servicesUrls.coriolis}/${Api.projectId}/migrations/${migrationId}`, - skipLog, - cancelId: migrationId, - }); - const migration = response.data.migration; - sortTasks(migration.tasks, MigrationSourceUtils.sortTaskUpdates); - return migration; - } - - async recreateFullCopy( - migration: MigrationItemOptions - ): Promise { - const { - // eslint-disable-next-line @typescript-eslint/naming-convention - origin_endpoint_id, - destination_endpoint_id, - destination_environment, - // eslint-disable-next-line @typescript-eslint/naming-convention - network_map, - instances, - storage_mappings, - notes, - destination_minion_pool_id, - // eslint-disable-next-line @typescript-eslint/naming-convention - origin_minion_pool_id, - instance_osmorphing_minion_pool_mappings, - } = migration; - - const payload: any = { - migration: { - origin_endpoint_id, - destination_endpoint_id, - destination_environment, - network_map, - instances, - storage_mappings, - notes, - destination_minion_pool_id, - origin_minion_pool_id, - instance_osmorphing_minion_pool_mappings, - }, - }; - - if (migration.skip_os_morphing != null) { - payload.migration.skip_os_morphing = migration.skip_os_morphing; - } - - if (migration.source_environment) { - payload.migration.source_environment = migration.source_environment; - } - - payload.migration.shutdown_instances = Boolean( - migration.shutdown_instances - ); - payload.migration.replication_count = migration.replication_count || 2; - - const response = await Api.send({ - url: `${configLoader.config.servicesUrls.coriolis}/${Api.projectId}/migrations`, - method: "POST", - data: payload, - }); - return response.data.migration; - } - - async recreate(opts: { - sourceEndpoint: Endpoint; - destEndpoint: Endpoint; - instanceNames: string[]; - destEnv: { [prop: string]: any } | null; - updatedDestEnv: { [prop: string]: any } | null; - sourceEnv?: { [prop: string]: any } | null; - updatedSourceEnv?: { [prop: string]: any } | null; - storageMappings?: { [prop: string]: any } | null; - updatedStorageMappings: StorageMap[] | null; - defaultStorage?: { value: string | null; busType?: string | null }; - updatedDefaultStorage?: { value: string | null; busType?: string | null }; - networkMappings?: any; - updatedNetworkMappings: NetworkMap[] | null; - defaultSkipOsMorphing: boolean | null; - replicationCount?: number | null; - migration: MigrationItemDetails; - uploadedScripts: InstanceScript[]; - removedScripts: InstanceScript[]; - }): Promise { - const getValue = (fieldName: string): string | null => { - const updatedDestEnv = - opts.updatedDestEnv && opts.updatedDestEnv[fieldName]; - return updatedDestEnv != null - ? updatedDestEnv - : opts.destEnv && opts.destEnv[fieldName]; - }; - - const sourceParser = OptionsSchemaPlugin.for(opts.sourceEndpoint.type); - const destParser = OptionsSchemaPlugin.for(opts.destEndpoint.type); - const payload: any = {}; - - payload.migration = { - origin_endpoint_id: opts.sourceEndpoint.id, - destination_endpoint_id: opts.destEndpoint.id, - shutdown_instances: Boolean( - opts.updatedDestEnv && opts.updatedDestEnv.shutdown_instances - ), - replication_count: - (opts.updatedDestEnv && opts.updatedDestEnv.replication_count) || - opts.replicationCount || - 2, - instances: opts.instanceNames, - notes: opts.updatedDestEnv?.title || opts.migration.notes || "", - }; - - const skipOsMorphingValue = getValue("skip_os_morphing"); - if (skipOsMorphingValue != null) { - payload.migration.skip_os_morphing = skipOsMorphingValue; - } else if (opts.defaultSkipOsMorphing != null) { - payload.migration.skip_os_morphing = opts.defaultSkipOsMorphing; - } - - if ( - opts.networkMappings || - (opts.updatedNetworkMappings && opts.updatedNetworkMappings.length) - ) { - payload.migration.network_map = { - ...opts.networkMappings, - ...destParser.getNetworkMap(opts.updatedNetworkMappings), - }; - } - - if ( - (opts.storageMappings && Object.keys(opts.storageMappings).length) || - (opts.updatedStorageMappings && opts.updatedStorageMappings.length) - ) { - payload.migration.storage_mappings = { - ...opts.storageMappings, - ...destParser.getStorageMap( - opts.updatedDefaultStorage || opts.defaultStorage, - opts.updatedStorageMappings - ), - }; - } - const { migration } = opts; - const sourceEnv: any = { - ...opts.sourceEnv, - }; - const updatedSourceEnv = opts.updatedSourceEnv - ? sourceParser.getDestinationEnv(opts.updatedSourceEnv) - : {}; - const sourceMinionPoolId = - opts?.updatedSourceEnv?.minion_pool_id || migration.origin_minion_pool_id; - if (sourceMinionPoolId) { - payload.migration.origin_minion_pool_id = sourceMinionPoolId; - } - payload.migration.source_environment = { - ...sourceEnv, - ...updatedSourceEnv, - }; - - const destEnv: any = { - ...opts.destEnv, - }; - const updatedDestEnv = opts.updatedDestEnv - ? sourceParser.getDestinationEnv(opts.updatedDestEnv) - : {}; - const destMinionPoolId = - opts?.updatedDestEnv?.minion_pool_id || - migration.destination_minion_pool_id; - if (destMinionPoolId) { - payload.migration.destination_minion_pool_id = destMinionPoolId; - } - - const updatedDestEnvMappings = - updatedDestEnv[INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS] || {}; - const oldMappings = - migration[INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS] || {}; - const mergedMappings = { ...oldMappings, ...updatedDestEnvMappings }; - if (Object.keys(mergedMappings).length) { - const newMappings: any = {}; - Object.keys(mergedMappings).forEach(k => { - if (mergedMappings[k] !== null) { - newMappings[k] = mergedMappings[k]; - } - }); - payload.migration[INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS] = newMappings; - } - - delete updatedDestEnv[INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS]; - - payload.migration.destination_environment = { - ...destEnv, - ...updatedDestEnv, - }; - - if ( - opts.uploadedScripts?.length || - opts.removedScripts?.length || - migration.user_scripts - ) { - payload.migration.user_scripts = - new DefaultOptionsSchemaPlugin().getUserScripts( - opts.uploadedScripts || [], - opts.removedScripts || [], - migration.user_scripts - ); - } - - const response = await Api.send({ - url: `${configLoader.config.servicesUrls.coriolis}/${Api.projectId}/migrations`, - method: "POST", - data: payload, - }); - return response.data.migration; - } - - async cancel(migrationId: string, force?: boolean | null): Promise { - const data: any = { cancel: null }; - if (force) { - data.cancel = { force: true }; - } - await Api.send({ - url: `${configLoader.config.servicesUrls.coriolis}/${Api.projectId}/migrations/${migrationId}/actions`, - method: "POST", - data, - }); - return migrationId; - } - - async delete(migrationId: string): Promise { - await Api.send({ - url: `${configLoader.config.servicesUrls.coriolis}/${Api.projectId}/migrations/${migrationId}`, - method: "DELETE", - }); - return migrationId; - } - - async migrateReplica(opts: { - replicaId: string; - options: Field[]; - uploadedUserScripts: InstanceScript[]; - removedUserScripts: InstanceScript[]; - userScriptData: UserScriptData | null | undefined; - minionPoolMappings: { [instance: string]: string }; - }): Promise { - const { - replicaId, - options, - uploadedUserScripts, - removedUserScripts, - userScriptData, - minionPoolMappings, - } = opts; - const payload: any = { - migration: { - replica_id: replicaId, - }, - }; - options.forEach(o => { - payload.migration[o.name] = o.value || o.default || false; - }); - - if ( - uploadedUserScripts.length || - removedUserScripts.length || - userScriptData - ) { - payload.migration.user_scripts = - new DefaultOptionsSchemaPlugin().getUserScripts( - uploadedUserScripts, - removedUserScripts, - userScriptData - ); - } - - if (Object.keys(minionPoolMappings).length) { - const newMappings: any = {}; - Object.keys(minionPoolMappings).forEach(k => { - if (minionPoolMappings[k] !== null) { - newMappings[k] = minionPoolMappings[k]; - } - }); - payload.migration[INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS] = newMappings; - } else { - payload.migration[INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS] = null; - } - - const response = await Api.send({ - url: `${configLoader.config.servicesUrls.coriolis}/${Api.projectId}/migrations`, - method: "POST", - data: payload, - }); - return response.data.migration; - } -} - -export default new MigrationSource(); diff --git a/src/stores/AssessmentStore.ts b/src/stores/AssessmentStore.ts deleted file mode 100644 index 3cd180ae..00000000 --- a/src/stores/AssessmentStore.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import { observable, action } from "mobx"; - -import AssessmentSource from "@src/sources/AssessmentSource"; -import type { Endpoint } from "@src/@types/Endpoint"; -import type { Assessment, MigrationInfo } from "@src/@types/Assessment"; -import { MigrationItem } from "@src/@types/MainItem"; - -class AssessmentStore { - @observable selectedEndpoint: Endpoint | null = null; - - @observable selectedResourceGroup: Assessment["group"] | null = null; - - @observable migrating = false; - - @observable migrations: MigrationItem[] = []; - - @action updateSelectedEndpoint(endpoint: Endpoint) { - this.selectedEndpoint = endpoint; - } - - @action updateSelectedResourceGroup( - resourceGroup: Assessment["group"] | null - ) { - this.selectedResourceGroup = resourceGroup; - } - - @action async migrate(data: MigrationInfo): Promise { - this.migrating = true; - this.migrations = []; - const separateVm = data.fieldValues.separate_vm; - - if (separateVm) { - try { - const items = await AssessmentSource.migrateMultiple(data); - this.migrating = false; - this.migrations = items; - } catch (e) { - this.migrating = false; - } - } - - try { - const item = await AssessmentSource.migrate(data); - this.migrating = false; - this.migrations = [item]; - } catch (e) { - this.migrating = false; - } - } - - @action clearSelection() { - this.selectedEndpoint = null; - this.selectedResourceGroup = null; - } -} - -export default new AssessmentStore(); diff --git a/src/stores/AzureStore.ts b/src/stores/AzureStore.ts deleted file mode 100644 index 5b942d51..00000000 --- a/src/stores/AzureStore.ts +++ /dev/null @@ -1,314 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import { observable, action } from "mobx"; -import cookie from "js-cookie"; - -import AzureSource from "@src/sources/AzureSource"; -import type { Assessment, VmItem, AzureLocation } from "@src/@types/Assessment"; -import type { NetworkMap } from "@src/@types/Network"; -import type { Endpoint } from "@src/@types/Endpoint"; - -export type LocalData = { - endpoint: Endpoint; - sourceEndpoint: Endpoint | null; - connectionInfo: any; - resourceGroupName: string; - locationName: string; - assessmentName: string; - groupName: string; - projectName: string; - selectedVmSizes: { [prop: string]: string }; - selectedVms: string[]; - selectedNetworks: NetworkMap[]; - [prop: string]: any; -}; - -class AzureLocalStorage { - static loadLocalData(assessmentName: string): LocalData | undefined { - const localDataArray: LocalData[] = JSON.parse( - localStorage.getItem(`assessments-${cookie.get("projectId") || ""}`) || - "[]" - ); - return localDataArray.find(a => a.assessmentName === assessmentName); - } - - static setLocalData(data: LocalData) { - const localDataArray: LocalData[] = JSON.parse( - localStorage.getItem(`assessments-${cookie.get("projectId") || ""}`) || - "[]" - ); - const assessmentIndex = localDataArray.findIndex( - a => a.assessmentName === data.assessmentName - ); - if (assessmentIndex > -1) { - localDataArray.splice(assessmentIndex, 1); - } - localDataArray.push(data); - localStorage.setItem( - `assessments-${cookie.get("projectId") || ""}`, - JSON.stringify(localDataArray) - ); - } -} - -class AzureStore { - @observable authenticating = false; - - @observable loadingResourceGroups = false; - - @observable assessmentResourceGroups: Assessment["group"][] = []; - - @observable coriolisResourceGroups: string[] = []; - - @observable loadingAssessments = false; - - @observable loadingAssessmentDetails = false; - - @observable assessmentDetails: Assessment | null = null; - - @observable assessments: Assessment[] = []; - - @observable loadingAssessedVms = false; - - @observable assessedVms: VmItem[] = []; - - @observable loadingVmSizes = false; - - // @observable vmSizes: VmSize[] = [] - @observable assessmentsProjectId = ""; - - @observable locations: AzureLocation[] = []; - - @observable localData: LocalData | null | undefined = null; - - @observable vmSizes: string[] = []; - - @action loadLocalData(assessmentName: string): boolean { - this.localData = AzureLocalStorage.loadLocalData(assessmentName); - return Boolean(this.localData); - } - - @action setLocalData(data: LocalData) { - const newData = data; - newData.selectedVmSizes = data.selectedVmSizes || {}; - newData.selectedVms = data.selectedVms || []; - newData.selectedNetworks = data.selectedNetworks || []; - - this.localData = newData; - AzureLocalStorage.setLocalData(newData); - } - - @action updateResourceGroup(resourceGroupName: string) { - if (!this.localData) { - return; - } - this.localData.resourceGroupName = resourceGroupName; - AzureLocalStorage.setLocalData(this.localData); - } - - @action updateNetworkMap(selectedNetworks: NetworkMap[]) { - if (!this.localData) { - return; - } - this.localData.selectedNetworks = selectedNetworks; - AzureLocalStorage.setLocalData(this.localData); - } - - @action updateSourceEndpoint(sourceEndpoint: Endpoint | null) { - if (!this.localData) { - return; - } - this.localData.sourceEndpoint = sourceEndpoint; - AzureLocalStorage.setLocalData(this.localData); - } - - @action updateSelectedVms(selectedVms: string[]) { - if (!this.localData) { - return; - } - this.localData.selectedVms = selectedVms; - AzureLocalStorage.setLocalData(this.localData); - } - - @action updateVmSize(vmId: string, vmSize: string) { - if (!this.localData) { - return; - } - this.localData.selectedVmSizes[vmId] = vmSize; - if (this.localData) { - AzureLocalStorage.setLocalData(this.localData); - } - } - - @action updateVmSizes(vmSizes: { [prop: string]: string }) { - if (!this.localData) { - return; - } - this.localData.selectedVmSizes = vmSizes; - AzureLocalStorage.setLocalData(this.localData); - } - - @action updateLocation(locationName: string) { - if (!this.localData) { - return; - } - this.localData.locationName = locationName; - AzureLocalStorage.setLocalData(this.localData); - } - - @action updateTargetEndpoint(endpoint: Endpoint) { - if (!this.localData) { - return; - } - this.localData.endpoint = endpoint; - AzureLocalStorage.setLocalData(this.localData); - } - - @action async authenticate(connectionInfo: any): Promise { - this.authenticating = true; - try { - await AzureSource.authenticate(connectionInfo); - this.authenticating = false; - return await Promise.resolve(); - } catch (e) { - this.authenticating = false; - return Promise.reject(); - } - } - - @action async getResourceGroups(subscriptionId: string): Promise { - this.loadingResourceGroups = true; - - try { - const groups = await AzureSource.getResourceGroups(subscriptionId); - this.loadingResourceGroups = false; - this.assessmentResourceGroups = groups; - } catch (e) { - this.loadingResourceGroups = false; - } - } - - @action isLoadedForCurrentProject() { - return this.assessmentsProjectId === (cookie.get("projectId") || "null"); - } - - @action async getAssessments(opts: { - subscriptionId: string; - resourceGroupName: string; - projectId: string; - backgroundLoading?: boolean; - skipLog?: boolean; - }): Promise { - const { - subscriptionId, - resourceGroupName, - projectId, - backgroundLoading, - skipLog, - } = opts; - let cookieProjectId = cookie.get("projectId") || "null"; - if (projectId !== cookieProjectId) { - return Promise.resolve(); - } - - if (!backgroundLoading) { - this.loadingAssessments = true; - } - const assessments = await AzureSource.getAssessments( - subscriptionId, - resourceGroupName, - skipLog - ); - this.loadingAssessments = false; - cookieProjectId = cookie.get("projectId") || "null"; - if (projectId !== cookieProjectId) { - return Promise.resolve(); - } - this.assessmentsProjectId = cookieProjectId; - this.assessments = assessments; - return Promise.resolve(); - } - - @action async getAssessmentDetails(info: Assessment): Promise { - this.loadingAssessmentDetails = true; - try { - const assessment = await AzureSource.getAssessmentDetails(info); - this.loadingAssessmentDetails = false; - this.assessmentDetails = assessment; - } catch (e) { - this.loadingAssessmentDetails = false; - } - } - - @action saveLocations(locations: AzureLocation[]) { - this.locations = locations; - } - - @action saveResourceGroups(resourceGroups: string[]) { - this.coriolisResourceGroups = resourceGroups; - } - - @action saveTargetVmSizes(targetVmSizes: string[]) { - this.vmSizes = targetVmSizes; - } - - @action setLocation(location: string) { - if (!this.localData || this.localData.locationName) { - return; - } - this.localData.locationName = location; - } - - @action clearAssessmentDetails() { - this.assessmentDetails = null; - this.assessedVms = []; - } - - @action async getAssessedVms(info: Assessment): Promise { - this.loadingAssessedVms = true; - - try { - const vms = await AzureSource.getAssessedVms(info); - this.loadingAssessedVms = false; - this.assessedVms = vms; - } catch (e) { - this.loadingAssessedVms = false; - } - } - - // @action getVmSizes(info: Assessment): Promise { - // this.loadingVmSizes = true - - // return AzureSource.getVmSizes(info).then((sizes: VmSize[]) => { - // this.loadingVmSizes = false - // this.vmSizes = sizes - // }).catch(() => { - // this.loadingVmSizes = false - // }) - // } - - @action clearAssessedVms() { - this.assessedVms = []; - } - - @action clearAssessments() { - this.assessmentResourceGroups = []; - this.assessments = []; - this.locations = []; - this.coriolisResourceGroups = []; - } -} - -export default new AzureStore(); diff --git a/src/stores/MigrationStore.ts b/src/stores/MigrationStore.ts deleted file mode 100644 index d33b32d8..00000000 --- a/src/stores/MigrationStore.ts +++ /dev/null @@ -1,198 +0,0 @@ -/* -Copyright (C) 2017 Cloudbase Solutions SRL -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -import { observable, action, runInAction } from "mobx"; - -import type { - UpdateData, - MigrationItem, - MigrationItemDetails, - MigrationItemOptions, - UserScriptData, -} from "@src/@types/MainItem"; -import type { Field } from "@src/@types/Field"; -import type { Endpoint } from "@src/@types/Endpoint"; -import type { InstanceScript } from "@src/@types/Instance"; -import MigrationSource from "@src/sources/MigrationSource"; -import apiCaller from "@src/utils/ApiCaller"; - -class MigrationStore { - @observable migrations: MigrationItem[] = []; - - @observable migrationDetails: MigrationItemDetails | null = null; - - @observable loading = true; - - @observable detailsLoading = true; - - migrationsLoaded = false; - - @action async getMigrations(options?: { - showLoading?: boolean; - skipLog?: boolean; - }) { - if ((options && options.showLoading) || !this.migrationsLoaded) { - this.loading = true; - } - - try { - const migrations = await MigrationSource.getMigrations( - options && options.skipLog - ); - runInAction(() => { - this.migrations = migrations; - this.loading = false; - this.migrationsLoaded = true; - }); - } catch (ex) { - runInAction(() => { - this.loading = false; - }); - throw ex; - } - } - - getDefaultSkipOsMorphing(migration: MigrationItemDetails | null) { - const tasks = migration && migration.tasks; - if (tasks && !tasks.find(t => t.task_type === "OS_MORPHING")) { - return true; - } - return null; - } - - @action async recreateFullCopy(migration: MigrationItemOptions) { - return MigrationSource.recreateFullCopy(migration); - } - - @action async recreate(opts: { - migration: MigrationItemDetails; - sourceEndpoint: Endpoint; - destEndpoint: Endpoint; - updateData: UpdateData; - defaultStorage: { value: string | null; busType?: string | null }; - updatedDefaultStorage: - | { value: string | null; busType?: string | null } - | undefined; - replicationCount: number | null | undefined; - }): Promise { - const { - migration, - sourceEndpoint, - destEndpoint, - updateData, - defaultStorage, - updatedDefaultStorage, - replicationCount, - } = opts; - const migrationResult = await MigrationSource.recreate({ - sourceEndpoint, - destEndpoint, - migration, - instanceNames: migration.instances, - sourceEnv: migration.source_environment, - updatedSourceEnv: updateData.source, - destEnv: migration.destination_environment, - updatedDestEnv: updateData.destination, - storageMappings: migration.storage_mappings, - updatedStorageMappings: updateData.storage, - defaultStorage, - updatedDefaultStorage, - networkMappings: migration.network_map, - updatedNetworkMappings: updateData.network, - defaultSkipOsMorphing: this.getDefaultSkipOsMorphing(migration), - replicationCount, - uploadedScripts: updateData.uploadedScripts, - removedScripts: updateData.removedScripts, - }); - return migrationResult; - } - - @action async getMigration( - migrationId: string, - options?: { showLoading?: boolean; skipLog?: boolean } - ) { - if (options && options.showLoading) { - this.detailsLoading = true; - } - - try { - const migration = await MigrationSource.getMigration( - migrationId, - options && options.skipLog - ); - runInAction(() => { - this.migrationDetails = migration; - this.migrations = this.migrations.map(m => - m.id === migration.id ? migration : m - ); - }); - } finally { - runInAction(() => { - this.detailsLoading = false; - }); - } - } - - @action async cancel(migrationId: string, force?: boolean | null) { - await MigrationSource.cancel(migrationId, force); - } - - @action async delete(migrationId: string) { - await MigrationSource.delete(migrationId); - runInAction(() => { - this.migrations = this.migrations.filter(r => r.id !== migrationId); - }); - } - - @action async migrateReplica(opts: { - replicaId: string; - fields: Field[]; - uploadedUserScripts: InstanceScript[]; - removedUserScripts: InstanceScript[]; - userScriptData: UserScriptData | null | undefined; - minionPoolMappings: { [instance: string]: string }; - }) { - const { - replicaId, - fields: options, - uploadedUserScripts, - removedUserScripts, - userScriptData, - minionPoolMappings, - } = opts; - const migration = await MigrationSource.migrateReplica({ - replicaId, - options, - uploadedUserScripts, - removedUserScripts, - userScriptData, - minionPoolMappings, - }); - return migration; - } - - @action cancelMigrationDetails() { - if (this.migrationDetails) { - apiCaller.cancelRequests(this.migrationDetails.id); - } - this.detailsLoading = false; - } - - @action clearDetails() { - this.detailsLoading = true; - this.migrationDetails = null; - } -} - -export default new MigrationStore();