[pve-devel] applied: [PATCH pve-client] implement config file locking
Dietmar Maurer
dietmar at proxmox.com
Fri Jun 15 13:05:12 CEST 2018
applied
> On June 15, 2018 at 12:29 PM Dietmar Maurer <dietmar at proxmox.com> wrote:
>
>
> Signed-off-by: Dietmar Maurer <dietmar at proxmox.com>
> ---
> PVE/APIClient/Commands/config.pm | 57 +++++++++++++++--------------
> PVE/APIClient/Commands/remote.pm | 78
> ++++++++++++++++++++++++----------------
> PVE/APIClient/Config.pm | 12 +++++++
> 3 files changed, 90 insertions(+), 57 deletions(-)
>
> diff --git a/PVE/APIClient/Commands/config.pm
> b/PVE/APIClient/Commands/config.pm
> index d467b4c..3b208a0 100644
> --- a/PVE/APIClient/Commands/config.pm
> +++ b/PVE/APIClient/Commands/config.pm
> @@ -43,35 +44,37 @@ __PACKAGE__->register_method ({
> code => sub {
> my ($param) = @_;
>
> - # fixme: lock config file
> -
> my $digest = extract_param($param, 'digest');
> my $delete = extract_param($param, 'delete');
>
> - my $config = PVE::APIClient::Config->load();
> - my $defaults = PVE::APIClient::Config->get_defaults($config);
> -
> - my $plugin = PVE::APIClient::Config->lookup('defaults');
> - my $opts = $plugin->check_config('defaults', $param, 0, 1);
> -
> - foreach my $k (%$opts) {
> - $defaults->{$k} = $opts->{$k};
> - }
> -
> - if ($delete) {
> - my $options = $plugin->private()->{options}->{'defaults'};
> - foreach my $k (PVE::APIClient::Tools::split_list($delete)) {
> - my $d = $options->{$k} ||
> - die "no such option '$k'\n";
> - die "unable to delete required option '$k'\n"
> - if !$d->{optional};
> - die "unable to delete fixed option '$k'\n"
> - if $d->{fixed};
> - delete $defaults->{$k};
> + my $code = sub {
> + my $config = PVE::APIClient::Config->load();
> + my $defaults = PVE::APIClient::Config->get_defaults($config);
> +
> + my $plugin = PVE::APIClient::Config->lookup('defaults');
> + my $opts = $plugin->check_config('defaults', $param, 0, 1);
> +
> + foreach my $k (%$opts) {
> + $defaults->{$k} = $opts->{$k};
> }
> - }
>
> - PVE::APIClient::Config->save($config);
> + if ($delete) {
> + my $options = $plugin->private()->{options}->{'defaults'};
> + foreach my $k (PVE::APIClient::Tools::split_list($delete)) {
> + my $d = $options->{$k} ||
> + die "no such option '$k'\n";
> + die "unable to delete required option '$k'\n"
> + if !$d->{optional};
> + die "unable to delete fixed option '$k'\n"
> + if $d->{fixed};
> + delete $defaults->{$k};
> + }
> + }
> +
> + PVE::APIClient::Config->save($config);
> + };
> +
> + PVE::APIClient::Config->lock_config(undef, $code);
>
> return undef;
> }});
> diff --git a/PVE/APIClient/Commands/remote.pm
> b/PVE/APIClient/Commands/remote.pm
> index 090672e..03960af 100644
> --- a/PVE/APIClient/Commands/remote.pm
> +++ b/PVE/APIClient/Commands/remote.pm
> @@ -3,6 +3,7 @@ package PVE::APIClient::Commands::remote;
> use strict;
> use warnings;
>
> +use PVE::APIClient::Helpers;
> use PVE::APIClient::JSONSchema qw(get_standard_option);
> use PVE::APIClient::Tools qw(extract_param);
> use PVE::APIClient::Config;
> @@ -51,10 +52,9 @@ __PACKAGE__->register_method ({
> code => sub {
> my ($param) = @_;
>
> - # fixme: lock config file
> -
> my $remote = $param->{name};
>
> + # Note: we try to keep lock time sort, and lock later when we have all info
> my $config = PVE::APIClient::Config->load();
>
> die "Remote '$remote' already exists\n"
> @@ -90,11 +90,25 @@ __PACKAGE__->register_method ({
> $api->login();
>
> $param->{fingerprint} = $last_fp if !defined($param->{fingerprint});
> +
> my $plugin = PVE::APIClient::Config->lookup('remote');
> - my $opts = $plugin->check_config($remote, $param, 1, 1);
> - $config->{ids}->{$remote} = $opts;
>
> - PVE::APIClient::Config->save($config);
> + my $code = sub {
> +
> + $config = PVE::APIClient::Config->load(); # reload
> +
> + # check again (file is locked now)
> + die "Remote '$remote' already exists\n"
> + if $config->{ids}->{$remote};
> +
> + my $opts = $plugin->check_config($remote, $param, 1, 1);
> +
> + $config->{ids}->{$remote} = $opts;
> +
> + PVE::APIClient::Config->save($config);
> + };
> +
> + PVE::APIClient::Config->lock_config(undef, $code);
>
> return undef;
> }});
> @@ -109,36 +123,38 @@ __PACKAGE__->register_method ({
> code => sub {
> my ($param) = @_;
>
> - # fixme: lock config file
> -
> my $name = extract_param($param, 'name');
> my $digest = extract_param($param, 'digest');
> my $delete = extract_param($param, 'delete');
>
> - my $config = PVE::APIClient::Config->load();
> - my $remote = PVE::APIClient::Config->lookup_remote($config, $name);
> + my $code = sub {
> + my $config = PVE::APIClient::Config->load();
> + my $remote = PVE::APIClient::Config->lookup_remote($config, $name);
>
> - my $plugin = PVE::APIClient::Config->lookup('remote');
> - my $opts = $plugin->check_config($name, $param, 0, 1);
> + my $plugin = PVE::APIClient::Config->lookup('remote');
> + my $opts = $plugin->check_config($name, $param, 0, 1);
>
> - foreach my $k (%$opts) {
> - $remote->{$k} = $opts->{$k};
> - }
> + foreach my $k (%$opts) {
> + $remote->{$k} = $opts->{$k};
> + }
>
> - if ($delete) {
> - my $options = $plugin->private()->{options}->{'remote'};
> - foreach my $k (PVE::APIClient::Tools::APIClient::split_list($delete)) {
> - my $d = $options->{$k} ||
> - die "no such option '$k'\n";
> - die "unable to delete required option '$k'\n"
> - if !$d->{optional};
> - die "unable to delete fixed option '$k'\n"
> - if $d->{fixed};
> - delete $remote->{$k};
> + if ($delete) {
> + my $options = $plugin->private()->{options}->{'remote'};
> + foreach my $k (PVE::APIClient::Tools::APIClient::split_list($delete)) {
> + my $d = $options->{$k} ||
> + die "no such option '$k'\n";
> + die "unable to delete required option '$k'\n"
> + if !$d->{optional};
> + die "unable to delete fixed option '$k'\n"
> + if $d->{fixed};
> + delete $remote->{$k};
> + }
> }
> - }
>
> - PVE::APIClient::Config->save($config);
> + PVE::APIClient::Config->save($config);
> + };
> +
> + PVE::APIClient::Config->lock_config(undef, $code);
>
> return undef;
> }});
> @@ -158,11 +174,13 @@ __PACKAGE__->register_method ({
> code => sub {
> my ($param) = @_;
>
> - # fixme: lock config
> + my $code = sub {
> + my $config = PVE::APIClient::Config->load();
> + delete $config->{ids}->{$param->{name}};
> + PVE::APIClient::Config->save($config);
> + };
>
> - my $config = PVE::APIClient::Config->load();
> - delete $config->{ids}->{$param->{name}};
> - PVE::APIClient::Config->save($config);
> + PVE::APIClient::Config->lock_config(undef, $code);
>
> return undef;
> }});
> diff --git a/PVE/APIClient/Config.pm b/PVE/APIClient/Config.pm
> index 3878425..a4aa4c6 100644
> --- a/PVE/APIClient/Config.pm
> +++ b/PVE/APIClient/Config.pm
> @@ -64,6 +64,18 @@ sub config_filename {
> return "$dir/config";
> }
>
> +sub lock_config {
> + my ($class, $timeout, $code, @param) = @_;
> +
> + my $filename = $class->config_filename();
> +
> + my $res = PVE::APIClient::Tools::lock_file($filename, $timeout, $code,
> @param);
> +
> + die $@ if $@;
> +
> + return $res;
> +}
> +
> sub format_section_header {
> my ($class, $type, $sectionId, $scfg, $done_hash) = @_;
>
> --
> 2.11.0
>
>
More information about the pve-devel
mailing list