* [pve-devel] [PATCH RFC container 1/3] cloudinit: introduce config parameters
2023-05-11 11:12 [pve-devel] [PATCH RFC container manager] Introduce cloud-init support for LXC Leo Nunner
@ 2023-05-11 11:12 ` Leo Nunner
2023-05-11 11:12 ` [pve-devel] [PATCH RFC container 2/3] cloudinit: basic implementation Leo Nunner
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Leo Nunner @ 2023-05-11 11:12 UTC (permalink / raw)
To: pve-devel
Introduce configuration parameters for cloud-init. Like with VMs, it's
possible to specify:
- user
- password
- ssh keys
- enable/disable updates on first boot
It's also possible to pass through custom config files for the user and
vendor settings. We don't allow configuring the network through
cloud-init, since it will clash with whatever configuration we already
did for the container.
Signed-off-by: Leo Nunner <l.nunner@proxmox.com>
---
src/PVE/API2/LXC.pm | 3 ++
src/PVE/API2/LXC/Config.pm | 7 ++++-
src/PVE/LXC/Config.pm | 61 ++++++++++++++++++++++++++++++++++++++
3 files changed, 70 insertions(+), 1 deletion(-)
diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 50c9eaf..e585509 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -2492,6 +2492,9 @@ __PACKAGE__->register_method({
my $pending_delete_hash = PVE::LXC::Config->parse_pending_delete($conf->{pending}->{delete});
+ $conf->{cipassword} = '**********' if defined($conf->{cipassword});
+ $conf->{pending}->{cipassword} = '********** ' if defined($conf->{pending}->{cipassword});
+
return PVE::GuestHelpers::config_with_pending_array($conf, $pending_delete_hash);
}});
diff --git a/src/PVE/API2/LXC/Config.pm b/src/PVE/API2/LXC/Config.pm
index e6c0980..0ff4115 100644
--- a/src/PVE/API2/LXC/Config.pm
+++ b/src/PVE/API2/LXC/Config.pm
@@ -79,7 +79,7 @@ __PACKAGE__->register_method({
} else {
$conf = PVE::LXC::Config->load_current_config($param->{vmid}, $param->{current});
}
-
+ $conf->{cipassword} = '**********' if $conf->{cipassword};
return $conf;
}});
@@ -148,6 +148,11 @@ __PACKAGE__->register_method({
$param->{cpuunits} = PVE::CGroup::clamp_cpu_shares($param->{cpuunits})
if defined($param->{cpuunits}); # clamp value depending on cgroup version
+ if (defined(my $cipassword = $param->{cipassword})) {
+ $param->{cipassword} = PVE::Tools::encrypt_pw($cipassword)
+ if $cipassword !~ /^\$(?:[156]|2[ay])(\$.+){2}/;
+ }
+
my $code = sub {
my $conf = PVE::LXC::Config->load_config($vmid);
diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm
index ac9db94..8aeb03b 100644
--- a/src/PVE/LXC/Config.pm
+++ b/src/PVE/LXC/Config.pm
@@ -442,6 +442,63 @@ my $features_desc = {
},
};
+my $cicustom_fmt = {
+ user => {
+ type => 'string',
+ optional => 1,
+ description => 'To pass a custom file containing all user data to the container via cloud-init.',
+ format => 'pve-volume-id',
+ format_description => 'volume',
+ },
+ vendor => {
+ type => 'string',
+ optional => 1,
+ description => 'To pass a custom file containing all vendor data to the container via cloud-init.',
+ format => 'pve-volume-id',
+ format_description => 'volume',
+ },
+};
+PVE::JSONSchema::register_format('pve-pct-cicustom', $cicustom_fmt);
+
+my $confdesc_cloudinit = {
+ cienable => {
+ optional => 1,
+ type => 'boolean',
+ description => "cloud-init: provide cloud-init configuration to container.",
+ },
+ ciuser => {
+ optional => 1,
+ type => 'string',
+ description => "cloud-init: User name to change ssh keys and password for instead of the"
+ ." image's configured default user.",
+ },
+ cipassword => {
+ optional => 1,
+ type => 'string',
+ description => 'cloud-init: Password to assign the user. Using this is generally not'
+ .' recommended. Use ssh keys instead. Also note that older cloud-init versions do not'
+ .' support hashed passwords.',
+ },
+ ciupdate => {
+ optional => 1,
+ type => 'boolean',
+ description => 'cloud-init: do an automatic package update on boot.'
+ },
+ cicustom => {
+ optional => 1,
+ type => 'string',
+ description => 'cloud-init: Specify custom files to replace the automatically generated'
+ .' ones at start.',
+ format => 'pve-pct-cicustom',
+ },
+ sshkeys => {
+ optional => 1,
+ type => 'string',
+ format => 'urlencoded',
+ description => "cloud-init: Setup public SSH keys (one key per line, OpenSSH format).",
+ },
+};
+
my $confdesc = {
lock => {
optional => 1,
@@ -614,6 +671,10 @@ my $confdesc = {
},
};
+foreach my $key (keys %$confdesc_cloudinit) {
+ $confdesc->{$key} = $confdesc_cloudinit->{$key};
+}
+
my $valid_lxc_conf_keys = {
'lxc.apparmor.profile' => 1,
'lxc.apparmor.allow_incomplete' => 1,
--
2.30.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH RFC container 2/3] cloudinit: basic implementation
2023-05-11 11:12 [pve-devel] [PATCH RFC container manager] Introduce cloud-init support for LXC Leo Nunner
2023-05-11 11:12 ` [pve-devel] [PATCH RFC container 1/3] cloudinit: introduce config parameters Leo Nunner
@ 2023-05-11 11:12 ` Leo Nunner
2023-05-11 11:12 ` [pve-devel] [PATCH RFC container 3/3] cloudinit: add dump command to pct Leo Nunner
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Leo Nunner @ 2023-05-11 11:12 UTC (permalink / raw)
To: pve-devel
The code to generate the actual configuration works pretty much the same
as with the VM system. We generate an instance ID by hashing the user
configuration, causing cloud-init to run every time said configuration
changes.
Instead of creating a config drive, we write files directly into the
volume of the container. We create a folder at
'/var/lib/cloud/seed/nocloud-net' and write the files 'user-data',
'vendor-data' and 'meta-data'. Cloud-init looks at the instance ID
inside 'meta-data' to decide whether it should run (again) or not.
Custom scripts need to be located inside the snippets directory, and
overwrite the default generated configuration file.
Signed-off-by: Leo Nunner <l.nunner@proxmox.com>
---
src/PVE/LXC.pm | 1 +
src/PVE/LXC/Cloudinit.pm | 114 ++++++++++++++++++++++++++++++++++++++
src/PVE/LXC/Makefile | 1 +
src/lxc-pve-prestart-hook | 5 ++
4 files changed, 121 insertions(+)
create mode 100644 src/PVE/LXC/Cloudinit.pm
diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index d138161..ea01fbb 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -39,6 +39,7 @@ use PVE::Tools qw(
use PVE::Syscall qw(:fsmount);
use PVE::LXC::CGroup;
+use PVE::LXC::Cloudinit;
use PVE::LXC::Config;
use PVE::LXC::Monitor;
use PVE::LXC::Tools;
diff --git a/src/PVE/LXC/Cloudinit.pm b/src/PVE/LXC/Cloudinit.pm
new file mode 100644
index 0000000..e4bc67d
--- /dev/null
+++ b/src/PVE/LXC/Cloudinit.pm
@@ -0,0 +1,114 @@
+package PVE::LXC::Cloudinit;
+
+use strict;
+use warnings;
+
+use Digest::SHA;
+use File::Path;
+
+use PVE::LXC;
+
+sub gen_cloudinit_metadata {
+ my ($user) = @_;
+
+ my $uuid_str = Digest::SHA::sha1_hex($user);
+ return cloudinit_metadata($uuid_str);
+}
+
+sub cloudinit_metadata {
+ my ($uuid) = @_;
+ my $raw = "";
+
+ $raw .= "instance-id: $uuid\n";
+
+ return $raw;
+}
+
+sub cloudinit_userdata {
+ my ($conf) = @_;
+
+ my $content = "#cloud-config\n";
+
+ my $username = $conf->{ciuser};
+ my $password = $conf->{cipassword};
+
+ $content .= "user: $username\n" if defined($username);
+ $content .= "password: $password\n" if defined($password);
+
+ if (defined(my $keys = $conf->{sshkeys})) {
+ $keys = URI::Escape::uri_unescape($keys);
+ $keys = [map { my $key = $_; chomp $key; $key } split(/\n/, $keys)];
+ $keys = [grep { /\S/ } @$keys];
+ $content .= "ssh_authorized_keys:\n";
+ foreach my $k (@$keys) {
+ $content .= " - $k\n";
+ }
+ }
+ $content .= "chpasswd:\n";
+ $content .= " expire: False\n";
+
+ if (!defined($username) || $username ne 'root') {
+ $content .= "users:\n";
+ $content .= " - default\n";
+ }
+
+ $content .= "package_upgrade: true\n" if $conf->{ciupdate};
+
+ return $content;
+}
+
+sub read_cloudinit_snippets_file {
+ my ($storage_conf, $volid) = @_;
+
+ my ($full_path, undef, $type) = PVE::Storage::path($storage_conf, $volid);
+ die "$volid is not in the snippets directory\n" if $type ne 'snippets';
+ return PVE::Tools::file_get_contents($full_path, 1 * 1024 * 1024);
+}
+
+sub read_custom_cloudinit_files {
+ my ($conf) = @_;
+
+ my $cloudinit_conf = $conf->{cicustom};
+ my $files = $cloudinit_conf ? PVE::JSONSchema::parse_property_string('pve-pct-cicustom', $cloudinit_conf) : {};
+
+ my $user_volid = $files->{user};
+ my $vendor_volid = $files->{vendor};
+
+ my $storage_conf = PVE::Storage::config();
+
+ my $user_data;
+ if ($user_volid) {
+ $user_data = read_cloudinit_snippets_file($storage_conf, $user_volid);
+ }
+
+ my $vendor_data;
+ if ($vendor_volid) {
+ $user_data = read_cloudinit_snippets_file($storage_conf, $vendor_volid);
+ }
+
+ return ($user_data, $vendor_data);
+}
+
+sub create_cloudinit_files {
+ my ($conf, $setup) = @_;
+
+ my $cloudinit_dir = "/var/lib/cloud/seed/nocloud-net";
+
+ my ($user_data, $vendor_data) = read_custom_cloudinit_files($conf);
+ $user_data = cloudinit_userdata($conf) if !defined($user_data);
+ $vendor_data = '' if !defined($vendor_data);
+
+ my $meta_data = gen_cloudinit_metadata($user_data);
+
+ $setup->protected_call(sub {
+ my $plugin = $setup->{plugin};
+
+ $plugin->ct_make_path($cloudinit_dir);
+
+ $plugin->ct_file_set_contents("$cloudinit_dir/user-data", $user_data);
+ $plugin->ct_file_set_contents("$cloudinit_dir/vendor-data", $vendor_data);
+ $plugin->ct_file_set_contents("$cloudinit_dir/meta-data", $meta_data);
+ });
+}
+
+1;
diff --git a/src/PVE/LXC/Makefile b/src/PVE/LXC/Makefile
index a190260..5d595ba 100644
--- a/src/PVE/LXC/Makefile
+++ b/src/PVE/LXC/Makefile
@@ -1,5 +1,6 @@
SOURCES= \
CGroup.pm \
+ Cloudinit.pm \
Command.pm \
Config.pm \
Create.pm \
diff --git a/src/lxc-pve-prestart-hook b/src/lxc-pve-prestart-hook
index 3bdf7e4..e5932d2 100755
--- a/src/lxc-pve-prestart-hook
+++ b/src/lxc-pve-prestart-hook
@@ -12,6 +12,7 @@ use POSIX;
use PVE::CGroup;
use PVE::Cluster;
use PVE::LXC::Config;
+use PVE::LXC::Cloudinit;
use PVE::LXC::Setup;
use PVE::LXC::Tools;
use PVE::LXC;
@@ -140,6 +141,10 @@ PVE::LXC::Tools::lxc_hook('pre-start', 'lxc', sub {
my $lxc_setup = PVE::LXC::Setup->new($conf, $rootdir);
$lxc_setup->pre_start_hook();
+ if ($conf->{cienable}) {
+ PVE::LXC::Cloudinit::create_cloudinit_files($conf, $lxc_setup)
+ }
+
if (PVE::CGroup::cgroup_mode() == 2) {
if (!$lxc_setup->unified_cgroupv2_support()) {
log_warn($vmid, "old systemd (< v232) detected, container won't run in a pure cgroupv2"
--
2.30.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH RFC container 3/3] cloudinit: add dump command to pct
2023-05-11 11:12 [pve-devel] [PATCH RFC container manager] Introduce cloud-init support for LXC Leo Nunner
2023-05-11 11:12 ` [pve-devel] [PATCH RFC container 1/3] cloudinit: introduce config parameters Leo Nunner
2023-05-11 11:12 ` [pve-devel] [PATCH RFC container 2/3] cloudinit: basic implementation Leo Nunner
@ 2023-05-11 11:12 ` Leo Nunner
2023-05-11 11:12 ` [pve-devel] [PATCH RFC manager 1/2] cloudinit: rename qemu cloudinit panel Leo Nunner
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Leo Nunner @ 2023-05-11 11:12 UTC (permalink / raw)
To: pve-devel
Introduce a 'pct cloudinit dump <vmid> <section>' command to dump the
generated cloudinit configuration for a section.
Signed-off-by: Leo Nunner <l.nunner@proxmox.com>
---
src/PVE/API2/LXC.pm | 33 +++++++++++++++++++++++++++++++++
src/PVE/CLI/pct.pm | 4 ++++
src/PVE/LXC/Cloudinit.pm | 11 +++++++++++
3 files changed, 48 insertions(+)
diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index e585509..2cae727 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -2963,4 +2963,37 @@ __PACKAGE__->register_method({
return { socket => $socket };
}});
+
+__PACKAGE__->register_method({
+ name => 'cloudinit_generated_config_dump',
+ path => '{vmid}/cloudinit/dump',
+ method => 'GET',
+ proxyto => 'node',
+ description => "Get automatically generated cloudinit config.",
+ permissions => {
+ check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid }),
+ type => {
+ description => 'Config type.',
+ type => 'string',
+ enum => ['user', 'meta'],
+ },
+ },
+ },
+ returns => {
+ type => 'string',
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $conf = PVE::LXC::Config->load_config($param->{vmid});
+
+ return PVE::LXC::Cloudinit::dump_cloudinit_config($conf, $param->{type});
+ }});
+
1;
diff --git a/src/PVE/CLI/pct.pm b/src/PVE/CLI/pct.pm
index ff75d33..69f3560 100755
--- a/src/PVE/CLI/pct.pm
+++ b/src/PVE/CLI/pct.pm
@@ -1000,6 +1000,10 @@ our $cmddef = {
rescan => [ __PACKAGE__, 'rescan', []],
cpusets => [ __PACKAGE__, 'cpusets', []],
fstrim => [ __PACKAGE__, 'fstrim', ['vmid']],
+
+ cloudinit => {
+ dump => [ "PVE::API2::LXC", 'cloudinit_generated_config_dump', ['vmid', 'type'], { node => $nodename }, sub { print "$_[0]\n"; }],
+ },
};
1;
diff --git a/src/PVE/LXC/Cloudinit.pm b/src/PVE/LXC/Cloudinit.pm
index e4bc67d..c977a08 100644
--- a/src/PVE/LXC/Cloudinit.pm
+++ b/src/PVE/LXC/Cloudinit.pm
@@ -111,4 +111,15 @@ sub create_cloudinit_files {
});
}
+sub dump_cloudinit_config {
+ my ($conf, $type) = @_;
+
+ if ($type eq 'user') {
+ return cloudinit_userdata($conf);
+ } else { # metadata config
+ my $user = cloudinit_userdata($conf);
+ return gen_cloudinit_metadata($user);
+ }
+}
+
1;
--
2.30.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH RFC manager 1/2] cloudinit: rename qemu cloudinit panel
2023-05-11 11:12 [pve-devel] [PATCH RFC container manager] Introduce cloud-init support for LXC Leo Nunner
` (2 preceding siblings ...)
2023-05-11 11:12 ` [pve-devel] [PATCH RFC container 3/3] cloudinit: add dump command to pct Leo Nunner
@ 2023-05-11 11:12 ` Leo Nunner
2023-05-11 11:12 ` [pve-devel] [PATCH RFC manager 2/2] cloudinit: introduce panel for LXCs Leo Nunner
2023-05-12 11:39 ` [pve-devel] [PATCH RFC container manager] Introduce cloud-init support for LXC Wolfgang Bumiller
5 siblings, 0 replies; 7+ messages in thread
From: Leo Nunner @ 2023-05-11 11:12 UTC (permalink / raw)
To: pve-devel
Signed-off-by: Leo Nunner <l.nunner@proxmox.com>
---
www/manager6/qemu/CloudInit.js | 4 ++--
www/manager6/qemu/Config.js | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/www/manager6/qemu/CloudInit.js b/www/manager6/qemu/CloudInit.js
index 77ff93d4..14117ff6 100644
--- a/www/manager6/qemu/CloudInit.js
+++ b/www/manager6/qemu/CloudInit.js
@@ -1,6 +1,6 @@
Ext.define('PVE.qemu.CloudInit', {
extend: 'Proxmox.grid.PendingObjectGrid',
- xtype: 'pveCiPanel',
+ xtype: 'pveQemuCiPanel',
onlineHelp: 'qm_cloud_init',
@@ -66,7 +66,7 @@ Ext.define('PVE.qemu.CloudInit', {
xtype: 'proxmoxButton',
disabled: true,
enableFn: function(rec) {
- let view = this.up('pveCiPanel');
+ let view = this.up('pveQemuCiPanel');
return !!view.rows[rec.data.key].editor;
},
handler: function() {
diff --git a/www/manager6/qemu/Config.js b/www/manager6/qemu/Config.js
index 94c540c5..03e1e6d8 100644
--- a/www/manager6/qemu/Config.js
+++ b/www/manager6/qemu/Config.js
@@ -284,7 +284,7 @@ Ext.define('PVE.qemu.Config', {
title: 'Cloud-Init',
itemId: 'cloudinit',
iconCls: 'fa fa-cloud',
- xtype: 'pveCiPanel',
+ xtype: 'pveQemuCiPanel',
},
{
title: gettext('Options'),
--
2.30.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH RFC manager 2/2] cloudinit: introduce panel for LXCs
2023-05-11 11:12 [pve-devel] [PATCH RFC container manager] Introduce cloud-init support for LXC Leo Nunner
` (3 preceding siblings ...)
2023-05-11 11:12 ` [pve-devel] [PATCH RFC manager 1/2] cloudinit: rename qemu cloudinit panel Leo Nunner
@ 2023-05-11 11:12 ` Leo Nunner
2023-05-12 11:39 ` [pve-devel] [PATCH RFC container manager] Introduce cloud-init support for LXC Wolfgang Bumiller
5 siblings, 0 replies; 7+ messages in thread
From: Leo Nunner @ 2023-05-11 11:12 UTC (permalink / raw)
To: pve-devel
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 | 219 ++++++++++++++++++++++++++++++++++
www/manager6/lxc/Config.js | 6 +
3 files changed, 226 insertions(+)
create mode 100644 www/manager6/lxc/CloudInit.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 2b577c8e..27ac9068 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -168,6 +168,7 @@ JSSRC= \
dc/UserTagAccessEdit.js \
dc/RegisteredTagsEdit.js \
lxc/CmdMenu.js \
+ lxc/CloudInit.js \
lxc/Config.js \
lxc/CreateWizard.js \
lxc/DNS.js \
diff --git a/www/manager6/lxc/CloudInit.js b/www/manager6/lxc/CloudInit.js
new file mode 100644
index 00000000..2e4e26ba
--- /dev/null
+++ b/www/manager6/lxc/CloudInit.js
@@ -0,0 +1,219 @@
+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: '',
+ },
+ };
+ me.callParent();
+ },
+});
diff --git a/www/manager6/lxc/Config.js b/www/manager6/lxc/Config.js
index 23c17d2e..bd86b93b 100644
--- a/www/manager6/lxc/Config.js
+++ b/www/manager6/lxc/Config.js
@@ -260,6 +260,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.30.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [pve-devel] [PATCH RFC container manager] Introduce cloud-init support for LXC
2023-05-11 11:12 [pve-devel] [PATCH RFC container manager] Introduce cloud-init support for LXC Leo Nunner
` (4 preceding siblings ...)
2023-05-11 11:12 ` [pve-devel] [PATCH RFC manager 2/2] cloudinit: introduce panel for LXCs Leo Nunner
@ 2023-05-12 11:39 ` Wolfgang Bumiller
5 siblings, 0 replies; 7+ messages in thread
From: Wolfgang Bumiller @ 2023-05-12 11:39 UTC (permalink / raw)
To: Leo Nunner; +Cc: pve-devel
On Thu, May 11, 2023 at 01:12:44PM +0200, Leo Nunner wrote:
> This series introduces basic cloudinit support for containers. All in
> all, it works quite similar to VMs, with the caveat that we only allow
> network configuration through the alrady existing systems, and not via
> cloud-init.
>
> These patches should still be seen as WIP, but they are in a workable
> state and I'd like some feedback on how I currently handle things. Are
> there any other parameters/features that are needed here? Is the current
> mechanism for providing the configuration to the container optimal, or
> is there a better way?
Seems fine to me. Regarding other parameters/features... meh, I'd say we
can discuss them when they're requested?
^ permalink raw reply [flat|nested] 7+ messages in thread