feat: use the SUSE Virtualization product name on Prime (#1202)

* feat: switch the product name with Rancher Prime

Use a [[Harvester]] token for the product name in the translations, so
Rancher 2.16 fills it from the l10n global that harvester-manager
registers: SUSE Virtualization on Rancher Prime, Harvester otherwise.

Rancher before 2.16 shows the tokens as written, so on those hosts (and
standalone) the extension resolves them to Harvester itself.

Signed-off-by: Marcelo Fukumoto <marcelo.fukumoto@suse.com>

* feat: switch the standalone product name with the server flavor

Standalone has no Rancher Prime, so register the [[Harvester]] l10n
global from the server-flavor setting instead: SUSE Virtualization on
prime, Harvester otherwise.

Signed-off-by: Marcelo Fukumoto <marcelo.fukumoto@suse.com>

* fix: point the network policy banner to the documentation

Signed-off-by: Marcelo Fukumoto <marcelo.fukumoto@suse.com>

* feat: use the SUSE theme in standalone Prime

Standalone Prime kept the harvester brand and only overrode the primary
colour, so the rest of the palette and the fonts didn't match Rancher
Prime. Switch the ui-brand setting to suse in the store when the server
flavor is prime, which makes the shell load the SUSE theme.

Signed-off-by: Marcelo Fukumoto <marcelo.fukumoto@suse.com>

* fix: keep the SUSE theme after a brand setting change event

The watcher also reads the setting's value, so a change from the server
loaded into the same object switches the brand back to suse.

Signed-off-by: Marcelo Fukumoto <marcelo.fukumoto@suse.com>

---------

Signed-off-by: Marcelo Fukumoto <marcelo.fukumoto@suse.com>
This commit is contained in:
marcelofukumoto
2026-10-26 17:28:50 +01:00
committed by GitHub
parent d6f6f7c54c
commit 6e0e0237ef
7 changed files with 315 additions and 76 deletions
+17 -20
View File
@@ -57,10 +57,12 @@ import {
} from './table-headers'; } from './table-headers';
import { ADD_ONS } from './harvester-map'; import { ADD_ONS } from './harvester-map';
import { registerAddonSideNav } from '../utils/dynamic-nav'; import { registerAddonSideNav } from '../utils/dynamic-nav';
import { setStandalonePrime } from '../utils/l10n-globals';
import { setVendor } from '@shell/config/private-label'; import { setVendor } from '@shell/config/private-label';
import { createCssVars } from '@shell/utils/color';
import { CONFIGURABLE_TABLES } from '@shell/store/features'; import { CONFIGURABLE_TABLES } from '@shell/store/features';
import { tableViewsOffFeature } from '../utils/table-views'; import { tableViewsOffFeature } from '../utils/table-views';
import { SETTING } from '@shell/config/settings';
import { primeBrandUpdater } from '../utils/prime-brand';
const TEMPLATE = HCI.VM_VERSION; const TEMPLATE = HCI.VM_VERSION;
const MONITORING_GROUP = 'Monitoring & Logging::Monitoring'; const MONITORING_GROUP = 'Monitoring & Logging::Monitoring';
@@ -123,27 +125,9 @@ export function init($plugin, store) {
const [isHarvesterPrime, isDark, privateLabel] = JSON.parse(value); const [isHarvesterPrime, isDark, privateLabel] = JSON.parse(value);
const primeLogo = isDark ? require('../assets/images/dark/suse-virtualization.svg') : require('../assets/images/suse-virtualization.svg'); const primeLogo = isDark ? require('../assets/images/dark/suse-virtualization.svg') : require('../assets/images/suse-virtualization.svg');
setStandalonePrime(isHarvesterPrime);
setVendor(privateLabel || ''); setVendor(privateLabel || '');
let primaryColorStyle = document.getElementById('harvester-prime-primary-color');
// set harvester prime primary color style to #4dd192 (Cyan Green)
if (isHarvesterPrime) {
if (!primaryColorStyle) {
primaryColorStyle = document.createElement('style');
primaryColorStyle.id = 'harvester-prime-primary-color';
document.head.appendChild(primaryColorStyle);
primaryColorStyle.sheet.insertRule('body.theme-light, body.theme-dark {}', 0);
}
const colors = createCssVars('#4dd192', isDark ? 'dark' : 'light');
const rule = primaryColorStyle.sheet.cssRules[0];
Object.entries(colors).forEach(([property, color]) => rule.style.setProperty(property.trim(), color));
} else {
primaryColorStyle?.remove();
}
const primeLabelKey = privateLabel ? 'harvester.branding.primeLabel' : 'harvester.branding.primeEmptyLabel'; const primeLabelKey = privateLabel ? 'harvester.branding.primeLabel' : 'harvester.branding.primeEmptyLabel';
store.dispatch('setIsSingleProduct', { store.dispatch('setIsSingleProduct', {
@@ -169,6 +153,19 @@ export function init($plugin, store) {
}, },
{ immediate: true } { immediate: true }
); );
const updateBrand = primeBrandUpdater();
// The value is read too: a change event from the server is loaded into the same setting object
store.watch(
(_state, getters) => {
const brandSetting = getters['management/byId'](MANAGEMENT.SETTING, SETTING.BRAND);
return [!!getters['harvester-common/isHarvesterPrime'], brandSetting, brandSetting?.value];
},
([isHarvesterPrime, brandSetting]) => updateBrand(brandSetting, isHarvesterPrime),
{ immediate: true }
);
} }
product({ product({
+12
View File
@@ -6,6 +6,9 @@ import harvesterCommonStore from './store/harvester-common';
import harvesterStore from './store/harvester-store'; import harvesterStore from './store/harvester-store';
import customValidators from './validators'; import customValidators from './validators';
import { PRODUCT_NAME } from './config/harvester'; import { PRODUCT_NAME } from './config/harvester';
import {
hostResolvesL10nGlobals, resolveL10nGlobals, standaloneProductName, PRODUCT_NAME_GLOBAL
} from './utils/l10n-globals';
import { defineAsyncComponent } from 'vue'; import { defineAsyncComponent } from 'vue';
import './styles/vue-flow.scss'; import './styles/vue-flow.scss';
@@ -17,6 +20,15 @@ export default function (plugin: IPlugin) {
// Auto-import model, detail, edit from the folders // Auto-import model, detail, edit from the folders
importTypes(plugin); importTypes(plugin);
if (isSingleVirtualCluster) {
// Standalone: the server-flavor setting picks the product name, see config/harvester-cluster
plugin.register('l10n-global', PRODUCT_NAME_GLOBAL, standaloneProductName);
} else if (!hostResolvesL10nGlobals(plugin.environment?.version)) {
// Hosts older than Rancher 2.16 would show `[[Harvester]]` literally, so resolve the tokens here.
// Mutating the module in place also updates the copy that importTypes registered.
resolveL10nGlobals(require('./l10n/en-us.yaml'));
}
// Provide plugin metadata from package.json // Provide plugin metadata from package.json
plugin.metadata = require('./package.json'); plugin.metadata = require('./package.json');
+56 -56
View File
@@ -25,8 +25,8 @@ generic:
unsupported: unsupported:
serverVersion: 'Current version: <code>{serverVersion}</code>' serverVersion: 'Current version: <code>{serverVersion}</code>'
description: Harvester ui only supports Harvester cluster version greater or equal to 1.3.0. description: '[[Harvester]] ui only supports [[Harvester]] cluster version greater or equal to 1.3.0.'
learnMore: Learn more about Harvester from the <a target="_blank" href="https://harvesterhci.io/" rel="noopener noreferrer nofollow">Harvester Web Site</a> or read the <a target="_blank" href="https://docs.harvesterhci.io/" rel="noopener noreferrer nofollow">Harvester Docs</a> learnMore: Learn more about [[Harvester]] from the <a target="_blank" href="https://harvesterhci.io/" rel="noopener noreferrer nofollow">[[Harvester]] Web Site</a> or read the <a target="_blank" href="https://docs.harvesterhci.io/" rel="noopener noreferrer nofollow">[[Harvester]] Docs</a>
nav: nav:
group: group:
@@ -87,10 +87,10 @@ harvester:
primeLabel: '{vendor}' primeLabel: '{vendor}'
primeEmptyLabel: '' primeEmptyLabel: ''
logos: logos:
tip: 'Upload a logo to replace the Harvester logo in the top-level navigation header. Image height should be 21 pixels with a max width of 200 pixels. Max file size is 20KB. Accepted formats: JPEG, PNG, SVG.' tip: 'Upload a logo to replace the [[Harvester]] logo in the top-level navigation header. Image height should be 21 pixels with a max width of 200 pixels. Max file size is 20KB. Accepted formats: JPEG, PNG, SVG.'
favicon: favicon:
tip: 'Upload an icon to replace the Harvester favicon in the browser tab. Max file size is 20KB' tip: 'Upload an icon to replace the [[Harvester]] favicon in the browser tab. Max file size is 20KB'
productLabel: 'Harvester' productLabel: '[[Harvester]]'
modal: modal:
backup: backup:
success: 'Backup { backUpName } has been initiated.' success: 'Backup { backUpName } has been initiated.'
@@ -182,7 +182,7 @@ harvester:
delete: Delete delete: Delete
bundle: bundle:
title: Generate a Support Bundle title: Generate a Support Bundle
titleDescription: Collect system-related logs in Harvester to assist with troubleshooting and support. titleDescription: Collect system-related logs in [[Harvester]] to assist with troubleshooting and support.
tip: Each field below specifies an aspect of the support bundle. For detailed explanations, please refer to the <a href="{doc}" target="_blank">documentation</a>. tip: Each field below specifies an aspect of the support bundle. For detailed explanations, please refer to the <a href="{doc}" target="_blank">documentation</a>.
url: Issue URL url: Issue URL
description: Description description: Description
@@ -336,7 +336,7 @@ harvester:
attachedVM: Attached Virtual Machine attachedVM: Attached Virtual Machine
cpuManager: CPU<br>Manager cpuManager: CPU<br>Manager
diskState: Disk diskState: Disk
routeConnectivityTooltip: Connectivity between the VM network and the management network, which the Harvester nodes are connected to. routeConnectivityTooltip: Connectivity between the VM network and the management network, which the [[Harvester]] nodes are connected to.
fingerprint: Fingerprint fingerprint: Fingerprint
value: Value value: Value
actions: Actions actions: Actions
@@ -501,7 +501,7 @@ harvester:
aclEmptyError: The fields in subnet access control list rule can not be empty. aclEmptyError: The fields in subnet access control list rule can not be empty.
dashboard: dashboard:
label: Dashboard label: Dashboard
header: "Harvester Cluster: {cluster}" header: "[[Harvester]] Cluster: {cluster}"
hardwareResourceGauge: hardwareResourceGauge:
cpu: CPU cpu: CPU
memory: Memory memory: Memory
@@ -839,7 +839,7 @@ harvester:
collapse: Hide VM-wide high-performance options collapse: Hide VM-wide high-performance options
blockMultiQueue: blockMultiQueue:
label: Virtio Block Multi-Queue label: Virtio Block Multi-Queue
tip: Map disk I/O to multiple queues so it is processed across multiple CPUs. Applies to virtio disks and requires a fixed CPU allocation (Harvester always sets one). tip: Map disk I/O to multiple queues so it is processed across multiple CPUs. Applies to virtio disks and requires a fixed CPU allocation ([[Harvester]] always sets one).
noVirtioTip: Add at least one disk on the virtio bus to enable Block Multi-Queue. noVirtioTip: Add at least one disk on the virtio bus to enable Block Multi-Queue.
ioThreadsPolicy: ioThreadsPolicy:
label: I/O Threads Policy label: I/O Threads Policy
@@ -939,7 +939,7 @@ harvester:
displayNamePlaceholder: Virtual machine alias name displayNamePlaceholder: Virtual machine alias name
displayName: Display Name displayName: Display Name
filesystem: filesystem:
description: Harvester supports filesystem volumes for VM via virtiofs. description: '[[Harvester]] supports filesystem volumes for VM via virtiofs.'
type: Filesystem Type type: Filesystem Type
volume: Volume volume: Volume
resource: Resource resource: Resource
@@ -1193,8 +1193,8 @@ harvester:
selectExisting: Select Existing Image selectExisting: Select Existing Image
createRepository: Creating Upgrade Repository createRepository: Creating Upgrade Repository
succeeded: Succeeded succeeded: Succeeded
releaseTip: Please read the upgrade documentation carefully. You can view details on the <a href="{url}" target="_blank">Harvester Release Notes</a>. releaseTip: Please read the upgrade documentation carefully. You can view details on the <a href="{url}" target="_blank">[[Harvester]] Release Notes</a>.
checkReady: I have read and understood the upgrade instructions related to this Harvester version. checkReady: I have read and understood the upgrade instructions related to this [[Harvester]] version.
pending: Pending pending: Pending
upload: upload:
duplicatedFile: The file you are trying to upload already exists. duplicatedFile: The file you are trying to upload already exists.
@@ -1203,7 +1203,7 @@ harvester:
os: OS os: OS
kubernetes: Kubernetes kubernetes: Kubernetes
monitoringChart: Monitoring Chart monitoringChart: Monitoring Chart
harvesterChart: Harvester Chart harvesterChart: '[[Harvester]] Chart'
success: Success success: Success
fail: Fail fail: Fail
ongoing: On-going ongoing: On-going
@@ -1243,7 +1243,7 @@ harvester:
maxFailure: maxFailure:
label: Max Failure label: Max Failure
count: Count count: Count
tooltip: Max number of consecutive failed backups that could be tolerated. If reach this threshold, Harvester controller will suspend the schedule job. This value should less than retain count tooltip: Max number of consecutive failed backups that could be tolerated. If reach this threshold, [[Harvester]] controller will suspend the schedule job. This value should less than retain count
virtualMachine: virtualMachine:
title: Virtual Machine Name title: Virtual Machine Name
placeholder: Select a virtual machine placeholder: Select a virtual machine
@@ -1257,7 +1257,7 @@ harvester:
title: Restore Virtual Machine title: Restore Virtual Machine
refreshInterval: refreshInterval:
label: Refresh Interval label: Refresh Interval
tip: The interval for the backup target to sync data to harvester cluster. Set to 0 to disable refresh mechanism. tip: The interval for the backup target to sync data to [[Harvester]] cluster. Set to 0 to disable refresh mechanism.
backupTargetTip: The endpoint used to access the backupstore. NFS and S3 are supported. backupTargetTip: The endpoint used to access the backupstore. NFS and S3 are supported.
message: message:
noSetting: noSetting:
@@ -1276,7 +1276,7 @@ harvester:
actionLabel: Test connection actionLabel: Test connection
waitingLabel: Testing connection... waitingLabel: Testing connection...
successLabel: Connection tested successLabel: Connection tested
successMessage: 'Harvester can successfully connect to the endpoint {endpoint}' successMessage: '[[Harvester]] can successfully connect to the endpoint {endpoint}'
restore: restore:
backup: Backup backup: Backup
deletePreviousVolumes: Delete Previous Volumes deletePreviousVolumes: Delete Previous Volumes
@@ -1487,7 +1487,7 @@ harvester:
placeholder: Select a provider network placeholder: Select a provider network
networkPolicy: networkPolicy:
label: Policies label: Policies
banner: The network policies must be used for VMs attached to overlay networks. Please read the <a href="{url}" target="_blank">harvester document</a> how the network policy works. banner: The network policies must be used for VMs attached to overlay networks. Please read the <a href="{url}" target="_blank">[[Harvester]] documentation</a> on how network policies work.
network: network:
label: Virtual Machine Networks label: Virtual Machine Networks
tabs: tabs:
@@ -1596,7 +1596,7 @@ harvester:
autoRotateRKE2Certs: autoRotateRKE2Certs:
expiringInHours: Expiring in expiringInHours: Expiring in
httpProxy: httpProxy:
warning: 'WARNING: <br/> If you configure "http-proxy" and "https-proxy", you must also put Harvester node&apos;s CIDR into "no-proxy", otherwise the Harvester cluster will be broken.' warning: 'WARNING: <br/> If you configure "http-proxy" and "https-proxy", you must also put [[Harvester]] node&apos;s CIDR into "no-proxy", otherwise the [[Harvester]] cluster will be broken.'
supportBundleImage: supportBundleImage:
imagePullPolicy: Pull Policy imagePullPolicy: Pull Policy
repo: Repository repo: Repository
@@ -1648,7 +1648,7 @@ harvester:
strategyType: Strategy Type strategyType: Strategy Type
concurrency: Concurrency concurrency: Concurrency
harvesterMonitoring: harvesterMonitoring:
label: Harvester Monitoring label: '[[Harvester]] Monitoring'
section: section:
prometheus: Prometheus prometheus: Prometheus
prometheusNodeExporter: Prometheus Node Exporter prometheusNodeExporter: Prometheus Node Exporter
@@ -1663,10 +1663,10 @@ harvester:
url: URL url: URL
insecureSkipTLSVerify: Insecure Skip TLS Verify insecureSkipTLSVerify: Insecure Skip TLS Verify
tip: tip:
prefix: Harvester secures cluster registration via TLS by default. If opt out "Insecure Skip TLS Verify", you must provide custom CA certificates using the prefix: '[[Harvester]] secures cluster registration via TLS by default. If opt out "Insecure Skip TLS Verify", you must provide custom CA certificates using the'
middle: 'additional-ca' middle: 'additional-ca'
suffix: setting. suffix: setting.
message: To completely unset the imported Harvester cluster, please also remove it on the Rancher Dashboard UI via the <code> Virtualization Management </code> page. message: To completely unset the imported [[Harvester]] cluster, please also remove it on the Rancher Dashboard UI via the <code> Virtualization Management </code> page.
ntpServers: ntpServers:
isNotIPV4: The address you entered is not IPv4 or host. Please enter a valid IPv4 address or a host address. isNotIPV4: The address you entered is not IPv4 or host. Please enter a valid IPv4 address or a host address.
isDuplicate: There are duplicate NTP server configurations. isDuplicate: There are duplicate NTP server configurations.
@@ -1696,19 +1696,19 @@ harvester:
networkData: Network Data networkData: Network Data
support: support:
title: Harvester Support title: '[[Harvester]] Support'
kubeconfig: kubeconfig:
title: Download KubeConfig title: Download KubeConfig
titleDescription: Download kubeconfig for debugging. titleDescription: Download kubeconfig for debugging.
internal: internal:
rancher: rancher:
title: Access Embedded Rancher UI title: Access Embedded Rancher UI
titleDescription: You can only use the embedded Rancher UI for debugging and validation purposes. For more information about how Harvester integrates with Rancher, see the <a target="_blank" href="{url}" rel="noopener noreferrer nofollow">documentation</a>. titleDescription: You can only use the embedded Rancher UI for debugging and validation purposes. For more information about how [[Harvester]] integrates with Rancher, see the <a target="_blank" href="{url}" rel="noopener noreferrer nofollow">documentation</a>.
longhorn: longhorn:
title: Access Embedded Longhorn UI title: Access Embedded Longhorn UI
titleDescription: We only support to use the embedded Longhorn UI for debugging and validation purpose. titleDescription: We only support to use the embedded Longhorn UI for debugging and validation purpose.
community: community:
learnMore: Find out more about SUSE Harvester support learnMore: Find out more about [[Harvester]] support
pricing: Contact us for pricing pricing: Contact us for pricing
namespace: namespace:
@@ -1928,16 +1928,16 @@ harvester:
addons: addons:
descriptions: descriptions:
'harvester-system/vm-import-controller': vm-import-controller is an add-on to help migrate virtual machine workloads from other source clusters to an existing Harvester cluster. 'harvester-system/vm-import-controller': vm-import-controller is an add-on to help migrate virtual machine workloads from other source clusters to an existing [[Harvester]] cluster.
'harvester-system/pcidevices-controller': pcidevices-controller is an add-on to help discover PCI devices for nodes in your cluster and allow users to prepare devices for PCI Passthrough, for use with Harvester virtual machine and guest clusters. 'harvester-system/pcidevices-controller': pcidevices-controller is an add-on to help discover PCI devices for nodes in your cluster and allow users to prepare devices for PCI Passthrough, for use with [[Harvester]] virtual machine and guest clusters.
'cattle-logging-system/rancher-logging': rancher-logging is an add-on to collect versatile logs, events, and audits from the Harvester cluster and route them to many kinds of servers based on flows. 'cattle-logging-system/rancher-logging': rancher-logging is an add-on to collect versatile logs, events, and audits from the [[Harvester]] cluster and route them to many kinds of servers based on flows.
'harvester-system/rancher-vcluster': rancher-vcluster deploys a virtual cluster (vcluster) with Rancher installed. 'harvester-system/rancher-vcluster': rancher-vcluster deploys a virtual cluster (vcluster) with Rancher installed.
'cattle-monitoring-system/rancher-monitoring': rancher-monitoring is an add-on that collects Harvester cluster and virtual machine metrics and allows you to view the metrics on an embedded dashboard and send alert(s) to remote servers. 'cattle-monitoring-system/rancher-monitoring': rancher-monitoring is an add-on that collects [[Harvester]] cluster and virtual machine metrics and allows you to view the metrics on an embedded dashboard and send alert(s) to remote servers.
'vm-import-controller': vm-import-controller is an add-on to help migrate virtual machine workloads from other source clusters to an existing Harvester cluster. 'vm-import-controller': vm-import-controller is an add-on to help migrate virtual machine workloads from other source clusters to an existing [[Harvester]] cluster.
'pcidevices-controller': pcidevices-controller is an add-on to help discover PCI devices for nodes in your cluster and allow users to prepare devices for PCI Passthrough, for use with Harvester virtual machines and guest clusters. 'pcidevices-controller': pcidevices-controller is an add-on to help discover PCI devices for nodes in your cluster and allow users to prepare devices for PCI Passthrough, for use with [[Harvester]] virtual machines and guest clusters.
'nvidia-driver-toolkit': 'nvidia-driver-toolkit is an add-on to enable vGPU devices and assign them to Harvester virtual machines.' 'nvidia-driver-toolkit': 'nvidia-driver-toolkit is an add-on to enable vGPU devices and assign them to [[Harvester]] virtual machines.'
'rancher-logging': rancher-logging is an add-on to collect versatile logs, events, and audits from the Harvester cluster and route them to many kinds of servers based on flows. 'rancher-logging': rancher-logging is an add-on to collect versatile logs, events, and audits from the [[Harvester]] cluster and route them to many kinds of servers based on flows.
'rancher-monitoring': rancher-monitoring is an add-on to collect Harvester cluster and virtual machine metrics, view them on the embedded dashboard, and send alert(s) to remote servers. 'rancher-monitoring': rancher-monitoring is an add-on to collect [[Harvester]] cluster and virtual machine metrics, view them on the embedded dashboard, and send alert(s) to remote servers.
'rancher-vcluster': rancher-vcluster deploys a virtual cluster (vcluster) with Rancher installed. 'rancher-vcluster': rancher-vcluster deploys a virtual cluster (vcluster) with Rancher installed.
'k3k': k3k is an add-on to deploy the k3k controller. 'k3k': k3k is an add-on to deploy the k3k controller.
'rancher-k3k': rancher-k3k deploys a k3k virtual cluster with Rancher installed. 'rancher-k3k': rancher-k3k deploys a k3k virtual cluster with Rancher installed.
@@ -2006,7 +2006,7 @@ harvester:
providerSelect: Provider providerSelect: Provider
createNew: Create new provider createNew: Create new provider
requirementsTitle: Requirements requirementsTitle: Requirements
requirementsText: "To migrate virtual machines from VMware, you will need a vCenter Server running version 6.5 or higher with a user account that has at least read permissions, and the source environment must be network-accessible from Harvester Node." requirementsText: "To migrate virtual machines from VMware, you will need a vCenter Server running version 6.5 or higher with a user account that has at least read permissions, and the source environment must be network-accessible from [[Harvester]] Node."
name: Name name: Name
urlLabel: vCenter/ESXi URL urlLabel: vCenter/ESXi URL
urlPlaceholder: "https://vcenter.example.com/sdk" urlPlaceholder: "https://vcenter.example.com/sdk"
@@ -2059,7 +2059,7 @@ harvester:
datastore: Datastore datastore: Datastore
dashboard: dashboard:
title: Virtual Machine Migration Overview title: Virtual Machine Migration Overview
description: "Migrate virtual machines from VMware vSphere to Harvester using cold migration for data consistency. Create a migration plan to select VMs, map networks and storage, and prepare a migration to Harvester." description: "Migrate virtual machines from VMware vSphere to [[Harvester]] using cold migration for data consistency. Create a migration plan to select VMs, map networks and storage, and prepare a migration to [[Harvester]]."
createPlan: Create Migration createPlan: Create Migration
tableTitle: Migrations tableTitle: Migrations
columns: columns:
@@ -2079,22 +2079,22 @@ harvester:
checkMigratedVm: Click to check migrated VM details checkMigratedVm: Click to check migrated VM details
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
save: Save Mappings and Continue save: Save Mappings and Continue
noTemplate: Start from scratch noTemplate: Start from scratch
removeMap: Remove mapping removeMap: Remove mapping
networkMapping: networkMapping:
title: Network Mapping title: Network Mapping
description: Map VMware port groups to Harvester networks description: Map VMware port groups to [[Harvester]] networks
placeholder: Choose a Harvester network placeholder: Choose a [[Harvester]] network
template: Use existing network mapping as template template: Use existing network mapping as template
options: options:
podNetworking: Management Network podNetworking: Management Network
ignored: Ignored (No NIC will be created) ignored: Ignored (No NIC will be created)
storageMapping: storageMapping:
title: Storage Mapping title: Storage Mapping
description: Map VMware datastores to Harvester storage classes description: Map VMware datastores to [[Harvester]] storage classes
placeholder: Choose a Harvester Storage Class placeholder: Choose a [[Harvester]] Storage Class
template: Use existing storage mapping as template template: Use existing storage mapping as template
storageDefaults: storageDefaults:
title: 'Storage defaults — {name}' title: 'Storage defaults — {name}'
@@ -2413,7 +2413,7 @@ harvester:
vGpuDevices: vGPU Devices vGpuDevices: vGPU Devices
showMore: Show More showMore: Show More
parentSriov: Filter By Parent SR-IOV GPU parentSriov: Filter By Parent SR-IOV GPU
noPermission: Please contact your system administrator to add Harvester add-ons first. noPermission: Please contact your system administrator to add [[Harvester]] add-ons first.
goSetting: goSetting:
prefix: The nvidia-driver-toolkit add-on is not enabled, click prefix: The nvidia-driver-toolkit add-on is not enabled, click
middle: here middle: here
@@ -2449,7 +2449,7 @@ harvester:
vgpu: vgpu:
label: vGPU Devices label: vGPU Devices
noPermission: Please contact system administrator to add Harvester add-ons first. noPermission: Please contact system administrator to add [[Harvester]] add-ons first.
detachWarning: detachWarning:
title: Cannot Disable vGPU title: Cannot Disable vGPU
message: Please detach the device from the VM and save it first before disabling this vGPU device. message: Please detach the device from the VM and save it first before disabling this vGPU device.
@@ -2470,7 +2470,7 @@ harvester:
usb: usb:
label: USB Devices label: USB Devices
noPermission: Please contact system admin to add Harvester add-ons first noPermission: Please contact system admin to add [[Harvester]] add-ons first
goSetting: goSetting:
prefix: The pcidevices-controller add-on is not enabled, click prefix: The pcidevices-controller add-on is not enabled, click
middle: here middle: here
@@ -2531,7 +2531,7 @@ typeDescription:
# Should fit on one line. # Should fit on one line.
# If you link to anything external, it MUST have # If you link to anything external, it MUST have
# target="_blank" rel="noopener noreferrer nofollow" # target="_blank" rel="noopener noreferrer nofollow"
harvester: "Branding allows administrators to globally re-brand the UI by customizing the Harvester product name, logos and color scheme." harvester: "Branding allows administrators to globally re-brand the UI by customizing the [[Harvester]] product name, logos and color scheme."
advancedSettings: advancedSettings:
tags: tags:
@@ -2546,19 +2546,19 @@ advancedSettings:
descriptions: descriptions:
'harv-vlan': Default Network Interface name of the VLAN network. 'harv-vlan': Default Network Interface name of the VLAN network.
'harv-backup-target': Custom backup target to store virtual machine backups. 'harv-backup-target': Custom backup target to store virtual machine backups.
'branding': Branding allows administrators to globally re-brand the UI by customizing the Harvester product name, logos, and color scheme. 'branding': Branding allows administrators to globally re-brand the UI by customizing the [[Harvester]] product name, logos, and color scheme.
'harv-csi-driver-config': Configure additional information for CSI drivers. 'harv-csi-driver-config': Configure additional information for CSI drivers.
'harv-csi-online-expand-validation': Allow online volume expansion for specific CSI drivers. 'harv-csi-online-expand-validation': Allow online volume expansion for specific CSI drivers.
'harv-containerd-registry': Containerd Registry Configuration to connect private registries. 'harv-containerd-registry': Containerd Registry Configuration to connect private registries.
'harv-log-level': Configure Harvester server log level. Defaults to Info. 'harv-log-level': Configure [[Harvester]] server log level. Defaults to Info.
'harv-server-version': Harvester server version. 'harv-server-version': '[[Harvester]] server version.'
'harv-server-flavor': "Indicates the Harvester edition: Prime or Community." 'harv-server-flavor': "Indicates the [[Harvester]] edition: Prime or Community."
'harv-upgrade-checker-enabled': Specifies whether to enable Harvester upgrade check or not. Default is True. 'harv-upgrade-checker-enabled': Specifies whether to enable [[Harvester]] upgrade check or not. Default is True.
'harv-upgrade-checker-url': Default Harvester upgrade check url. Only used when the <code>upgrade-checker-enabled</code> is equal to True. 'harv-upgrade-checker-url': Default [[Harvester]] upgrade check url. Only used when the <code>upgrade-checker-enabled</code> is equal to True.
'harv-ui-source': Configure how to load the UI source. The `External` option is used to load the UI from a ui-index URL, while the `Bundled` option loads the UI from the local Harvester server. 'harv-ui-source': Configure how to load the UI source. The `External` option is used to load the UI from a ui-index URL, while the `Bundled` option loads the UI from the local [[Harvester]] server.
'harv-ui-index': 'HTML index location for the UI.' 'harv-ui-index': 'HTML index location for the UI.'
'harv-cluster-registration-url': Registration URL for multi-cluster management. 'harv-cluster-registration-url': Registration URL for multi-cluster management.
'harv-http-proxy': 'HTTP proxy for Harvester to access external services.' 'harv-http-proxy': 'HTTP proxy for [[Harvester]] to access external services.'
'harv-additional-ca': 'Custom CA root certificates for TLS validation.' 'harv-additional-ca': 'Custom CA root certificates for TLS validation.'
'harv-overcommit-config': 'Resource overcommit configuration.' 'harv-overcommit-config': 'Resource overcommit configuration.'
'harv-support-bundle-timeout': 'Support bundle timeout configuration in minutes, use 0 to disable the timeout.' 'harv-support-bundle-timeout': 'Support bundle timeout configuration in minutes, use 0 to disable the timeout.'
@@ -2570,13 +2570,13 @@ advancedSettings:
'harv-storage-network': 'Longhorn storage-network setting.' 'harv-storage-network': 'Longhorn storage-network setting.'
'harv-rwx-network': 'Configure RWX network behavior for shared or dedicated storage network usage.' 'harv-rwx-network': 'Configure RWX network behavior for shared or dedicated storage network usage.'
'harv-support-bundle-namespaces': Select additional namespaces to include in the support bundle. 'harv-support-bundle-namespaces': Select additional namespaces to include in the support bundle.
'harv-auto-disk-provision-paths': Specify the disks(using glob pattern) that Harvester will automatically add as virtual machine storage. 'harv-auto-disk-provision-paths': Specify the disks(using glob pattern) that [[Harvester]] will automatically add as virtual machine storage.
'harv-support-bundle-image': Support bundle image configuration. Find different versions in <a href="https://hub.docker.com/r/rancher/support-bundle-kit/tags" target="_blank">rancher/support-bundle-kit</a>. 'harv-support-bundle-image': Support bundle image configuration. Find different versions in <a href="https://hub.docker.com/r/rancher/support-bundle-kit/tags" target="_blank">rancher/support-bundle-kit</a>.
'harv-release-download-url': This setting allows you to configure the <code>upgrade release download</code> URL address. Harvester will get the ISO URL and checksum value from the (<code>$URL</code>/<code>$VERSION</code>/version.yaml) file hosted by the configured URL. 'harv-release-download-url': This setting allows you to configure the <code>upgrade release download</code> URL address. [[Harvester]] will get the ISO URL and checksum value from the (<code>$URL</code>/<code>$VERSION</code>/version.yaml) file hosted by the configured URL.
'harv-default-vm-termination-grace-period-seconds': Configure the virtual machine termination grace period for virtual machine stop. 'harv-default-vm-termination-grace-period-seconds': Configure the virtual machine termination grace period for virtual machine stop.
'harv-ntp-servers': Configure NTP server. You can configure multiple IPv4 addresses or host addresses. 'harv-ntp-servers': Configure NTP server. You can configure multiple IPv4 addresses or host addresses.
'harv-auto-rotate-rke2-certs': The certificate rotation mechanism relies on Rancher. Harvester will automatically update certificates generation to trigger rotation. 'harv-auto-rotate-rke2-certs': The certificate rotation mechanism relies on Rancher. [[Harvester]] will automatically update certificates generation to trigger rotation.
'harv-kubeconfig-default-token-ttl-minutes': 'TTL (in minutes) applied on Harvester administration kubeconfig files. Default is 0, which means to never expire.' 'harv-kubeconfig-default-token-ttl-minutes': 'TTL (in minutes) applied on [[Harvester]] administration kubeconfig files. Default is 0, which means to never expire.'
'harv-longhorn-v2-data-engine-enabled': 'Enable the Longhorn V2 data engine. Default is false. <ul><li>Changing this setting will restart RKE2 on all nodes. This will not affect running VM workloads.</li><li>If you see "not enough hugepages-2Mi capacity" errors when enabling this setting, wait a minute for the error to clear. If the error remains, reboot the affected node.</li></ul>' 'harv-longhorn-v2-data-engine-enabled': 'Enable the Longhorn V2 data engine. Default is false. <ul><li>Changing this setting will restart RKE2 on all nodes. This will not affect running VM workloads.</li><li>If you see "not enough hugepages-2Mi capacity" errors when enabling this setting, wait a minute for the error to clear. If the error remains, reboot the affected node.</li></ul>'
'harv-longhorn-v2-data-engine-hugepage-enabled': 'Enable hugepages when using the Longhorn V2 data engine. Default is true. Disabling hugepages reduces memory pressure on low-spec nodes and increases deployment flexibility. However, performance may be lower compared to running with hugepages.' 'harv-longhorn-v2-data-engine-hugepage-enabled': 'Enable hugepages when using the Longhorn V2 data engine. Default is true. Disabling hugepages reduces memory pressure on low-spec nodes and increases deployment flexibility. However, performance may be lower compared to running with hugepages.'
'harv-longhorn-v2-data-engine-memory-size': 'Configure the amount of memory allocated to the SPDK target daemon when using the Longhorn V2 data engine. Default is 2048 MiB.' 'harv-longhorn-v2-data-engine-memory-size': 'Configure the amount of memory allocated to the SPDK target daemon when using the Longhorn V2 data engine. Default is 2048 MiB.'
@@ -0,0 +1,101 @@
import fs from 'fs';
import path from 'path';
import { load } from 'js-yaml';
import { hostResolvesL10nGlobals, resolveL10nGlobals, setStandalonePrime, standaloneProductName } from '../l10n-globals';
describe('hostResolvesL10nGlobals', () => {
it('should be true from Rancher 2.16', () => {
expect(hostResolvesL10nGlobals('v2.16.0')).toBe(true);
expect(hostResolvesL10nGlobals('v2.17.1')).toBe(true);
});
it('should be true for 2.16 head builds', () => {
expect(hostResolvesL10nGlobals('v2.16.0-68ddd75-head')).toBe(true);
expect(hostResolvesL10nGlobals('v2.16-136b11a0062247c1b28f107d82283bdb29bc07ae-head')).toBe(true);
});
it('should be false before Rancher 2.16', () => {
expect(hostResolvesL10nGlobals('v2.15.1')).toBe(false);
expect(hostResolvesL10nGlobals('v2.14.6')).toBe(false);
});
it('should be false when the Rancher version is missing or unknown', () => {
expect(hostResolvesL10nGlobals('')).toBe(false);
expect(hostResolvesL10nGlobals(undefined)).toBe(false);
expect(hostResolvesL10nGlobals('dev')).toBe(false);
});
});
describe('standaloneProductName', () => {
it('should be Harvester when the server flavor is not prime', () => {
setStandalonePrime(false);
expect(standaloneProductName()).toBe('Harvester');
});
it('should be SUSE Virtualization when the server flavor is prime', () => {
setStandalonePrime(true);
expect(standaloneProductName()).toBe('SUSE Virtualization');
setStandalonePrime(false);
});
it('should go back to Harvester when the server flavor changes from prime', () => {
setStandalonePrime(true);
setStandalonePrime(false);
expect(standaloneProductName()).toBe('Harvester');
});
});
describe('resolveL10nGlobals', () => {
it('should replace tokens with their name when no value is given', () => {
const translations = { support: { title: '[[Harvester]] Support' } };
resolveL10nGlobals(translations);
expect(translations).toStrictEqual({ support: { title: 'Harvester Support' } });
});
it('should replace every token in a string with the given value', () => {
const translations = { message: 'The [[Harvester]] UI only supports [[Harvester]] v1.3.0 and later' };
resolveL10nGlobals(translations, { Harvester: 'SUSE Virtualization' });
expect(translations.message).toBe('The SUSE Virtualization UI only supports SUSE Virtualization v1.3.0 and later');
});
it('should keep an escaped token as a literal', () => {
const translations = { message: 'Use \\[[Harvester]] in a string' };
resolveL10nGlobals(translations);
expect(translations.message).toBe('Use [[Harvester]] in a string');
});
it('should leave strings without tokens and non-string values untouched', () => {
const translations = {
plain: 'harvester-seeder is an add-on',
count: 3,
nested: { link: '<a href="https://harvesterhci.io/">site</a>' },
};
resolveL10nGlobals(translations);
expect(translations).toStrictEqual({
plain: 'harvester-seeder is an add-on',
count: 3,
nested: { link: '<a href="https://harvesterhci.io/">site</a>' },
});
});
it('should leave no token in the extension translations', () => {
const translations = load(fs.readFileSync(path.join(__dirname, '../../l10n/en-us.yaml'), 'utf8'));
expect(JSON.stringify(translations)).toContain('[[Harvester]]');
resolveL10nGlobals(translations);
expect(JSON.stringify(translations)).not.toContain('[[');
});
});
@@ -0,0 +1,54 @@
import { primeBrandUpdater } from '../prime-brand';
describe('primeBrandUpdater', () => {
it('should switch the brand to suse on Prime', () => {
const setting = { value: 'harvester' };
primeBrandUpdater()(setting, true);
expect(setting.value).toBe('suse');
});
it('should keep the brand of the server when not on Prime', () => {
const setting = { value: 'harvester' };
primeBrandUpdater()(setting, false);
expect(setting.value).toBe('harvester');
});
it('should put the brand of the server back when the flavor stops being Prime', () => {
const setting = { value: 'harvester' };
const update = primeBrandUpdater();
update(setting, true);
update(setting, false);
expect(setting.value).toBe('harvester');
});
it('should switch the brand to suse again when the server sends its brand back on Prime', () => {
const setting = { value: 'harvester' };
const update = primeBrandUpdater();
update(setting, true);
setting.value = 'harvester';
update(setting, true);
expect(setting.value).toBe('suse');
});
it('should keep an empty brand of the server when not on Prime', () => {
const setting = { value: '' };
const update = primeBrandUpdater();
update(setting, true);
update(setting, false);
expect(setting.value).toBe('');
});
it('should do nothing before the setting is loaded', () => {
expect(() => primeBrandUpdater()(undefined, true)).not.toThrow();
});
});
+49
View File
@@ -0,0 +1,49 @@
import semver from 'semver';
// Rancher 2.16 resolves `[[name]]` tokens in translations from values registered as 'l10n-global'
export const L10N_GLOBALS_MIN_RANCHER_VERSION = '2.16.0';
// Name of the product name token, `[[Harvester]]`, and its value on Prime
export const PRODUCT_NAME_GLOBAL = 'Harvester';
export const PRIME_PRODUCT_NAME = 'SUSE Virtualization';
const TOKEN = /(\\?)\[\[([\w-]+)\]\]/g;
// Standalone has no Rancher Prime, the server-flavor setting decides instead
let standalonePrime = false;
export function setStandalonePrime(isPrime) {
standalonePrime = !!isPrime;
}
export function standaloneProductName() {
return standalonePrime ? PRIME_PRODUCT_NAME : PRODUCT_NAME_GLOBAL;
}
/**
* Whether the host Rancher resolves `[[name]]` tokens itself.
* A missing or unknown version counts as an older host.
*/
export function hostResolvesL10nGlobals(version) {
const v = semver.coerce(version);
return !!v && semver.gte(v, L10N_GLOBALS_MIN_RANCHER_VERSION);
}
/**
* Replace `[[name]]` tokens in every string of `translations`, in place, the same way Rancher 2.16 does:
* a known name gets its value, an unknown one falls back to the name and `\[[name]]` stays a literal `[[name]]`
*/
export function resolveL10nGlobals(translations, values = {}) {
Object.keys(translations || {}).forEach((key) => {
const value = translations[key];
if (typeof value === 'string') {
translations[key] = value.replace(TOKEN, (_, escaped, name) => (escaped ? `[[${ name }]]` : (values[name] ?? name)));
} else if (value && typeof value === 'object') {
resolveL10nGlobals(value, values);
}
});
return translations;
}
+26
View File
@@ -0,0 +1,26 @@
import { BRAND } from '@shell/config/types';
/**
* Standalone Prime takes the SUSE theme of Rancher Prime: the `ui-brand` setting decides the stylesheet the shell
* loads, and only the `suse` brand has one. Returns an updater that switches the copy of the setting in the store,
* the server keeps its value, and puts the server's brand back when the flavor stops being Prime.
*/
export function primeBrandUpdater() {
let serverBrand;
return (brandSetting, isPrime) => {
if (!brandSetting) {
return;
}
if (brandSetting.value !== BRAND.SUSE) {
serverBrand = brandSetting.value;
}
const brand = isPrime ? BRAND.SUSE : (serverBrand ?? brandSetting.value);
if (brandSetting.value !== brand) {
brandSetting.value = brand;
}
};
}