use PVE::IPCC;
use PVE::SafeSyslog;
use PVE::JSONSchema;
+use PVE::Network;
use JSON;
use RRDs;
use Encode;
+use UUID;
use base 'Exporter';
our @EXPORT_OK = qw(
mkdir $authdir || $! == EEXIST || die "unable to create dir '$authdir' - $!\n";
- my $cmd = "openssl genrsa -out '$authprivkeyfn' 2048";
- run_silent_cmd($cmd);
+ run_silent_cmd(['openssl', 'genrsa', '-out', $authprivkeyfn, '2048']);
- $cmd = "openssl rsa -in '$authprivkeyfn' -pubout -out '$authpubkeyfn'";
- run_silent_cmd($cmd)
+ run_silent_cmd(['openssl', 'rsa', '-in', $authprivkeyfn, '-pubout', '-out', $authpubkeyfn]);
}
sub gen_pveca_key {
# we try to generate an unique 'subject' to avoid browser problems
# (reused serial numbers, ..)
- my $nid = (split (/\s/, `md5sum '$pveca_key_fn'`))[0] || time();
+ my $uuid;
+ UUID::generate($uuid);
+ my $uuid_str;
+ UUID::unparse($uuid, $uuid_str);
eval {
# wrap openssl with faketime to prevent bug #904
run_silent_cmd(['faketime', 'yesterday', 'openssl', 'req', '-batch',
'-days', '3650', '-new', '-x509', '-nodes', '-key',
$pveca_key_fn, '-out', $pveca_cert_fn, '-subj',
- "/CN=Proxmox Virtual Environment/OU=$nid/O=PVE Cluster Manager CA/"]);
+ "/CN=Proxmox Virtual Environment/OU=$uuid_str/O=PVE Cluster Manager CA/"]);
};
die "generating pve root certificate failed:\n$@" if $@;
for my $line (@$data) {
my $entry = { 'time' => $start };
$start += $step;
- my $found_undefs;
for (my $i = 0; $i < $fields; $i++) {
my $name = $names->[$i];
if (defined(my $val = $line->[$i])) {
$entry->{$name} = $val;
} else {
- # we only add entryies with all data defined
- # extjs chart has problems with undefined values
- $found_undefs = 1;
+ # leave empty fields undefined
+ # maybe make this configurable?
}
}
- push @$res, $entry if !$found_undefs;
+ push @$res, $entry;
}
return $res;
return wantarray ? ($ip, $family) : $ip;
}
+sub get_local_migration_ip {
+ my ($migration_network, $noerr) = @_;
+
+ my $cidr = $migration_network;
+
+ if (!defined($cidr)) {
+ my $dc_conf = cfs_read_file('datacenter.cfg');
+ $cidr = $dc_conf->{migration}->{network}
+ if defined($dc_conf->{migration}->{network});
+ }
+
+ if (defined($cidr)) {
+ my $ips = PVE::Network::get_local_ip_from_cidr($cidr);
+
+ die "could not get migration ip: no IP address configured on local " .
+ "node for network '$cidr'\n" if !$noerr && (scalar(@$ips) == 0);
+
+ die "could not get migration ip: multiple IP address configured for " .
+ "network '$cidr'\n" if !$noerr && (scalar(@$ips) > 1);
+
+ return @$ips[0];
+ }
+
+ return undef;
+};
+
# ssh related utility functions
sub ssh_merge_keys {
}
sub setup_sshd_config {
+ my ($start_sshd) = @_;
my $conf = PVE::Tools::file_get_contents($sshd_config_fn);
PVE::Tools::file_set_contents($sshd_config_fn, $conf);
- PVE::Tools::run_command(['systemctl', 'reload-or-restart', 'sshd']);
+ my $cmd = $start_sshd ? 'reload-or-restart' : 'reload-or-try-restart';
+ PVE::Tools::run_command(['systemctl', $cmd, 'sshd']);
}
sub setup_rootsshconfig {
}
+my $migration_format = {
+ type => {
+ default_key => 1,
+ type => 'string',
+ enum => ['secure', 'insecure'],
+ description => "Migration traffic is encrypted using an SSH tunnel by " .
+ "default. On secure, completely private networks this can be " .
+ "disabled to increase performance.",
+ default => 'secure',
+ },
+ network => {
+ optional => 1,
+ type => 'string', format => 'CIDR',
+ format_description => 'CIDR',
+ description => "CIDR of the (sub) network that is used for migration."
+ },
+};
+
my $datacenter_schema = {
type => "object",
additionalProperties => 0,
migration_unsecure => {
optional => 1,
type => 'boolean',
- description => "Migration is secure using SSH tunnel by default. For secure private networks you can disable it to speed up migration.",
+ description => "Migration is secure using SSH tunnel by default. " .
+ "For secure private networks you can disable it to speed up " .
+ "migration. Deprecated, use the 'migration' property instead!",
+ },
+ migration => {
+ optional => 1,
+ type => 'string', format => $migration_format,
+ description => "For cluster wide migration settings.",
},
console => {
optional => 1,
enum => [ 'watchdog', 'hardware', 'both' ],
description => "Set the fencing mode of the HA cluster. Hardware mode " .
"needs a valid configuration of fence devices in /etc/pve/ha/fence.cfg." .
- " With both all two modes are used. " .
- " NOTE: 'hardware' and 'both' are EXPERIMENTAL & WIP",
+ " With both all two modes are used." .
+ "\n\nWARNING: 'hardware' and 'both' are EXPERIMENTAL & WIP",
+ },
+ mac_prefix => {
+ optional => 1,
+ type => 'string',
+ pattern => qr/[a-f0-9]{2}(?::[a-f0-9]{2}){0,2}:?/i,
+ description => 'Prefix for autogenerated MAC addresses.',
},
},
};
sub parse_datacenter_config {
my ($filename, $raw) = @_;
- return PVE::JSONSchema::parse_config($datacenter_schema, $filename, $raw // '');
+ my $res = PVE::JSONSchema::parse_config($datacenter_schema, $filename, $raw // '');
+
+ if (my $migration = $res->{migration}) {
+ $res->{migration} = PVE::JSONSchema::parse_property_string($migration_format, $migration);
+ }
+
+ # for backwards compatibility only, new migration property has precedence
+ if (defined($res->{migration_unsecure})) {
+ if (defined($res->{migration}->{type})) {
+ warn "deprecated setting 'migration_unsecure' and new 'migration: type' " .
+ "set at same time! Ignore 'migration_unsecure'\n";
+ } else {
+ $res->{migration}->{type} = ($res->{migration_unsecure}) ? 'insecure' : 'secure';
+ }
+ }
+
+ return $res;
}
sub write_datacenter_config {
my ($filename, $cfg) = @_;
-
+
+ # map deprecated setting to new one
+ if (defined($cfg->{migration_unsecure}) && !defined($cfg->{migration})) {
+ my $migration_unsecure = delete $cfg->{migration_unsecure};
+ $cfg->{migration}->{type} = ($migration_unsecure) ? 'insecure' : 'secure';
+ }
+
return PVE::JSONSchema::dump_config($datacenter_schema, $filename, $cfg);
}
my $exists = -f "$basedir/corosync.conf";
warn "Corosync config '$basedir/corosync.conf' does not exist - is this node part of a cluster?\n"
- if !$silent;
+ if !$silent && !$exists;
return $exists;
}