all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Daniel Herzig <d.herzig@proxmox.com>
To: pve-devel@lists.proxmox.com
Cc: Leo Nunner <l.nunner@proxmox.com>
Subject: [pve-devel] [PATCH 6/8 manager] cloudinit: introduce panel for LXCs
Date: Mon, 10 Feb 2025 13:07:20 +0100	[thread overview]
Message-ID: <20250210120722.163622-7-d.herzig@proxmox.com> (raw)
In-Reply-To: <20250210120722.163622-1-d.herzig@proxmox.com>

From: Leo Nunner <l.nunner@proxmox.com>

based on the already existing panel for VMs. Some things have been
changed, there is no network configuration, and a separate "enable"
options toggles cloud-init (simillar to adding/removing a cloud-init
drive for VMs).

Signed-off-by: Leo Nunner <l.nunner@proxmox.com>
---
 www/manager6/Makefile         |   1 +
 www/manager6/lxc/CloudInit.js | 237 ++++++++++++++++++++++++++++++++++
 www/manager6/lxc/Config.js    |   6 +
 3 files changed, 244 insertions(+)
 create mode 100644 www/manager6/lxc/CloudInit.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index c94a5cdf..a0e7a2e6 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -189,6 +189,7 @@ JSSRC= 							\
 	dc/PCIMapView.js				\
 	dc/USBMapView.js				\
 	lxc/CmdMenu.js					\
+	lxc/CloudInit.js				\
 	lxc/Config.js					\
 	lxc/CreateWizard.js				\
 	lxc/DeviceEdit.js				\
