From a3cf990d5a67aaf222e934f6d7d06feda9ce00b1 Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Mon, 14 Sep 2015 17:21:54 +0200 Subject: [PATCH] move ha-manager to separate CLIHandler class Move ha-manager to separate CLIHandler class and add basic auto completion support. Signed-off-by: Thomas Lamprecht --- src/Makefile | 17 ++-- src/PVE/CLI/Makefile | 6 ++ src/PVE/CLI/ha_manager.pm | 175 ++++++++++++++++++++++++++++++++++++ src/PVE/Makefile | 1 + src/ha-manager | 185 +------------------------------------- 5 files changed, 196 insertions(+), 188 deletions(-) create mode 100644 src/PVE/CLI/Makefile create mode 100644 src/PVE/CLI/ha_manager.pm diff --git a/src/Makefile b/src/Makefile index dd96b55..d2cdd8e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,6 +9,7 @@ DOCDIR=${PREFIX}/share/doc/${PACKAGE} SIMDOCDIR=${PREFIX}/share/doc/${SIMPACKAGE} PODDIR=${DOCDIR}/pod MAN1DIR=${MANDIR}/man1/ +BASHCOMPLDIR=${PREFIX}/share/bash-completion/completions/ export PERLDIR=${PREFIX}/share/perl5 all: watchdog-mux @@ -23,22 +24,28 @@ pve-ha-crm.1.pod: pve-ha-crm pve-ha-lrm.1.pod: pve-ha-lrm perl -I. ./pve-ha-lrm printmanpod >$@ -ha-manager.1.pod: ha-manager - perl -I. ./ha-manager printmanpod >$@ +ha-manager.1.pod: + perl -I. -T -e "use PVE::CLI::ha_manager; PVE::CLI::ha_manager->generate_pod_manpage();" >$@.tmp + mv $@.tmp $@ + +ha-manager.bash-completion: + perl -I. -T -e "use PVE::CLI::ha_manager; PVE::CLI::ha_manager->generate_bash_completions();" >$@ + watchdog-mux: watchdog-mux.c gcc watchdog-mux.c -o watchdog-mux -Wall -Wl,-z,relro $$(pkg-config --libs --cflags libsystemd-daemon) .PHONY: install -install: watchdog-mux pve-ha-crm pve-ha-lrm ha-manager.1.pod ha-manager.1.gz pve-ha-crm.1.pod pve-ha-crm.1.gz pve-ha-lrm.1.pod pve-ha-lrm.1.gz +install: watchdog-mux pve-ha-crm pve-ha-lrm ha-manager.1.pod ha-manager.1.gz pve-ha-crm.1.pod pve-ha-crm.1.gz pve-ha-lrm.1.pod pve-ha-lrm.1.gz ha-manager.bash-completion perl -I. ./pve-ha-crm verifyapi perl -I. ./pve-ha-lrm verifyapi - perl -I. ./ha-manager verifyapi + perl -I. -T -e "use PVE::CLI::ha_manager; PVE::CLI::ha_manager->verify_api();" install -d ${DESTDIR}${SBINDIR} install -m 0755 pve-ha-crm ${DESTDIR}${SBINDIR} install -m 0755 pve-ha-lrm ${DESTDIR}${SBINDIR} install -m 0755 ha-manager ${DESTDIR}${SBINDIR} install -m 0755 watchdog-mux ${DESTDIR}${SBINDIR} + install -m 0644 -D ha-manager.bash-completion ${DESTDIR}${BASHCOMPLDIR}/ha-manager make -C PVE install install -d ${DESTDIR}/usr/share/man/man1 install -d ${DESTDIR}${PODDIR} @@ -62,7 +69,7 @@ test: .PHONY: clean clean: make -C test clean - rm -rf watchdog-mux *.1.pod *.1.gz + rm -rf watchdog-mux *.1.pod *.1.gz *.bash-completion find . -name '*~' -exec rm {} ';' .PHONY: distclean diff --git a/src/PVE/CLI/Makefile b/src/PVE/CLI/Makefile new file mode 100644 index 0000000..d1f170f --- /dev/null +++ b/src/PVE/CLI/Makefile @@ -0,0 +1,6 @@ +SOURCES=ha_manager.pm + +.PHONY: install +install: ${SOURCES} + install -d -m 0755 ${DESTDIR}${PERLDIR}/PVE/CLI + for i in ${SOURCES}; do install -D -m 0644 $$i ${DESTDIR}${PERLDIR}/PVE/CLI/$$i; done diff --git a/src/PVE/CLI/ha_manager.pm b/src/PVE/CLI/ha_manager.pm new file mode 100644 index 0000000..8c7b17a --- /dev/null +++ b/src/PVE/CLI/ha_manager.pm @@ -0,0 +1,175 @@ +package PVE::CLI::ha_manager; + +use strict; +use warnings; +use Data::Dumper; + +use PVE::INotify; +use JSON; + +use PVE::JSONSchema qw(get_standard_option); +use PVE::CLIHandler; +use PVE::Cluster; + +use PVE::HA::Tools; +use PVE::API2::HA::Resources; +use PVE::API2::HA::Groups; +use PVE::API2::HA::Status; +use PVE::HA::Env::PVE2; + +use base qw(PVE::CLIHandler); + +our $exename = 'ha-manager'; + +my $nodename = PVE::INotify::nodename(); + +__PACKAGE__->register_method ({ + name => 'enable', + path => 'enable', + method => 'POST', + description => "Enable a HA resource.", + parameters => { + additionalProperties => 0, + properties => { + sid => get_standard_option('pve-ha-resource-or-vm-id'), + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $sid = PVE::HA::Tools::parse_sid($param->{sid}); + + # delete state (default is 'enabled') + PVE::API2::HA::Resources->update({ sid => $sid, delete => 'state' }); + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'disable', + path => 'disable', + method => 'POST', + description => "Disable a HA resource.", + parameters => { + additionalProperties => 0, + properties => { + sid => get_standard_option('pve-ha-resource-or-vm-id'), + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $sid = PVE::HA::Tools::parse_sid($param->{sid}); + + PVE::API2::HA::Resources->update({ sid => $sid, state => 'disabled' }); + + return undef; + }}); + +my $timestamp_to_status = sub { + my ($ctime, $timestamp) = @_; + + my $tdiff = $ctime - $timestamp; + if ($tdiff > 30) { + return "old timestamp - dead?"; + } elsif ($tdiff < -2) { + return "detected time drift!"; + } else { + return "active"; + } +}; + +__PACKAGE__->register_method ({ + name => 'status', + path => 'status', + method => 'GET', + description => "Display HA manger status.", + parameters => { + additionalProperties => 0, + properties => { + verbose => { + description => "Verbose output. Include complete CRM and LRM status (JSON).", + type => 'boolean', + default => 0, + optional => 1, + } + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $res = PVE::API2::HA::Status->status({}); + foreach my $e (@$res) { + print "$e->{type} $e->{status}\n"; + } + + if ($param->{verbose}) { + print "full cluster state:\n"; + my $data = PVE::API2::HA::Status->manager_status({}); + print to_json($data, { pretty => 1, canonical => 1} ); + } + + return undef; + }}); + +our $cmddef = { + enable => [ __PACKAGE__, 'enable', ['sid']], + disable => [ __PACKAGE__, 'disable', ['sid']], + status => [ __PACKAGE__, 'status'], + config => [ 'PVE::API2::HA::Resources', 'index', [], {}, sub { + my $res = shift; + foreach my $rec (sort { $a->{sid} cmp $b->{sid} } @$res) { + my ($type, $name) = split(':', $rec->{sid}, 2); + print "$type:$name\n"; + foreach my $k (sort keys %$rec) { + next if $k eq 'digest' || $k eq 'sid' || + $k eq 'type' || $k eq 'errors'; + print "\t$k $rec->{$k}\n"; + } + if (my $errors = $rec->{errors}) { + foreach my $p (keys %$errors) { + warn "error: property '$p' - $errors->{$p}\n"; + } + } + print "\n"; + }}], + groups => [ 'PVE::API2::HA::Groups', 'index', [], {}, sub { + my $res = shift; + foreach my $rec (sort { $a->{group} cmp $b->{group} } @$res) { + print "group: $rec->{group}\n"; + foreach my $k (sort keys %$rec) { + next if $k eq 'digest' || $k eq 'group' || + $k eq 'type'; + print "\t$k $rec->{$k}\n"; + } + print "\n"; + }}], + add => [ "PVE::API2::HA::Resources", 'create', ['sid'] ], + remove => [ "PVE::API2::HA::Resources", 'delete', ['sid'] ], + set => [ "PVE::API2::HA::Resources", 'update', ['sid'] ], + + migrate => [ "PVE::API2::HA::Resources", 'migrate', ['sid', 'node'] ], + relocate => [ "PVE::API2::HA::Resources", 'relocate', ['sid', 'node'] ], + +}; + +1; + +__END__ + +=head1 NAME + +pvecm - Proxmox VE HA Command Line Interface + +=head1 SYNOPSIS + +=include synopsis + +=head1 DESCRIPTION + +ha-manager is a program to manage the HA configuration. + +=include pve_copyright diff --git a/src/PVE/Makefile b/src/PVE/Makefile index b238452..6012c2c 100644 --- a/src/PVE/Makefile +++ b/src/PVE/Makefile @@ -4,6 +4,7 @@ install: install -d -m 0755 ${DESTDIR}${PERLDIR}/PVE make -C HA install make -C API2 install + make -C CLI install .PHONY: installsim installsim: diff --git a/src/ha-manager b/src/ha-manager index e3e0348..a989f70 100755 --- a/src/ha-manager +++ b/src/ha-manager @@ -2,188 +2,7 @@ use strict; use warnings; -use Data::Dumper; - -use PVE::INotify; -use JSON; - -use PVE::JSONSchema qw(get_standard_option); -use PVE::CLIHandler; -use PVE::Cluster; - -use PVE::HA::Tools; -use PVE::API2::HA::Resources; -use PVE::API2::HA::Groups; -use PVE::API2::HA::Status; -use PVE::HA::Env::PVE2; - -use base qw(PVE::CLIHandler); - -$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin'; -$ENV{LC_ALL} = 'C'; - -die "please run as root\n" if $> != 0; - -my $nodename = PVE::INotify::nodename(); - -__PACKAGE__->register_method ({ - name => 'enable', - path => 'enable', - method => 'POST', - description => "Enable a HA resource.", - parameters => { - additionalProperties => 0, - properties => { - sid => get_standard_option('pve-ha-resource-or-vm-id'), - }, - }, - returns => { type => 'null' }, - code => sub { - my ($param) = @_; - - my $sid = PVE::HA::Tools::parse_sid($param->{sid}); - - # delete state (default is 'enabled') - PVE::API2::HA::Resources->update({ sid => $sid, delete => 'state' }); - - return undef; - }}); - -__PACKAGE__->register_method ({ - name => 'disable', - path => 'disable', - method => 'POST', - description => "Disable a HA resource.", - parameters => { - additionalProperties => 0, - properties => { - sid => get_standard_option('pve-ha-resource-or-vm-id'), - }, - }, - returns => { type => 'null' }, - code => sub { - my ($param) = @_; - - my $sid = PVE::HA::Tools::parse_sid($param->{sid}); - - PVE::API2::HA::Resources->update({ sid => $sid, state => 'disabled' }); - - return undef; - }}); - -my $timestamp_to_status = sub { - my ($ctime, $timestamp) = @_; - - my $tdiff = $ctime - $timestamp; - if ($tdiff > 30) { - return "old timestamp - dead?"; - } elsif ($tdiff < -2) { - return "detected time drift!"; - } else { - return "active"; - } -}; - -__PACKAGE__->register_method ({ - name => 'status', - path => 'status', - method => 'GET', - description => "Display HA manger status.", - parameters => { - additionalProperties => 0, - properties => { - verbose => { - description => "Verbose output. Include complete CRM and LRM status (JSON).", - type => 'boolean', - default => 0, - optional => 1, - } - }, - }, - returns => { type => 'null' }, - code => sub { - my ($param) = @_; - - my $res = PVE::API2::HA::Status->status({}); - foreach my $e (@$res) { - print "$e->{type} $e->{status}\n"; - } - - if ($param->{verbose}) { - print "full cluster state:\n"; - my $data = PVE::API2::HA::Status->manager_status({}); - print to_json($data, { pretty => 1, canonical => 1} ); - } - - return undef; - }}); - -my $cmddef = { - enable => [ __PACKAGE__, 'enable', ['sid']], - disable => [ __PACKAGE__, 'disable', ['sid']], - status => [ __PACKAGE__, 'status'], - config => [ 'PVE::API2::HA::Resources', 'index', [], {}, sub { - my $res = shift; - foreach my $rec (sort { $a->{sid} cmp $b->{sid} } @$res) { - my ($type, $name) = split(':', $rec->{sid}, 2); - print "$type:$name\n"; - foreach my $k (sort keys %$rec) { - next if $k eq 'digest' || $k eq 'sid' || - $k eq 'type' || $k eq 'errors'; - print "\t$k $rec->{$k}\n"; - } - if (my $errors = $rec->{errors}) { - foreach my $p (keys %$errors) { - warn "error: property '$p' - $errors->{$p}\n"; - } - } - print "\n"; - }}], - groups => [ 'PVE::API2::HA::Groups', 'index', [], {}, sub { - my $res = shift; - foreach my $rec (sort { $a->{group} cmp $b->{group} } @$res) { - print "group: $rec->{group}\n"; - foreach my $k (sort keys %$rec) { - next if $k eq 'digest' || $k eq 'group' || - $k eq 'type'; - print "\t$k $rec->{$k}\n"; - } - print "\n"; - }}], - add => [ "PVE::API2::HA::Resources", 'create', ['sid'] ], - remove => [ "PVE::API2::HA::Resources", 'delete', ['sid'] ], - set => [ "PVE::API2::HA::Resources", 'update', ['sid'] ], - - migrate => [ "PVE::API2::HA::Resources", 'migrate', ['sid', 'node'] ], - relocate => [ "PVE::API2::HA::Resources", 'relocate', ['sid', 'node'] ], - -}; - -my $cmd = shift; - -if ($cmd && $cmd ne 'printmanpod' && $cmd ne 'verifyapi') { - PVE::Cluster::check_cfs_is_mounted(); - PVE::Cluster::cfs_update(); -} - -PVE::CLIHandler::handle_cmd($cmddef, "ha-manager", $cmd, \@ARGV, undef, $0); - -exit 0; - -__END__ - -=head1 NAME - -pvecm - Proxmox VE HA Command Line Interface - -=head1 SYNOPSIS - -=include synopsis - -=head1 DESCRIPTION - -ha-manager is a program to manage the HA configuration. - -=include pve_copyright +use PVE::CLI::ha_manager; +PVE::CLI::ha_manager->run_cli(); -- 2.39.5