On Mon Feb 23, 2026 at 4:40 PM CET, Markus Frank wrote:
> Display a warning indicating that this feature is experimental.
>
> Add the Messages.js file to reuse warnings, hints, and other messages
> in different locations. Display the virtiofs warnings from the
> Messages.js file in the migration and directory edit windows.
>
> Requires the qemu-server commit named "virtiofs: add live migration
> support".
>
> Signed-off-by: Markus Frank <[email protected]>
> ---
> v2 changes:
> * show more warnings/hints and add them to Messages.js so that they can
>   be reused in multiple locations
>
> I discussed with Dominik Csapak off-list what a good place for common
> log messages or texts that can be reused would be.
> We both agreed that Utils.js is already big enough, so I added
> Messages.js. What do you think?
>
>
>  www/manager6/Makefile             |  1 +
>  www/manager6/Messages.js          | 24 +++++++++++++++
>  www/manager6/dc/DirMapView.js     |  8 +++++
>  www/manager6/window/DirMapEdit.js | 49 +++++++++++++++++++++++++++++++
>  www/manager6/window/Migrate.js    |  6 ++++
>  5 files changed, 88 insertions(+)
>  create mode 100644 www/manager6/Messages.js
>
> diff --git a/www/manager6/Makefile b/www/manager6/Makefile
> index 4558d53e..79356b2a 100644
> --- a/www/manager6/Makefile
> +++ b/www/manager6/Makefile
> @@ -7,6 +7,7 @@ JSSRC=                                                        
> \
>       StateProvider.js                                \
>       Utils.js                                        \
>       UIOptions.js                                    \
> +     Messages.js                                     \
>       Toolkit.js                                      \
>       VNCConsole.js                                   \
>       button/ConsoleButton.js                         \
> diff --git a/www/manager6/Messages.js b/www/manager6/Messages.js
> new file mode 100644
> index 00000000..2af81e83
> --- /dev/null
> +++ b/www/manager6/Messages.js
> @@ -0,0 +1,24 @@
> +Ext.define('PVE.Messages', {
> +    singleton: true,
> +
> +    virtiofs: {
> +        same_shared_dir: {
> +            text: gettext(
> +                'Ensure you are using the same shared directory on all hosts 
> before migrating with a virtiofs device.',
> +            ),
> +            severity: 'warning',

If the Messages module should only be for messages, then this shouldn't
hold the 'severity' properties, but only the translated text strings, as
the 'severity' property is very specific to the migration preconditions
modal.

> +        },
> +        umount: {
> +            text: gettext(
> +                'The safest way to migrate a VM with a virtiofs device is to 
> either unmount or mount the device as read-only.',
> +            ),
> +            severity: 'warning',
> +        },
> +        migration_method_change: {
> +            text: gettext(
> +                'Changes to the migration method will take effect when the 
> VM is restarted.',
> +            ),
> +            severity: 'info',
> +        },
> +    },
> +});
> diff --git a/www/manager6/dc/DirMapView.js b/www/manager6/dc/DirMapView.js
> index f0dfe28f..26f938e9 100644
> --- a/www/manager6/dc/DirMapView.js
> +++ b/www/manager6/dc/DirMapView.js
> @@ -26,6 +26,14 @@ Ext.define('PVE.dc.DirMapView', {
>              dataIndex: 'text',
>              width: 200,
>          },
> +        {
> +            header: gettext('Live Migration Method'),
> +            dataIndex: 'live-migration',
> +            renderer: function (value, _meta, record) {
> +                return Ext.String.htmlEncode(value ?? 
> record.data['live-migration-method']);
> +            },
> +            width: 150,
> +        },
>          {
>              header: gettext('Comment'),
>              dataIndex: 'description',
> diff --git a/www/manager6/window/DirMapEdit.js 
> b/www/manager6/window/DirMapEdit.js
> index 841ff1fe..56f0be06 100644
> --- a/www/manager6/window/DirMapEdit.js
> +++ b/www/manager6/window/DirMapEdit.js
> @@ -39,8 +39,10 @@ Ext.define('PVE.window.DirMapEditWindow', {
>  
>              let name = values.name;
>              let description = values.description;
> +            let liveMigration = values['live-migration-method'];
>              let deletes = values.delete;
>  
> +            delete values['live-migration-method'];
>              delete values.description;
>              delete values.name;
>              delete values.delete;
> @@ -69,6 +71,9 @@ Ext.define('PVE.window.DirMapEditWindow', {
>              if (description) {
>                  values.description = description;
>              }
> +            if (liveMigration) {
> +                values['live-migration-method'] = liveMigration;
> +            }
>              if (deletes && !view.isCreate) {
>                  values.delete = deletes;
>              }
> @@ -181,6 +186,37 @@ Ext.define('PVE.window.DirMapEditWindow', {
>                          },
>                      ],
>                  },
> +                {
> +                    xtype: 'proxmoxKVComboBox',
> +                    fieldLabel: `<i class="fa fa-exclamation-triangle 
> warning"></i> ${gettext('Experimental')}:
> +                        ${gettext('Live Migration Method')}`,
> +                    reference: 'live-migration-method',
> +                    name: 'live-migration-method',
> +                    value: '__default__',
> +                    comboItems: [
> +                        [
> +                            '__default__',
> +                            Proxmox.Utils.defaultText + ' (' + 
> Proxmox.Utils.disabledText + ')',
> +                        ],
> +                        ['find-paths', 'find-paths'],
> +                        ['file-handles', 'file-handles'],

nit: these should be translatable and use human-readable strings if
     possible.

> +                    ],
> +                    cbind: {
> +                        deleteEmpty: '{!isCreate}',
> +                        disabled: '{hideComment}',
> +                        hidden: '{hideComment}',

nit: it would make sense to rename hideComment to something more generic
     now (maybe even in a patch before that) as the scope of what is
     hidden for sub-entries has changed with this patch.

> +                    },
> +                },
> +                {
> +                    xtype: 'displayfield',
> +                    reference: 'migration-method-change-hint',
> +                    columnWidth: 1,
> +                    value: 
> PVE.Messages.virtiofs.migration_method_change.text,
> +                    cbind: {
> +                        hidden: '{hideComment}',
> +                    },
> +                    userCls: 'pmx-hint',
> +                },

This seems a little crammed in the web interface, maybe it would be
better to make it its own whole row rather than a half-column?

>              ],
>  
>              columnB: [
> @@ -202,6 +238,19 @@ Ext.define('PVE.window.DirMapEditWindow', {
>                          },
>                      ],
>                  },
> +                {
> +                    xtype: 'displayfield',
> +                    reference: 'migration-hint',
> +                    columnWidth: 1,
> +                    value:
> +                        PVE.Messages.virtiofs.same_shared_dir.text +
> +                        ' ' +
> +                        PVE.Messages.virtiofs.umount.text,
> +                    cbind: {
> +                        hidden: '{hideComment}',
> +                    },
> +                    userCls: 'pmx-hint',
> +                },

This should probably also go together with the 'live-migration-method'
field so they are close together, maybe move all of those fields to
columnB right before the comment?

The 'migration-hint' could also only be displayed if the setting !=
disabled.

>              ],
>          },
>      ],
> diff --git a/www/manager6/window/Migrate.js b/www/manager6/window/Migrate.js
> index ff80c70c..c91f3dd7 100644
> --- a/www/manager6/window/Migrate.js
> +++ b/www/manager6/window/Migrate.js
> @@ -335,8 +335,14 @@ Ext.define('PVE.window.Migrate', {
>              if (vm.get('running')) {
>                  let allowed = [];
>                  let notAllowed = [];
> +                let print_virtiofs_migration_warn_ones = true;
>                  for (const [key, resource] of 
> Object.entries(mappedResources)) {
>                      if (resource['live-migration']) {
> +                        if (key.match(/^virtiofs\d+/) && 
> print_virtiofs_migration_warn_ones) {
> +                            
> migration.preconditions.push(PVE.Messages.virtiofs.same_shared_dir);
> +                            
> migration.preconditions.push(PVE.Messages.virtiofs.umount);
> +                            print_virtiofs_migration_warn_ones = false;
> +                        }

nit: could also be something like

    let has_virtiofs_live_migration = Object.entries(mappedResources)
            .some(([key, resource]) => key.match(/^virtiofs\d+/) && 
resource['live-migration']);

to make this a little bit shorter.

>                          allowed.push(key);
>                      } else {
>                          notAllowed.push(key);




Reply via email to