mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-08-17 05:09:51 +00:00
feat(forklift): small fixes after Copilot
Signed-off-by: Marcelo Fukumoto <marcelo.fukumoto@suse.com>
This commit is contained in:
parent
5c7dd1953d
commit
2deb0aa254
11
.vscode/settings.json
vendored
11
.vscode/settings.json
vendored
@ -5,5 +5,14 @@
|
|||||||
".eslintcache": true,
|
".eslintcache": true,
|
||||||
".nyc_output": true,
|
".nyc_output": true,
|
||||||
"yarn-error.log": true
|
"yarn-error.log": true
|
||||||
}
|
},
|
||||||
|
"editor.formatOnSave": false,
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.eslint": "explicit"
|
||||||
|
},
|
||||||
|
"eslint.validate": [
|
||||||
|
"javascript",
|
||||||
|
"typescript",
|
||||||
|
"vue"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -159,9 +159,17 @@ watch(selectedProvider, (val) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (secret?.data) {
|
if (secret?.data) {
|
||||||
username.value = atob(secret.data.user || '');
|
const decode = (val) => {
|
||||||
password.value = atob(secret.data.password || '');
|
try {
|
||||||
skipTlsVerify.value = atob(secret.data.insecureSkipVerify || '') === 'true';
|
return atob(val || '');
|
||||||
|
} catch (e) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
username.value = decode(secret.data.user);
|
||||||
|
password.value = decode(secret.data.password);
|
||||||
|
skipTlsVerify.value = decode(secret.data.insecureSkipVerify) === 'true';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,6 +203,74 @@ watch(testing, (val) => {
|
|||||||
emit('testing', val);
|
emit('testing', val);
|
||||||
}, { immediate: true });
|
}, { immediate: true });
|
||||||
|
|
||||||
|
const pollProviderReady = async(name) => {
|
||||||
|
const inStore = store.getters['currentProduct'].inStore;
|
||||||
|
const namespace = FORKLIFT_NAMESPACE;
|
||||||
|
const maxAttempts = 15;
|
||||||
|
let attempts = 0;
|
||||||
|
|
||||||
|
while (attempts < maxAttempts) {
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||||
|
attempts++;
|
||||||
|
|
||||||
|
const refreshed = await store.dispatch(`${ inStore }/find`, {
|
||||||
|
type: HCI.FORKLIFT_PROVIDER,
|
||||||
|
id: `${ namespace }/${ name }`,
|
||||||
|
opt: { force: true }
|
||||||
|
});
|
||||||
|
|
||||||
|
const conditions = refreshed?.status?.conditions || [];
|
||||||
|
const connectionCondition = conditions.find((c) => c.type === 'ConnectionTestSucceeded');
|
||||||
|
const readyCondition = conditions.find((c) => c.type === 'Ready');
|
||||||
|
|
||||||
|
if (connectionCondition) {
|
||||||
|
if (connectionCondition.status === 'True') {
|
||||||
|
return { connected: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { connected: false, errorMsg: connectionCondition.message || t('harvester.addons.vmMigration.errors.connectionFailed') };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readyCondition) {
|
||||||
|
if (readyCondition.status === 'True') {
|
||||||
|
return { connected: true };
|
||||||
|
} else if (readyCondition.status === 'False') {
|
||||||
|
return { connected: false, errorMsg: readyCondition.message || t('harvester.addons.vmMigration.errors.providerNotReady') };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { connected: false, errorMsg: '' };
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePollResult = ({ connected, errorMsg }, buttonCb) => {
|
||||||
|
if (connected) {
|
||||||
|
testPassed.value = true;
|
||||||
|
testResult.value = t('harvester.addons.vmMigration.configureProvider.testSuccess');
|
||||||
|
testing.value = false;
|
||||||
|
buttonCb(true);
|
||||||
|
} else {
|
||||||
|
testError.value = errorMsg || t('harvester.addons.vmMigration.configureProvider.testTimeout');
|
||||||
|
testing.value = false;
|
||||||
|
buttonCb(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const cleanupCreatedResources = async() => {
|
||||||
|
if (createdProvider.value) {
|
||||||
|
try {
|
||||||
|
await createdProvider.value.remove();
|
||||||
|
} catch (e) {}
|
||||||
|
createdProvider.value = null;
|
||||||
|
createdSecret.value = null;
|
||||||
|
} else if (createdSecret.value) {
|
||||||
|
try {
|
||||||
|
await createdSecret.value.remove();
|
||||||
|
} catch (e) {}
|
||||||
|
createdSecret.value = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const testConnection = async(buttonCb) => {
|
const testConnection = async(buttonCb) => {
|
||||||
testResult.value = null;
|
testResult.value = null;
|
||||||
testError.value = null;
|
testError.value = null;
|
||||||
@ -213,8 +289,6 @@ const testConnection = async(buttonCb) => {
|
|||||||
// Edit mode: update existing provider URL + secret, then poll
|
// Edit mode: update existing provider URL + secret, then poll
|
||||||
if (props.editMode && createdProvider.value) {
|
if (props.editMode && createdProvider.value) {
|
||||||
try {
|
try {
|
||||||
const namespace = FORKLIFT_NAMESPACE;
|
|
||||||
|
|
||||||
createdProvider.value.spec.url = url.value;
|
createdProvider.value.spec.url = url.value;
|
||||||
await createdProvider.value.save();
|
await createdProvider.value.save();
|
||||||
|
|
||||||
@ -230,56 +304,7 @@ const testConnection = async(buttonCb) => {
|
|||||||
await createdSecret.value.save();
|
await createdSecret.value.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxAttempts = 15;
|
handlePollResult(await pollProviderReady(providerName.value), buttonCb);
|
||||||
let attempts = 0;
|
|
||||||
let connected = false;
|
|
||||||
let errorMsg = '';
|
|
||||||
|
|
||||||
while (attempts < maxAttempts) {
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
||||||
attempts++;
|
|
||||||
|
|
||||||
const refreshed = await store.dispatch(`${ inStore }/find`, {
|
|
||||||
type: HCI.FORKLIFT_PROVIDER,
|
|
||||||
id: `${ namespace }/${ providerName.value }`,
|
|
||||||
opt: { force: true }
|
|
||||||
});
|
|
||||||
|
|
||||||
const conditions = refreshed?.status?.conditions || [];
|
|
||||||
const readyCondition = conditions.find((c) => c.type === 'Ready');
|
|
||||||
const connectionCondition = conditions.find((c) => c.type === 'ConnectionTestSucceeded');
|
|
||||||
|
|
||||||
if (connectionCondition) {
|
|
||||||
if (connectionCondition.status === 'True') {
|
|
||||||
connected = true;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
errorMsg = connectionCondition.message || t('harvester.addons.vmMigration.errors.connectionFailed');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (readyCondition) {
|
|
||||||
if (readyCondition.status === 'True') {
|
|
||||||
connected = true;
|
|
||||||
break;
|
|
||||||
} else if (readyCondition.status === 'False') {
|
|
||||||
errorMsg = readyCondition.message || t('harvester.addons.vmMigration.errors.providerNotReady');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connected) {
|
|
||||||
testPassed.value = true;
|
|
||||||
testResult.value = t('harvester.addons.vmMigration.configureProvider.testSuccess');
|
|
||||||
testing.value = false;
|
|
||||||
buttonCb(true);
|
|
||||||
} else {
|
|
||||||
testError.value = errorMsg || t('harvester.addons.vmMigration.configureProvider.testTimeout');
|
|
||||||
testing.value = false;
|
|
||||||
buttonCb(false);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
testError.value = err.message || t('harvester.addons.vmMigration.configureProvider.testFailed');
|
testError.value = err.message || t('harvester.addons.vmMigration.configureProvider.testFailed');
|
||||||
testing.value = false;
|
testing.value = false;
|
||||||
@ -292,57 +317,7 @@ const testConnection = async(buttonCb) => {
|
|||||||
// For existing providers, just poll for Ready/ConnectionTestSucceeded status
|
// For existing providers, just poll for Ready/ConnectionTestSucceeded status
|
||||||
if (isExistingProvider.value) {
|
if (isExistingProvider.value) {
|
||||||
try {
|
try {
|
||||||
const namespace = FORKLIFT_NAMESPACE;
|
handlePollResult(await pollProviderReady(providerName.value), buttonCb);
|
||||||
const maxAttempts = 15;
|
|
||||||
let attempts = 0;
|
|
||||||
let connected = false;
|
|
||||||
let errorMsg = '';
|
|
||||||
|
|
||||||
while (attempts < maxAttempts) {
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
||||||
attempts++;
|
|
||||||
|
|
||||||
const refreshed = await store.dispatch(`${ inStore }/find`, {
|
|
||||||
type: HCI.FORKLIFT_PROVIDER,
|
|
||||||
id: `${ namespace }/${ providerName.value }`,
|
|
||||||
opt: { force: true }
|
|
||||||
});
|
|
||||||
|
|
||||||
const conditions = refreshed?.status?.conditions || [];
|
|
||||||
const readyCondition = conditions.find((c) => c.type === 'Ready');
|
|
||||||
const connectionCondition = conditions.find((c) => c.type === 'ConnectionTestSucceeded');
|
|
||||||
|
|
||||||
if (connectionCondition) {
|
|
||||||
if (connectionCondition.status === 'True') {
|
|
||||||
connected = true;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
errorMsg = connectionCondition.message || t('harvester.addons.vmMigration.errors.connectionFailed');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (readyCondition) {
|
|
||||||
if (readyCondition.status === 'True') {
|
|
||||||
connected = true;
|
|
||||||
break;
|
|
||||||
} else if (readyCondition.status === 'False') {
|
|
||||||
errorMsg = readyCondition.message || t('harvester.addons.vmMigration.errors.providerNotReady');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connected) {
|
|
||||||
testPassed.value = true;
|
|
||||||
testResult.value = t('harvester.addons.vmMigration.configureProvider.testSuccess');
|
|
||||||
testing.value = false;
|
|
||||||
buttonCb(true);
|
|
||||||
} else {
|
|
||||||
testError.value = errorMsg || t('harvester.addons.vmMigration.configureProvider.testTimeout');
|
|
||||||
testing.value = false;
|
|
||||||
buttonCb(false);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
testError.value = err.message || t('harvester.addons.vmMigration.configureProvider.testFailed');
|
testError.value = err.message || t('harvester.addons.vmMigration.configureProvider.testFailed');
|
||||||
testing.value = false;
|
testing.value = false;
|
||||||
@ -354,20 +329,11 @@ const testConnection = async(buttonCb) => {
|
|||||||
|
|
||||||
// For new providers, create provider + secret then poll
|
// For new providers, create provider + secret then poll
|
||||||
try {
|
try {
|
||||||
// Delete previous provider (cascades to secret via ownerReferences)
|
await cleanupCreatedResources();
|
||||||
if (createdProvider.value) {
|
|
||||||
await createdProvider.value.remove();
|
|
||||||
createdProvider.value = null;
|
|
||||||
createdSecret.value = null;
|
|
||||||
} else if (createdSecret.value) {
|
|
||||||
await createdSecret.value.remove();
|
|
||||||
createdSecret.value = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const namespace = FORKLIFT_NAMESPACE;
|
const namespace = FORKLIFT_NAMESPACE;
|
||||||
const secretName = `${ providerName.value }-creds-${ randomStr(4).toLowerCase() }`;
|
const secretName = `${ providerName.value }-creds-${ randomStr(4).toLowerCase() }`;
|
||||||
|
|
||||||
// Create Provider first so we have its UID for the ownerReference on the Secret
|
|
||||||
const provider = await store.dispatch(`${ inStore }/create`, {
|
const provider = await store.dispatch(`${ inStore }/create`, {
|
||||||
type: HCI.FORKLIFT_PROVIDER,
|
type: HCI.FORKLIFT_PROVIDER,
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -387,7 +353,6 @@ const testConnection = async(buttonCb) => {
|
|||||||
await provider.save();
|
await provider.save();
|
||||||
createdProvider.value = provider;
|
createdProvider.value = provider;
|
||||||
|
|
||||||
// Create Secret with ownerReference already set (avoids an extra PUT)
|
|
||||||
const newSecret = await store.dispatch(`${ inStore }/create`, {
|
const newSecret = await store.dispatch(`${ inStore }/create`, {
|
||||||
type: SECRET,
|
type: SECRET,
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -417,79 +382,15 @@ const testConnection = async(buttonCb) => {
|
|||||||
await newSecret.save();
|
await newSecret.save();
|
||||||
createdSecret.value = newSecret;
|
createdSecret.value = newSecret;
|
||||||
|
|
||||||
const maxAttempts = 15;
|
const result = await pollProviderReady(providerName.value);
|
||||||
let attempts = 0;
|
|
||||||
let connected = false;
|
|
||||||
let errorMsg = '';
|
|
||||||
|
|
||||||
while (attempts < maxAttempts) {
|
if (!result.connected) {
|
||||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
await cleanupCreatedResources();
|
||||||
attempts++;
|
|
||||||
|
|
||||||
const refreshed = await store.dispatch(`${ inStore }/find`, {
|
|
||||||
type: HCI.FORKLIFT_PROVIDER,
|
|
||||||
id: `${ namespace }/${ providerName.value }`,
|
|
||||||
opt: { force: true }
|
|
||||||
});
|
|
||||||
|
|
||||||
const conditions = refreshed?.status?.conditions || [];
|
|
||||||
const readyCondition = conditions.find((c) => c.type === 'Ready');
|
|
||||||
const connectionCondition = conditions.find((c) => c.type === 'ConnectionTestSucceeded');
|
|
||||||
|
|
||||||
if (connectionCondition) {
|
|
||||||
if (connectionCondition.status === 'True') {
|
|
||||||
connected = true;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
errorMsg = connectionCondition.message || t('harvester.addons.vmMigration.errors.connectionFailed');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readyCondition) {
|
handlePollResult(result, buttonCb);
|
||||||
if (readyCondition.status === 'True') {
|
|
||||||
connected = true;
|
|
||||||
break;
|
|
||||||
} else if (readyCondition.status === 'False') {
|
|
||||||
errorMsg = readyCondition.message || t('harvester.addons.vmMigration.errors.providerNotReady');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connected) {
|
|
||||||
testPassed.value = true;
|
|
||||||
testResult.value = t('harvester.addons.vmMigration.configureProvider.testSuccess');
|
|
||||||
testing.value = false;
|
|
||||||
buttonCb(true);
|
|
||||||
} else {
|
|
||||||
if (createdProvider.value) {
|
|
||||||
await createdProvider.value.remove();
|
|
||||||
createdProvider.value = null;
|
|
||||||
createdSecret.value = null;
|
|
||||||
} else if (createdSecret.value) {
|
|
||||||
await createdSecret.value.remove();
|
|
||||||
createdSecret.value = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
testError.value = errorMsg || t('harvester.addons.vmMigration.configureProvider.testTimeout');
|
|
||||||
testing.value = false;
|
|
||||||
buttonCb(false);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (createdProvider.value) {
|
await cleanupCreatedResources();
|
||||||
try {
|
|
||||||
await createdProvider.value.remove();
|
|
||||||
} catch (e) {}
|
|
||||||
createdProvider.value = null;
|
|
||||||
}
|
|
||||||
if (createdSecret.value) {
|
|
||||||
try {
|
|
||||||
await createdSecret.value.remove();
|
|
||||||
} catch (e) {}
|
|
||||||
createdSecret.value = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
testError.value = err.message || t('harvester.addons.vmMigration.configureProvider.testFailed');
|
testError.value = err.message || t('harvester.addons.vmMigration.configureProvider.testFailed');
|
||||||
testing.value = false;
|
testing.value = false;
|
||||||
buttonCb(false);
|
buttonCb(false);
|
||||||
|
|||||||
@ -15,8 +15,6 @@ const props = defineProps({
|
|||||||
providerName: { type: String, default: '' },
|
providerName: { type: String, default: '' },
|
||||||
provider: { type: Object, default: null },
|
provider: { type: Object, default: null },
|
||||||
selectedVms: { type: Array, default: () => [] },
|
selectedVms: { type: Array, default: () => [] },
|
||||||
networkMapName: { type: String, default: '' },
|
|
||||||
storageMapName: { type: String, default: '' },
|
|
||||||
mappingEntries: { type: Object, default: null },
|
mappingEntries: { type: Object, default: null },
|
||||||
stepData: { type: Object, required: true },
|
stepData: { type: Object, required: true },
|
||||||
});
|
});
|
||||||
|
|||||||
@ -406,8 +406,7 @@ init();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Loading v-if="refreshing" />
|
<Loading v-if="loading || refreshing" />
|
||||||
<Loading v-if="loading" />
|
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="select-vms-step"
|
class="select-vms-step"
|
||||||
|
|||||||
@ -1821,6 +1821,7 @@ harvester:
|
|||||||
failedLoadVms: Failed to load virtual machines
|
failedLoadVms: Failed to load virtual machines
|
||||||
failedRefreshVms: Failed to refresh virtual machines
|
failedRefreshVms: Failed to refresh virtual machines
|
||||||
failedLoadProviders: Failed to load providers
|
failedLoadProviders: Failed to load providers
|
||||||
|
failedLoadProvider: "Failed to load provider: {error}"
|
||||||
failedResolveDetails: Failed to resolve network and datastore details
|
failedResolveDetails: Failed to resolve network and datastore details
|
||||||
failedDecodeCredentials: Failed to decode provider credentials
|
failedDecodeCredentials: Failed to decode provider credentials
|
||||||
connectionFailed: Connection failed
|
connectionFailed: Connection failed
|
||||||
@ -1921,6 +1922,10 @@ harvester:
|
|||||||
failed: Failed
|
failed: Failed
|
||||||
migration: Migration
|
migration: Migration
|
||||||
initializingMigration: Initializing migration
|
initializingMigration: Initializing migration
|
||||||
|
finishedSuccessfully: Finished Successfully
|
||||||
|
step: "Step {index}"
|
||||||
|
vmCount: "{count} VMs"
|
||||||
|
vmId: "id: {id}"
|
||||||
configureMappings:
|
configureMappings:
|
||||||
title: Set Mappings
|
title: Set Mappings
|
||||||
description: Map VMware networks and datastores to Harvester and Longhorn target resources
|
description: Map VMware networks and datastores to Harvester and Longhorn target resources
|
||||||
|
|||||||
@ -69,17 +69,17 @@ const rows = computed(() => {
|
|||||||
overallProgress += (stepPct / 100) * stepWeight;
|
overallProgress += (stepPct / 100) * stepWeight;
|
||||||
|
|
||||||
if (!currentStep) {
|
if (!currentStep) {
|
||||||
currentStep = step.name || `Step ${ idx + 1 }`;
|
currentStep = step.name || t('harvester.addons.vmMigration.dashboard.progress.step', { index: idx + 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step.error && !errorMsg) {
|
if (step.error && !errorMsg) {
|
||||||
const reasons = (step.error.reasons || []).join('; ') || t('harvester.addons.vmMigration.plan.states.error');
|
const reasons = (step.error.reasons || []).join('; ') || t('harvester.addons.vmMigration.plan.states.error');
|
||||||
|
|
||||||
errorMsg = `${ step.name || `Step ${ idx + 1 }` }: ${ reasons }`;
|
errorMsg = `${ step.name || t('harvester.addons.vmMigration.dashboard.progress.step', { index: idx + 1 }) }: ${ reasons }`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step.phase === 'Failed' && !errorMsg) {
|
if (step.phase === 'Failed' && !errorMsg) {
|
||||||
errorMsg = `${ step.name || `Step ${ idx + 1 }` }: ${ t('harvester.addons.vmMigration.dashboard.progress.failed') }`;
|
errorMsg = `${ step.name || t('harvester.addons.vmMigration.dashboard.progress.step', { index: idx + 1 }) }: ${ t('harvester.addons.vmMigration.dashboard.progress.failed') }`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -215,7 +215,7 @@ init();
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #cell:vmCount="{ row }">
|
<template #cell:vmCount="{ row }">
|
||||||
{{ (row.spec.vms || []).length }} VMs
|
{{ t('harvester.addons.vmMigration.dashboard.progress.vmCount', { count: (row.spec.vms || []).length }) }}
|
||||||
</template>
|
</template>
|
||||||
<template #cell:progress="{ row }">
|
<template #cell:progress="{ row }">
|
||||||
<div
|
<div
|
||||||
@ -230,7 +230,7 @@ init();
|
|||||||
<div class="vm-progress-header">
|
<div class="vm-progress-header">
|
||||||
<div class="vm-name-block">
|
<div class="vm-name-block">
|
||||||
<span class="vm-name">{{ vm.vmName }}</span>
|
<span class="vm-name">{{ vm.vmName }}</span>
|
||||||
<span class="text-muted vm-id">id: {{ vm.vmId }}</span>
|
<span class="text-muted vm-id">{{ t('harvester.addons.vmMigration.dashboard.progress.vmId', { id: vm.vmId }) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="vm-pct-block">
|
<div class="vm-pct-block">
|
||||||
@ -246,7 +246,7 @@ init();
|
|||||||
v-if="vm.progress >= 100"
|
v-if="vm.progress >= 100"
|
||||||
class="step-label text-muted"
|
class="step-label text-muted"
|
||||||
>
|
>
|
||||||
Finished Successfully
|
{{ t('harvester.addons.vmMigration.dashboard.progress.finishedSuccessfully') }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else-if="vm.errorMsg"
|
v-else-if="vm.errorMsg"
|
||||||
@ -258,7 +258,7 @@ init();
|
|||||||
v-else-if="vm.canceled"
|
v-else-if="vm.canceled"
|
||||||
class="step-label text-muted"
|
class="step-label text-muted"
|
||||||
>
|
>
|
||||||
Canceled
|
{{ t('harvester.addons.vmMigration.plan.states.canceled') }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else-if="vm.currentStep"
|
v-else-if="vm.currentStep"
|
||||||
|
|||||||
@ -203,13 +203,17 @@ const init = async() => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (secret?.data) {
|
if (secret?.data) {
|
||||||
|
const decode = (val) => {
|
||||||
try {
|
try {
|
||||||
stepData.provider.username = atob(secret.data.user || '');
|
return atob(val || '');
|
||||||
stepData.provider.password = atob(secret.data.password || '');
|
|
||||||
stepData.provider.skipTlsVerify = atob(secret.data.insecureSkipVerify || '') === 'true';
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors.value = [t('harvester.addons.vmMigration.errors.failedDecodeCredentials')];
|
return '';
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
stepData.provider.username = decode(secret.data.user);
|
||||||
|
stepData.provider.password = decode(secret.data.password);
|
||||||
|
stepData.provider.skipTlsVerify = decode(secret.data.insecureSkipVerify) === 'true';
|
||||||
stepData.provider.createdSecret = secret;
|
stepData.provider.createdSecret = secret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,7 +234,7 @@ const init = async() => {
|
|||||||
// Maps may not exist yet
|
// Maps may not exist yet
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errors.value = [`Failed to load provider: ${ err.message || err }`];
|
errors.value = [t('harvester.addons.vmMigration.errors.failedLoadProvider', { error: err.message || err })];
|
||||||
}
|
}
|
||||||
|
|
||||||
initialLoading.value = false;
|
initialLoading.value = false;
|
||||||
|
|||||||
@ -15,14 +15,11 @@ const { t } = useI18n(store);
|
|||||||
|
|
||||||
const cruRef = ref(null);
|
const cruRef = ref(null);
|
||||||
const providerStepRef = ref(null);
|
const providerStepRef = ref(null);
|
||||||
const mappingsStepRef = ref(null);
|
|
||||||
const reviewStepRef = ref(null);
|
const reviewStepRef = ref(null);
|
||||||
|
|
||||||
const providerName = ref('');
|
const providerName = ref('');
|
||||||
const provider = ref(null);
|
const provider = ref(null);
|
||||||
const selectedVMs = ref([]);
|
const selectedVMs = ref([]);
|
||||||
const networkMapName = ref('');
|
|
||||||
const storageMapName = ref('');
|
|
||||||
const errors = ref([]);
|
const errors = ref([]);
|
||||||
|
|
||||||
const providerReady = ref(false);
|
const providerReady = ref(false);
|
||||||
@ -263,7 +260,6 @@ const onCancel = () => {
|
|||||||
</template>
|
</template>
|
||||||
<template #configure-mappings>
|
<template #configure-mappings>
|
||||||
<ConfigureMappingsStep
|
<ConfigureMappingsStep
|
||||||
ref="mappingsStepRef"
|
|
||||||
:provider-name="providerName"
|
:provider-name="providerName"
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:selected-vms="selectedVMs"
|
:selected-vms="selectedVMs"
|
||||||
@ -277,8 +273,6 @@ const onCancel = () => {
|
|||||||
:provider-name="providerName"
|
:provider-name="providerName"
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:selected-vms="selectedVMs"
|
:selected-vms="selectedVMs"
|
||||||
:network-map-name="networkMapName"
|
|
||||||
:storage-map-name="storageMapName"
|
|
||||||
:mapping-entries="stepData.mappings"
|
:mapping-entries="stepData.mappings"
|
||||||
:step-data="stepData.review"
|
:step-data="stepData.review"
|
||||||
@ready="onReviewReady"
|
@ready="onReviewReady"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user