public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Alexandre Derumier <aderumier@odiso.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH qemu-server] cloudinit: add opennebula config format
Date: Sat,  6 Feb 2021 14:01:29 +0100	[thread overview]
Message-ID: <20210206130129.2381426-1-aderumier@odiso.com> (raw)

This is an alternative format for cloudinit use by opennebula,
https://cloudinit.readthedocs.io/en/latest/topics/datasources/opennebula.html

but it can be also used by opennebula context scripts

https://github.com/OpenNebula/addon-context-linux
https://github.com/OpenNebula/addon-context-windows

This context scripts are simple udev trigger/bash scripts
and allow live configuration changes.

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/QemuServer.pm           |  2 +-
 PVE/QemuServer/Cloudinit.pm | 92 +++++++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 9c65d76..4d4efd9 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -718,7 +718,7 @@ my $confdesc_cloudinit = {
 	description => 'Specifies the cloud-init configuration format. The default depends on the'
 	    .' configured operating system type (`ostype`. We use the `nocloud` format for Linux,'
 	    .' and `configdrive2` for windows.',
-	enum => ['configdrive2', 'nocloud'],
+	enum => ['configdrive2', 'nocloud', 'opennebula'],
     },
     ciuser => {
 	optional => 1,
diff --git a/PVE/QemuServer/Cloudinit.pm b/PVE/QemuServer/Cloudinit.pm
index 52a4203..c464bf3 100644
--- a/PVE/QemuServer/Cloudinit.pm
+++ b/PVE/QemuServer/Cloudinit.pm
@@ -6,6 +6,7 @@ use warnings;
 use File::Path;
 use Digest::SHA;
 use URI::Escape;
+use MIME::Base64 qw(encode_base64);
 
 use PVE::Tools qw(run_command file_set_contents);
 use PVE::Storage;
@@ -241,6 +242,96 @@ sub generate_configdrive2 {
     commit_cloudinit_disk($conf, $vmid, $drive, $volname, $storeid, $files, 'config-2');
 }
 
+sub generate_opennebula {
+    my ($conf, $vmid, $drive, $volname, $storeid) = @_;
+
+    my ($hostname, $fqdn) = get_hostname_fqdn($conf, $vmid);
+
+    my $content = "";
+
+    my $username = $conf->{ciuser} || "root";
+    my $password = encode_base64($conf->{cipassword}) if defined($conf->{cipassword});
+
+    $content .= "USERNAME=$username\n" if defined($username);
+    $content .= "CRYPTED_PASSWORD_BASE64=$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_PUBLIC_KEY=\"";
+
+        foreach my $k (@$keys) {
+	     $content .= "$k\n";
+        }
+        $content .= "\"\n";
+
+    }
+
+    my ($searchdomains, $nameservers) = get_dns_conf($conf);
+    if ($nameservers && @$nameservers) {
+        $nameservers = join(' ', @$nameservers);
+        $content .= "DNS=\"$nameservers\"\n";
+    }
+
+    $content .= "SET_HOSTNAME=$hostname\n";
+
+    if ($searchdomains && @$searchdomains) {
+        $searchdomains = join(' ', @$searchdomains);
+        $content .= "SEARCH_DOMAIN=\"$searchdomains\"\n";
+    }
+
+    my $networkenabled = undef;
+    my @ifaces = grep { /^net(\d+)$/ } keys %$conf;
+    foreach my $iface (sort @ifaces) {
+        (my $id = $iface) =~ s/^net//;
+	my $net = PVE::QemuServer::parse_net($conf->{$iface});
+        next if !$conf->{"ipconfig$id"};
+	my $ipconfig = PVE::QemuServer::parse_ipconfig($conf->{"ipconfig$id"});
+        my $ethid = "ETH$id";
+
+	my $mac = lc $net->{hwaddr};
+
+	if ($ipconfig->{ip}) {
+	    $networkenabled = 1;
+
+	    if ($ipconfig->{ip} eq 'dhcp') {
+		$content .= $ethid."_DHCP=YES\n";
+	    } else {
+		my ($addr, $mask) = split_ip4($ipconfig->{ip});
+		$content .= $ethid."_IP=$addr\n";
+		$content .= $ethid."_MASK=$mask\n";
+		$content .= $ethid."_MAC=$mac\n";
+		$content .= $ethid."_GATEWAY=$ipconfig->{gw}\n" if $ipconfig->{gw};
+	    }
+	    $content .= $ethid."_MTU=$net->{mtu}\n" if $net->{mtu};
+	}
+
+	if ($ipconfig->{ip6}) {
+	    $networkenabled = 1;
+	    if ($ipconfig->{ip6} eq 'dhcp') {
+		$content .= $ethid."_DHCP6=YES\n";
+	    } elsif ($ipconfig->{ip6} eq 'auto') {
+		$content .= $ethid."_AUTO6=YES\n";
+	    } else {
+		my ($addr, $mask) = split('/', $ipconfig->{ip6});
+		$content .= $ethid."_IP6=$addr\n";
+		$content .= $ethid."_MASK6=$mask\n";
+		$content .= $ethid."_MAC6=$mac\n";
+		$content .= $ethid."_GATEWAY6=$ipconfig->{gw6}\n" if $ipconfig->{gw6};
+	    }
+	    $content .= $ethid."_MTU=$net->{mtu}\n" if $net->{mtu};
+	}
+    }
+
+    $content .= "NETWORK=YES\n" if $networkenabled;
+
+    my $files = {
+	'/context.sh' => $content,
+    };
+    commit_cloudinit_disk($conf, $vmid, $drive, $volname, $storeid, $files, 'CONTEXT');
+}
+
 sub nocloud_network_v2 {
     my ($conf) = @_;
 
@@ -459,6 +550,7 @@ sub read_cloudinit_snippets_file {
 my $cloudinit_methods = {
     configdrive2 => \&generate_configdrive2,
     nocloud => \&generate_nocloud,
+    opennebula => \&generate_opennebula,
 };
 
 sub generate_cloudinitconfig {
-- 
2.20.1




             reply	other threads:[~2021-02-06 13:02 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-06 13:01 Alexandre Derumier [this message]
2021-02-06 13:45 ` [pve-devel] applied: " Thomas Lamprecht

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=20210206130129.2381426-1-aderumier@odiso.com \
    --to=aderumier@odiso.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal