1 package PVE
::Storage
::DRBDPlugin
;
9 use PVE
::Tools
qw(run_command trim);
10 use PVE
::Storage
::Plugin
;
11 use PVE
::JSONSchema
qw(get_standard_option);
13 use base
qw(PVE::Storage::Plugin);
23 content
=> [ {images
=> 1}, { images
=> 1 }],
30 description
=> "The redundancy count specifies the number of nodes to which the resource should be deployed. It must be at least 1 and at most the number of nodes in the cluster.",
41 redundancy
=> { optional
=> 1 },
42 nodes
=> { optional
=> 1 },
43 disable
=> { optional
=> 1 },
49 sub connect_drbdmanage_service
{
51 my $bus = Net
::DBus-
>system;
53 my $service = $bus->get_service("org.drbd.drbdmanaged");
55 my $hdl = $service->get_object("/interface", "org.drbd.drbdmanaged");
63 die "got undefined drbd rc\n" if !$rc;
65 my ($code, $msg, $details) = @$rc;
67 return undef if $code == 0;
69 $msg = "drbd error: got error code $code" if !$msg;
72 # fixme: add error details?
73 #print Dumper($details);
75 die "drbd error: $msg\n";
78 sub drbd_list_volumes
{
81 $hdl = connect_drbdmanage_service
() if !$hdl;
83 my ($rc, $res) = $hdl->list_volumes([], 0, {}, []);
84 check_drbd_rc
($rc->[0]);
88 foreach my $entry (@$res) {
89 my ($volname, $properties, $vol_list) = @$entry;
91 next if $volname !~ m/^vm-(\d+)-/;
94 # fixme: we always use volid 0 ?
96 foreach my $volentry (@$vol_list) {
97 my ($vol_id, $vol_properties) = @$volentry;
99 my $vol_size = $vol_properties->{vol_size
} * 1024;
100 $size = $vol_size if $vol_size > $size;
103 $volumes->{$volname} = { format
=> 'raw', size
=> $size,
110 # Storage implementation
113 my ($class, $volname) = @_;
115 if ($volname =~ m/^(vm-(\d+)-[a-z][a-z0-9\-\_\.]*[a-z0-9]+)$/) {
116 return ('images', $1, $2);
119 die "unable to parse lvm volume name '$volname'\n";
122 sub filesystem_path
{
123 my ($class, $scfg, $volname) = @_;
125 my ($vtype, $name, $vmid) = $class->parse_volname($volname);
127 # fixme: always use volid 0?
128 my $path = "/dev/drbd/by-res/$volname/0";
130 return wantarray ?
($path, $vmid, $vtype) : $path;
134 my ($class, $storeid, $scfg, $volname) = @_;
136 die "can't create base images in drbd storage\n";
140 my ($class, $scfg, $storeid, $volname, $vmid, $snap) = @_;
142 die "can't clone images in drbd storage\n";
146 my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_;
148 die "unsupported format '$fmt'" if $fmt ne 'raw';
150 die "illegal name '$name' - sould be 'vm-$vmid-*'\n"
151 if $name && $name !~ m/^vm-$vmid-/;
153 my $hdl = connect_drbdmanage_service
();
154 my $volumes = drbd_list_volumes
($hdl);
156 die "volume '$name' already exists\n" if $volumes->{$name};
159 for (my $i = 1; $i < 100; $i++) {
160 my $tn = "vm-$vmid-disk-$i";
161 if (!defined ($volumes->{$tn})) {
168 die "unable to allocate an image name for VM $vmid in storage '$storeid'\n"
171 my ($rc, $res) = $hdl->create_resource($name, {});
172 check_drbd_rc
($rc->[0]);
174 ($rc, $res) = $hdl->create_volume($name, $size, {});
175 check_drbd_rc
($rc->[0]);
177 ($rc, $res) = $hdl->auto_deploy($name, $scfg->{redundancy
}, 0, 0);
178 check_drbd_rc
($rc->[0]);
184 my ($class, $storeid, $scfg, $volname, $isBase) = @_;
186 my $hdl = connect_drbdmanage_service
();
187 my ($rc, $res) = $hdl->remove_resource($volname, 0);
188 check_drbd_rc
($rc->[0]);
194 my ($class, $storeid, $scfg, $vmid, $vollist, $cache) = @_;
196 my $vgname = $scfg->{vgname
};
198 $cache->{drbd_volumes
} = drbd_list_volumes
() if !$cache->{drbd_volumes
};
202 my $dat = $cache->{drbd_volumes
};
204 foreach my $volname (keys %$dat) {
206 my $owner = $dat->{$volname}->{vmid
};
208 my $volid = "$storeid:$volname";
211 my $found = grep { $_ eq $volid } @$vollist;
214 next if defined ($vmid) && ($owner ne $vmid);
217 my $info = $dat->{$volname};
218 $info->{volid
} = $volid;
227 my ($class, $storeid, $scfg, $cache) = @_;
229 my ($total, $avail, $used);
232 my $hdl = connect_drbdmanage_service
();
233 my ($rc, $res) = $hdl->cluster_free_query($scfg->{redundancy
});
234 check_drbd_rc
($rc->[0]);
238 $total = $used + $avail;
243 # assume storage if offline
248 return ($total, $avail, $used, 1);
251 sub activate_storage
{
252 my ($class, $storeid, $scfg, $cache) = @_;
257 sub deactivate_storage
{
258 my ($class, $storeid, $scfg, $cache) = @_;
263 sub activate_volume
{
264 my ($class, $storeid, $scfg, $volname, $exclusive, $cache) = @_;
269 sub deactivate_volume
{
270 my ($class, $storeid, $scfg, $volname, $cache) = @_;
276 my ($class, $scfg, $storeid, $volname, $size, $running) = @_;
278 $size = ($size/1024/1024) . "M";
280 my $path = $class->path($scfg, $volname);
282 # fixme: howto implement this
283 die "drbd volume_resize is not implemented";
285 #my $cmd = ['/sbin/lvextend', '-L', $size, $path];
286 #run_command($cmd, errmsg => "error resizing volume '$path'");
291 sub volume_snapshot
{
292 my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
294 die "drbd snapshot is not implemented";
297 sub volume_snapshot_rollback
{
298 my ($class, $scfg, $storeid, $volname, $snap) = @_;
300 die "drbd snapshot rollback is not implemented";
303 sub volume_snapshot_delete
{
304 my ($class, $scfg, $storeid, $volname, $snap) = @_;
306 die "drbd snapshot delete is not implemented";
309 sub volume_has_feature
{
310 my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running) = @_;
313 copy
=> { base
=> 1, current
=> 1},
316 my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
317 $class->parse_volname($volname);
323 $key = $isBase ?
'base' : 'current';
325 return 1 if $features->{$feature}->{$key};