use Net::IP;
use File::Path;
-use PVE::Tools qw(run_command file_set_contents);
+use PVE::CephConfig;
+use PVE::JSONSchema qw(get_standard_option);
use PVE::ProcFSTools;
use PVE::Storage::Plugin;
-use PVE::JSONSchema qw(get_standard_option);
-use PVE::CephConfig;
+use PVE::Systemd;
+use PVE::Tools qw(run_command file_set_contents);
use base qw(PVE::Storage::Plugin);
return undef;
}
-
-# FIXME: duplicate of api/diskmanage one, move to common helper (pve-common's
-# Tools or Systemd ?)
-sub systemd_escape {
- my ($val, $is_path) = @_;
-
- # NOTE: this is not complete, but enough for our needs. normally all
- # characters which are not alpha-numerical, '.' or '_' would need escaping
- $val =~ s/\-/\\x2d/g;
-
- if ($is_path) {
- $val =~ s/^\///g;
- $val =~ s/\/$//g;
- }
- $val =~ s/\//-/g;
-
- return $val;
-}
-
-# FIXME: remove in PVE 7.0 where systemd is recent enough to not have those
-# local-fs/remote-fs dependency cycles generated for _netdev mounts...
+# FIXME: remove once it's possible to specify _netdev for fuse.ceph mounts
sub systemd_netmount {
my ($where, $type, $what, $opts) = @_;
# don't do default deps, systemd v241 generator produces ordering deps on both
# local-fs(-pre) and remote-fs(-pre) targets if we use the required _netdev
-# option. Over thre corners this gets us an ordering cycle on shutdown, which
+# option. Over three corners this gets us an ordering cycle on shutdown, which
# may make shutdown hang if the random cycle breaking hits the "wrong" unit to
# delete.
my $unit = <<"EOF";
Options=${opts}
EOF
- my $unit_fn = systemd_escape($where, 1) . ".mount";
+ my $unit_fn = PVE::Systemd::escape_unit($where, 1) . ".mount";
my $unit_path = "/run/systemd/system/$unit_fn";
+ my $daemon_needs_reload = -e $unit_path;
file_set_contents($unit_path, $unit);
+
+ run_command(['systemctl', 'daemon-reload'], errmsg => "daemon-reload error")
+ if $daemon_needs_reload;
run_command(['systemctl', 'start', $unit_fn], errmsg => "mount error");
}
sub cephfs_mount {
my ($scfg, $storeid) = @_;
- my $cmd;
my $mountpoint = $scfg->{path};
my $subdir = $scfg->{subdir} // '/';
my $configfile = $cmd_option->{ceph_conf};
my $secretfile = $cmd_option->{keyring};
my $server = $cmd_option->{mon_host} // PVE::CephConfig::get_monaddr_list($configfile);
+ my $type = 'ceph';
+ my $fs_name = $scfg->{'fs-name'};
- # fuse -> client-enforced quotas (kernel doesn't), updates w/ ceph-fuse pkg
- # kernel -> better performance, less frequent updates
+ my @opts = ();
if ($scfg->{fuse}) {
- # FIXME: ceph-fuse client complains about missing ceph.conf or keyring if
- # not provided on its default locations but still connects. Fix upstream??
- $cmd = ['/usr/bin/ceph-fuse', '-n', "client.$cmd_option->{userid}", '-m', $server];
- push @$cmd, '--keyfile', $secretfile if defined($secretfile);
- push @$cmd, '-r', $subdir if !($subdir =~ m|^/$|);
- push @$cmd, $mountpoint;
- push @$cmd, '--conf', $configfile if defined($configfile);
-
- if ($scfg->{options}) {
- push @$cmd, '-o', $scfg->{options};
- }
-
- run_command($cmd, errmsg => "mount error");
+ $type = 'fuse.ceph';
+ push @opts, "ceph.id=$cmd_option->{userid}";
+ push @opts, "ceph.keyfile=$secretfile" if defined($secretfile);
+ push @opts, "ceph.conf=$configfile" if defined($configfile);
+ push @opts, "ceph.client_fs=$fs_name" if defined($fs_name);
} else {
- my $source = "$server:$subdir";
- my @opts = ( "name=$cmd_option->{userid}" );
+ push @opts, "name=$cmd_option->{userid}";
push @opts, "secretfile=$secretfile" if defined($secretfile);
- push @opts, $scfg->{options} if $scfg->{options};
-
- systemd_netmount($mountpoint, 'ceph', $source, join(',', @opts));
+ push @opts, "conf=$configfile" if defined($configfile);
+ push @opts, "fs=$fs_name" if defined($fs_name);
}
+
+ push @opts, $scfg->{options} if $scfg->{options};
+
+ systemd_netmount($mountpoint, $type, "$server:$subdir", join(',', @opts));
}
# Configuration
description => "Subdir to mount.",
type => 'string', format => 'pve-storage-path',
},
+ 'fs-name' => {
+ description => "The Ceph filesystem name.",
+ type => 'string', format => 'pve-configid',
+ },
};
}
fuse => { optional => 1 },
bwlimit => { optional => 1 },
maxfiles => { optional => 1 },
+ keyring => { optional => 1 },
+ 'prune-backups' => { optional => 1 },
+ 'max-protected-backups' => { optional => 1 },
+ 'fs-name' => { optional => 1 },
};
}
sub on_add_hook {
my ($class, $storeid, $scfg, %param) = @_;
- return if defined($scfg->{monhost}); # nothing to do if not pve managed ceph
+ my $secret = $param{keyring} if defined $param{keyring} // undef;
+ PVE::CephConfig::ceph_create_keyfile($scfg->{type}, $storeid, $secret);
- PVE::CephConfig::ceph_create_keyfile($scfg->{type}, $storeid);
+ return;
}
-sub on_delete_hook {
- my ($class, $storeid, $scfg) = @_;
+sub on_update_hook {
+ my ($class, $storeid, $scfg, %param) = @_;
- return if defined($scfg->{monhost}); # nothing to do if not pve managed ceph
+ if (exists($param{keyring})) {
+ if (defined($param{keyring})) {
+ PVE::CephConfig::ceph_create_keyfile($scfg->{type}, $storeid, $param{keyring});
+ } else {
+ PVE::CephConfig::ceph_remove_keyfile($scfg->{type}, $storeid);
+ }
+ }
+ return;
+}
+
+sub on_delete_hook {
+ my ($class, $storeid, $scfg) = @_;
PVE::CephConfig::ceph_remove_keyfile($scfg->{type}, $storeid);
+ return;
}
sub status {
}
}
+# FIXME remove on the next APIAGE reset.
+# Deprecated, use get_volume_attribute instead.
+sub get_volume_notes {
+ my $class = shift;
+ PVE::Storage::DirPlugin::get_volume_notes($class, @_);
+}
+
+# FIXME remove on the next APIAGE reset.
+# Deprecated, use update_volume_attribute instead.
+sub update_volume_notes {
+ my $class = shift;
+ PVE::Storage::DirPlugin::update_volume_notes($class, @_);
+}
+
+sub get_volume_attribute {
+ return PVE::Storage::DirPlugin::get_volume_attribute(@_);
+}
+
+sub update_volume_attribute {
+ return PVE::Storage::DirPlugin::update_volume_attribute(@_);
+}
+
1;