1 package PVE
::API2
::Pool
;
6 use PVE
::AccessControl
;
7 use PVE
::Cluster qw
(cfs_read_file cfs_write_file
);
8 use PVE
::Exception
qw(raise_param_exc);
17 use base
qw(PVE::RESTHandler);
19 __PACKAGE__-
>register_method ({
23 description
=> "Pool index.",
25 description
=> "List all pools where you have Pool.Audit permissions on /pool/<pool>.",
29 additionalProperties
=> 0,
37 poolid
=> { type
=> 'string' },
40 links
=> [ { rel
=> 'child', href
=> "{poolid}" } ],
45 my $rpcenv = PVE
::RPCEnvironment
::get
();
46 my $authuser = $rpcenv->get_user();
48 my $usercfg = $rpcenv->{user_cfg
};
52 for my $pool (sort keys %{$usercfg->{pools
}}) {
53 next if !$rpcenv->check($authuser, "/pool/$pool", [ 'Pool.Audit' ], 1);
55 my $entry = { poolid
=> $pool };
56 my $pool_config = $usercfg->{pools
}->{$pool};
57 $entry->{comment
} = $pool_config->{comment
} if defined($pool_config->{comment
});
64 __PACKAGE__-
>register_method ({
65 name
=> 'create_pool',
70 check
=> ['perm', '/pool/{poolid}', ['Pool.Allocate']],
72 description
=> "Create new pool.",
74 additionalProperties
=> 0,
78 format
=> 'pve-poolid',
86 returns
=> { type
=> 'null' },
90 PVE
::AccessControl
::lock_user_config
(sub {
91 my $usercfg = cfs_read_file
("user.cfg");
92 my $pool = $param->{poolid
};
94 die "pool '$pool' already exists\n" if $usercfg->{pools
}->{$pool};
96 $usercfg->{pools
}->{$pool} = {
101 $usercfg->{pools
}->{$pool}->{comment
} = $param->{comment
} if $param->{comment
};
103 cfs_write_file
("user.cfg", $usercfg);
104 }, "create pool failed");
109 __PACKAGE__-
>register_method ({
110 name
=> 'update_pool',
115 description
=> "You also need the right to modify permissions on any object you add/delete.",
116 check
=> ['perm', '/pool/{poolid}', ['Pool.Allocate']],
118 description
=> "Update pool data.",
120 additionalProperties
=> 0,
122 poolid
=> { type
=> 'string', format
=> 'pve-poolid' },
123 comment
=> { type
=> 'string', optional
=> 1 },
125 description
=> 'List of guest VMIDs to add or remove from this pool.',
126 type
=> 'string', format
=> 'pve-vmid-list',
130 description
=> 'List of storage IDs to add or remove from this pool.',
131 type
=> 'string', format
=> 'pve-storage-id-list',
135 description
=> 'Allow adding a guest even if already in another pool.'
136 .' The guest will be removed from its current pool and added to this one.',
142 description
=> 'Remove the passed VMIDs and/or storage IDs instead of adding them.',
149 returns
=> { type
=> 'null' },
153 my $rpcenv = PVE
::RPCEnvironment
::get
();
154 my $authuser = $rpcenv->get_user();
156 PVE
::AccessControl
::lock_user_config
(sub {
157 my $usercfg = cfs_read_file
("user.cfg");
158 my $pool = $param->{poolid
};
159 my $pool_config = $usercfg->{pools
}->{$pool};
161 die "pool '$pool' does not exist\n" if !$pool_config;
163 $pool_config->{comment
} = $param->{comment
} if defined($param->{comment
});
165 if (defined($param->{vms
})) {
166 for my $vmid (PVE
::Tools
::split_list
($param->{vms
})) {
167 $rpcenv->check_perm_modify($authuser, "/vms/$vmid");
169 if ($param->{delete}) {
170 die "VM $vmid is not a pool member\n" if !$pool_config->{vms
}->{$vmid};
171 delete $pool_config->{vms
}->{$vmid};
172 delete $usercfg->{vms
}->{$vmid};
174 die "VM $vmid is already a pool member\n" if $pool_config->{vms
}->{$vmid};
175 if (defined(my $existing_pool = $usercfg->{vms
}->{$vmid})) {
176 die "VM $vmid belongs already to pool '$existing_pool' and 'transfer' is not set\n"
177 if !$param->{transfer
};
179 $rpcenv->check($authuser, "/pool/$existing_pool", ['Pool.Allocate']);
180 delete $usercfg->{pools
}->{$existing_pool}->{vms
}->{$vmid};
182 $pool_config->{vms
}->{$vmid} = 1;
183 $usercfg->{vms
}->{$vmid} = $pool;
188 if (defined($param->{storage
})) {
189 for my $storeid (PVE
::Tools
::split_list
($param->{storage
})) {
190 $rpcenv->check_perm_modify($authuser, "/storage/$storeid");
192 if ($param->{delete}) {
193 die "Storage '$storeid' is not a pool member\n"
194 if !$pool_config->{storage
}->{$storeid};
195 delete $pool_config->{storage
}->{$storeid};
197 die "Storage '$storeid' is already a pool member\n"
198 if $pool_config->{storage
}->{$storeid};
200 $pool_config->{storage
}->{$storeid} = 1;
205 cfs_write_file
("user.cfg", $usercfg);
206 }, "update pools failed");
211 __PACKAGE__-
>register_method ({
216 check
=> ['perm', '/pool/{poolid}', ['Pool.Audit']],
218 description
=> "Get pool configuration.",
220 additionalProperties
=> 0,
224 format
=> 'pve-poolid',
228 enum
=> [ 'qemu', 'lxc', 'storage' ],
235 additionalProperties
=> 0,
245 additionalProperties
=> 1,
249 enum
=> [ 'qemu', 'lxc', 'openvz', 'storage' ],
273 my $usercfg = cfs_read_file
("user.cfg");
275 my $vmlist = PVE
::Cluster
::get_vmlist
() || {};
276 my $idlist = $vmlist->{ids
} || {};
278 my $rrd = PVE
::Cluster
::rrd_dump
();
280 my $pool = $param->{poolid
};
282 my $pool_config = $usercfg->{pools
}->{$pool};
284 die "pool '$pool' does not exist\n" if !$pool_config;
287 for my $vmid (sort keys %{$pool_config->{vms
}}) {
288 my $vmdata = $idlist->{$vmid};
289 next if !$vmdata || defined($param->{type
}) && $param->{type
} ne $vmdata->{type
};
290 my $entry = PVE
::API2Tools
::extract_vm_stats
($vmid, $vmdata, $rrd);
291 push @$members, $entry;
294 my $nodename = PVE
::INotify
::nodename
();
295 my $cfg = PVE
::Storage
::config
();
296 if (!defined($param->{type
}) || $param->{type
} eq 'storage') {
297 for my $storeid (sort keys %{$pool_config->{storage
}}) {
298 my $scfg = PVE
::Storage
::storage_config
($cfg, $storeid, 1);
301 my $storage_node = $nodename; # prefer local node
302 if ($scfg->{nodes
} && !$scfg->{nodes
}->{$storage_node}) {
303 for my $node (sort keys(%{$scfg->{nodes
}})) {
304 $storage_node = $node;
309 my $entry = PVE
::API2Tools
::extract_storage_stats
($storeid, $scfg, $storage_node, $rrd);
310 push @$members, $entry;
317 $res->{comment
} = $pool_config->{comment
} if defined($pool_config->{comment
});
323 __PACKAGE__-
>register_method ({
324 name
=> 'delete_pool',
329 description
=> "You can only delete empty pools (no members).",
330 check
=> ['perm', '/pool/{poolid}', ['Pool.Allocate']],
332 description
=> "Delete pool.",
334 additionalProperties
=> 0,
336 poolid
=> { type
=> 'string', format
=> 'pve-poolid' },
339 returns
=> { type
=> 'null' },
343 my $rpcenv = PVE
::RPCEnvironment
::get
();
344 my $authuser = $rpcenv->get_user();
346 PVE
::AccessControl
::lock_user_config
(sub {
347 my $vmlist = PVE
::Cluster
::get_vmlist
() || {};
348 my $idlist = $vmlist->{ids
} || {};
350 my $storecfg = PVE
::Storage
::config
();
351 my $usercfg = cfs_read_file
("user.cfg");
353 my $pool = $param->{poolid
};
355 my $pool_config = $usercfg->{pools
}->{$pool};
356 die "pool '$pool' does not exist\n" if !$pool_config;
358 for my $vmid (sort keys %{$pool_config->{vms
}}) {
359 next if !$idlist->{$vmid}; # ignore destroyed guests
360 die "pool '$pool' is not empty (contains VM $vmid)\n";
363 for my $storeid (sort keys %{$pool_config->{storage
}}) {
364 next if !PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
365 die "pool '$pool' is not empty (contains storage '$storeid')\n";
368 delete ($usercfg->{pools
}->{$pool});
369 PVE
::AccessControl
::delete_pool_acl
($pool, $usercfg);
371 cfs_write_file
("user.cfg", $usercfg);
372 }, "delete pool failed");