diff --git a/www/manager6/lxc/CloudInit.js b/www/manager6/lxc/CloudInit.js
new file mode 100644
index 00000000..11d5448d
--- /dev/null
+++ b/www/manager6/lxc/CloudInit.js
@@ -0,0 +1,237 @@
+Ext.define('PVE.lxc.CloudInit', {
+    extend: 'Proxmox.grid.PendingObjectGrid',
+    xtype: 'pveLxcCiPanel',
+
+    tbar: [
+	{
+	    xtype: 'proxmoxButton',
+	    disabled: true,
+	    dangerous: true,
+	    confirmMsg: function(rec) {
+		let view = this.up('grid');
+		var warn = gettext('Are you sure you want to remove entry {0}');
+
+		var entry = rec.data.key;
+		var msg = Ext.String.format(warn, "'"
+		    + view.renderKey(entry, {}, rec) + "'");
+
+		return msg;
+	    },
+	    enableFn: function(record) {
+		let view = this.up('grid');
+		var caps = Ext.state.Manager.get('GuiCap');
+		if (view.rows[record.data.key].never_delete ||
+		    !caps.vms['VM.Config.Network']) {
+		    return false;
+		}
+
+		if (record.data.key === 'cipassword' && !record.data.value) {
+		    return false;
+		}
+		return true;
+	    },
+	    handler: function() {
+		let view = this.up('grid');
+		let records = view.getSelection();
+		if (!records || !records.length) {
+		    return;
+		}
+
+		var id = records[0].data.key;
+
+		var params = {};
+		params.delete = id;
+		Proxmox.Utils.API2Request({
+		    url: view.baseurl + '/config',
+		    waitMsgTarget: view,
+		    method: 'PUT',
+		    params: params,
+		    failure: function(response, opts) {
+			Ext.Msg.alert('Error', response.htmlStatus);
+		    },
+		    callback: function() {
+			view.reload();
+		    },
+		});
+	    },
+	    text: gettext('Remove'),
+	},
+	{
+	    xtype: 'proxmoxButton',
+	    disabled: true,
+	    enableFn: function(rec) {
+		let view = this.up('pveLxcCiPanel');
+		return !!view.rows[rec.data.key].editor;
+	    },
+	    handler: function() {
+		let view = this.up('grid');
+		view.run_editor();
+	    },
+	    text: gettext('Edit'),
+	},
+    ],
+
+    border: false,
+
+    renderKey: function(key, metaData, rec, rowIndex, colIndex, store) {
+	var me = this;
+	var rows = me.rows;
+	var rowdef = rows[key] || {};
+
+	var icon = "";
+	if (rowdef.iconCls) {
+	    icon = '<i class="' + rowdef.iconCls + '"></i> ';
+	}
+	return icon + (rowdef.header || key);
+    },
+
+    listeners: {
+	activate: function() {
+	    var me = this;
+	    me.rstore.startUpdate();
+	},
+	itemdblclick: function() {
+	    var me = this;
+	    me.run_editor();
+	},
+    },
+
+    initComponent: function() {
+	var me = this;
+
+	var nodename = me.pveSelNode.data.node;
+	if (!nodename) {
+	    throw "no node name specified";
+	}
+
+	var vmid = me.pveSelNode.data.vmid;
+	if (!vmid) {
+	    throw "no VM ID specified";
+	}
+	var caps = Ext.state.Manager.get('GuiCap');
+	me.baseurl = '/api2/extjs/nodes/' + nodename + '/lxc/' + vmid;
+	me.url = me.baseurl + '/pending';
+	me.editorConfig.url = me.baseurl + '/config';
+	me.editorConfig.pveSelNode = me.pveSelNode;
+
+	let caps_ci = caps.vms['VM.Config.Cloudinit'] || caps.vms['VM.Config.Network'];
+	/* editor is string and object */
+	me.rows = {
+	    cienable: {
+		header: gettext('Enable'),
+		iconCls: 'fa fa-cloud',
+		never_delete: true,
+		defaultValue: false,
+		editor: caps_ci ? {
+		    xtype: 'proxmoxWindowEdit',
+		    subject: gettext('Enable Cloud-Init'),
+		    items: [
+			{
+			    xtype: 'proxmoxcheckbox',
+			    deleteEmpty: true,
+			    fieldLabel: gettext('Enable'),
+			    name: 'cienable',
+			},
+		    ],
+		} : undefined,
+		renderer: Proxmox.Utils.format_boolean,
+	    },
+	    ciuser: {
+		header: gettext('User'),
+		iconCls: 'fa fa-user',
+		never_delete: true,
+		defaultValue: '',
+		editor: caps_ci ? {
+		    xtype: 'proxmoxWindowEdit',
+		    subject: gettext('User'),
+		    items: [
+			{
+			    xtype: 'proxmoxtextfield',
+			    deleteEmpty: true,
+			    emptyText: Proxmox.Utils.defaultText,
+			    fieldLabel: gettext('User'),
+			    name: 'ciuser',
+			},
+		    ],
+		} : undefined,
+		renderer: function(value) {
+		    return value || Proxmox.Utils.defaultText;
+		},
+	    },
+	    cipassword: {
+		header: gettext('Password'),
+		iconCls: 'fa fa-unlock',
+		defaultValue: '',
+		editor: caps_ci ? {
+		    xtype: 'proxmoxWindowEdit',
+		    subject: gettext('Password'),
+		    items: [
+			{
+			    xtype: 'proxmoxtextfield',
+			    inputType: 'password',
+			    deleteEmpty: true,
+			    emptyText: Proxmox.Utils.noneText,
+			    fieldLabel: gettext('Password'),
+			    name: 'cipassword',
+			},
+		    ],
+		} : undefined,
+		renderer: function(value) {
+		    return value || Proxmox.Utils.noneText;
+		},
+	    },
+	    sshkeys: {
+		header: gettext('SSH public key'),
+		iconCls: 'fa fa-key',
+		editor: caps_ci ? 'PVE.qemu.SSHKeyEdit' : undefined,
+		never_delete: true,
+		renderer: function(value) {
+		    value = decodeURIComponent(value);
+		    var keys = value.split('\n');
+		    var text = [];
+		    keys.forEach(function(key) {
+			if (key.length) {
+			    let res = PVE.Parser.parseSSHKey(key);
+			    if (res) {
+				key = Ext.String.htmlEncode(res.comment);
+				if (res.options) {
+				    key += ' <span style="color:gray">(' + gettext('with options') + ')</span>';
+				}
+				text.push(key);
+				return;
+			    }
+			    // Most likely invalid at this point, so just stick to
+			    // the old value.
+			    text.push(Ext.String.htmlEncode(key));
+			}
+		    });
+		    if (text.length) {
+			return text.join('<br>');
+		    } else {
+			return Proxmox.Utils.noneText;
+		    }
+		},
+		defaultValue: '',
+	    },
+	    ciupgrade: {
+		header: gettext('Upgrade packages'),
+		iconCls: 'fa fa-archive',
+		renderer: Proxmox.Utils.format_boolean,
+		defaultValue: '',
+		editor: {
+		    xtype: 'proxmoxWindowEdit',
+		    subject: gettext('Upgrade packages on boot'),
+		    items: {
+			xtype: 'proxmoxcheckbox',
+			name: 'ciupgrade',
+			uncheckedValue: 0,
+			defaultValue: 0,
+			fieldLabel: gettext('Upgrade packages'),
+			labelWidth: 140,
+		    },
+		},
+	    },
+	};
+	me.callParent();
+    },
+});
diff --git a/www/manager6/lxc/Config.js b/www/manager6/lxc/Config.js
index a7191fa2..6e53de72 100644
--- a/www/manager6/lxc/Config.js
+++ b/www/manager6/lxc/Config.js
@@ -262,6 +262,12 @@ Ext.define('PVE.lxc.Config', {
 		itemId: 'dns',
 		xtype: 'pveLxcDNS',
 	    },
+	    {
+		title: 'Cloud-Init',
+		itemId: 'cloudinit',
+		iconCls: 'fa fa-cloud',
+		xtype: 'pveLxcCiPanel',
+	    },
 	    {
 		title: gettext('Options'),
 		itemId: 'options',
-- 
2.39.5


_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  parent reply	other threads:[~2025-02-10 12:08 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-10 12:07 [pve-devel] [PATCH 0/8 container/manager/docs] fix #4686: Cloudinit support for LXC Daniel Herzig
2025-02-10 12:07 ` [pve-devel] [PATCH 1/8 container] cloudinit: introduce config parameters Daniel Herzig
2025-02-13 10:10   ` Fiona Ebner
2025-02-13 10:18     ` Mira Limbeck
2025-02-13 10:22       ` Fiona Ebner
2025-02-13 10:23   ` Fiona Ebner
2025-02-13 15:05     ` Daniel Herzig
2025-02-13 12:15   ` Fiona Ebner
2025-02-10 12:07 ` [pve-devel] [PATCH 2/8 container] cloudinit: basic implementation Daniel Herzig
2025-02-13 11:01   ` Fiona Ebner
2025-02-13 11:29     ` Mira Limbeck
2025-02-13 12:02       ` Fiona Ebner
2025-02-13 15:09       ` Daniel Herzig
2025-02-13 12:06     ` Fiona Ebner
2025-02-10 12:07 ` [pve-devel] [PATCH 3/8 container] cloudinit: add dump command to pct Daniel Herzig
2025-02-13 12:00   ` Fiona Ebner
2025-02-10 12:07 ` [pve-devel] [PATCH 4/8 container] cloudinit: add function dumping options for docs Daniel Herzig
2025-02-10 12:07 ` [pve-devel] [PATCH 5/8 manager] cloudinit: rename qemu cloudinit panel Daniel Herzig
2025-02-10 12:07 ` Daniel Herzig [this message]
2025-02-10 12:07 ` [pve-devel] [PATCH 7/8 docs] pct: add script to generate cloudinit options Daniel Herzig
2025-02-13  9:52   ` Fiona Ebner
2025-02-10 12:07 ` [pve-devel] [PATCH 8/8 docs] pct: document cloudinit for LXC Daniel Herzig
2025-02-12 15:46   ` Fiona Ebner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250210120722.163622-7-d.herzig@proxmox.com \
    --to=d.herzig@proxmox.com \
    --cc=l.nunner@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal