[pve-devel] applied: [PATCH storage 1/6] factor out scan CLI definition to real API module

Thomas Lamprecht t.lamprecht at proxmox.com
Wed Dec 2 11:51:17 CET 2020


we have a 1:1 copy of that code in pve-manager's PVE::API2::Scan,
which we can avoid by using a common module form pvesm CLI and the
API.

This is the first basic step of dropping the code duplication in
pve-manager.

Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
---

some very minor differences between both, CLI and pve-manager one, got already
resolved here.

 PVE/API2/Storage/Makefile |   2 +-
 PVE/API2/Storage/Scan.pm  | 341 +++++++++++++++++++++++++++++++++++++
 PVE/CLI/pvesm.pm          | 342 +-------------------------------------
 3 files changed, 350 insertions(+), 335 deletions(-)
 create mode 100644 PVE/API2/Storage/Scan.pm

diff --git a/PVE/API2/Storage/Makefile b/PVE/API2/Storage/Makefile
index 3f667e8..690b437 100644
--- a/PVE/API2/Storage/Makefile
+++ b/PVE/API2/Storage/Makefile
@@ -1,5 +1,5 @@
 
-SOURCES= Content.pm Status.pm Config.pm PruneBackups.pm
+SOURCES= Content.pm Status.pm Config.pm PruneBackups.pm Scan.pm
 
 .PHONY: install
 install:
diff --git a/PVE/API2/Storage/Scan.pm b/PVE/API2/Storage/Scan.pm
new file mode 100644
index 0000000..0e6fd9a
--- /dev/null
+++ b/PVE/API2/Storage/Scan.pm
@@ -0,0 +1,341 @@
+package PVE::API2::Storage::Scan;
+
+use strict;
+use warnings;
+
+# NOTE: This API endpoints are mounted by pve-manager's API2::Node module and pvesm CLI
+
+use PVE::JSONSchema qw(get_standard_option);
+use PVE::RESTHandler;
+use PVE::SafeSyslog;
+use PVE::Storage::LVMPlugin;
+use PVE::Storage;
+use PVE::SysFSTools;
+
+use base qw(PVE::RESTHandler);
+
+__PACKAGE__->register_method({
+    name => 'nfsscan',
+    path => 'nfs',
+    method => 'GET',
+    description => "Scan remote NFS server.",
+    protected => 1,
+    proxyto => "node",
+    permissions => {
+	check => ['perm', '/storage', ['Datastore.Allocate']],
+    },
+    parameters => {
+	additionalProperties => 0,
+	properties => {
+	    node => get_standard_option('pve-node'),
+	    server => {
+		description => "The server address (name or IP).",
+		type => 'string', format => 'pve-storage-server',
+	    },
+	},
+    },
+    returns => {
+	type => 'array',
+	items => {
+	    type => "object",
+	    properties => {
+		path => {
+		    description => "The exported path.",
+		    type => 'string',
+		},
+		options => {
+		    description => "NFS export options.",
+		    type => 'string',
+		},
+	    },
+	},
+    },
+    code => sub {
+	my ($param) = @_;
+
+	my $server = $param->{server};
+	my $res = PVE::Storage::scan_nfs($server);
+
+	my $data = [];
+	foreach my $k (sort keys %$res) {
+	    push @$data, { path => $k, options => $res->{$k} };
+	}
+	return $data;
+    }});
+
+__PACKAGE__->register_method({
+    name => 'cifsscan',
+    path => 'cifs',
+    method => 'GET',
+    description => "Scan remote CIFS server.",
+    protected => 1,
+    proxyto => "node",
+    permissions => {
+	check => ['perm', '/storage', ['Datastore.Allocate']],
+    },
+    parameters => {
+	additionalProperties => 0,
+	properties => {
+	    node => get_standard_option('pve-node'),
+	    server => {
+		description => "The server address (name or IP).",
+		type => 'string', format => 'pve-storage-server',
+	    },
+	    username => {
+		description => "User name.",
+		type => 'string',
+		optional => 1,
+	    },
+	    password => {
+		description => "User password.",
+		type => 'string',
+		optional => 1,
+	    },
+	    domain => {
+		description => "SMB domain (Workgroup).",
+		type => 'string',
+		optional => 1,
+	    },
+	},
+    },
+    returns => {
+	type => 'array',
+	items => {
+	    type => "object",
+	    properties => {
+		share => {
+		    description => "The cifs share name.",
+		    type => 'string',
+		},
+		description => {
+		    description => "Descriptive text from server.",
+		    type => 'string',
+		},
+	    },
+	},
+    },
+    code => sub {
+	my ($param) = @_;
+
+	my $server = $param->{server};
+
+	my $username = $param->{username};
+	my $password = $param->{password};
+	my $domain = $param->{domain};
+
+	my $res = PVE::Storage::scan_cifs($server, $username, $password, $domain);
+
+	my $data = [];
+	foreach my $k (sort keys %$res) {
+	    push @$data, { share => $k, description => $res->{$k} };
+	}
+
+	return $data;
+    }});
+
+# Note: GlusterFS currently does not have an equivalent of showmount.
+# As workaround, we simply use nfs showmount.
+# see http://www.gluster.org/category/volumes/
+__PACKAGE__->register_method({
+    name => 'glusterfsscan',
+    path => 'glusterfs',
+    method => 'GET',
+    description => "Scan remote GlusterFS server.",
+    protected => 1,
+    proxyto => "node",
+    permissions => {
+	check => ['perm', '/storage', ['Datastore.Allocate']],
+    },
+    parameters => {
+	additionalProperties => 0,
+	properties => {
+	    node => get_standard_option('pve-node'),
+	    server => {
+		description => "The server address (name or IP).",
+		type => 'string', format => 'pve-storage-server',
+	    },
+	},
+    },
+    returns => {
+	type => 'array',
+	items => {
+	    type => "object",
+	    properties => {
+		volname => {
+		    description => "The volume name.",
+		    type => 'string',
+		},
+	    },
+	},
+    },
+    code => sub {
+	my ($param) = @_;
+
+	my $server = $param->{server};
+	my $res = PVE::Storage::scan_nfs($server);
+
+	my $data = [];
+	foreach my $path (sort keys %$res) {
+	    if ($path =~ m!^/([^\s/]+)$!) {
+		push @$data, { volname => $1 };
+	    }
+	}
+	return $data;
+    }});
+
+__PACKAGE__->register_method({
+    name => 'iscsiscan',
+    path => 'iscsi',
+    method => 'GET',
+    description => "Scan remote iSCSI server.",
+    protected => 1,
+    proxyto => "node",
+    permissions => {
+	check => ['perm', '/storage', ['Datastore.Allocate']],
+    },
+    parameters => {
+	additionalProperties => 0,
+	properties => {
+	    node => get_standard_option('pve-node'),
+	    portal => {
+		description => "The iSCSI portal (IP or DNS name with optional port).",
+		type => 'string', format => 'pve-storage-portal-dns',
+	    },
+	},
+    },
+    returns => {
+	type => 'array',
+	items => {
+	    type => "object",
+	    properties => {
+		target => {
+		    description => "The iSCSI target name.",
+		    type => 'string',
+		},
+		portal => {
+		    description => "The iSCSI portal name.",
+		    type => 'string',
+		},
+	    },
+	},
+    },
+    code => sub {
+	my ($param) = @_;
+
+	my $res = PVE::Storage::scan_iscsi($param->{portal});
+
+	my $data = [];
+	foreach my $k (sort keys %$res) {
+	    push @$data, { target => $k, portal => join(',', @{$res->{$k}}) };
+	}
+
+	return $data;
+    }});
+
+__PACKAGE__->register_method({
+    name => 'lvmscan',
+    path => 'lvm',
+    method => 'GET',
+    description => "List local LVM volume groups.",
+    protected => 1,
+    proxyto => "node",
+    permissions => {
+	check => ['perm', '/storage', ['Datastore.Allocate']],
+    },
+    parameters => {
+	additionalProperties => 0,
+	properties => {
+	    node => get_standard_option('pve-node'),
+	},
+    },
+    returns => {
+	type => 'array',
+	items => {
+	    type => "object",
+	    properties => {
+		vg => {
+		    description => "The LVM logical volume group name.",
+		    type => 'string',
+		},
+	    },
+	},
+    },
+    code => sub {
+	my ($param) = @_;
+
+	my $res = PVE::Storage::LVMPlugin::lvm_vgs();
+	return PVE::RESTHandler::hash_to_array($res, 'vg');
+    }});
+
+__PACKAGE__->register_method({
+    name => 'lvmthinscan',
+    path => 'lvmthin',
+    method => 'GET',
+    description => "List local LVM Thin Pools.",
+    protected => 1,
+    proxyto => "node",
+    permissions => {
+	check => ['perm', '/storage', ['Datastore.Allocate']],
+    },
+    parameters => {
+	additionalProperties => 0,
+	properties => {
+	    node => get_standard_option('pve-node'),
+	    vg => {
+		type => 'string',
+		pattern => '[a-zA-Z0-9\.\+\_][a-zA-Z0-9\.\+\_\-]+', # see lvm(8) manpage
+		maxLength => 100,
+	    },
+	},
+    },
+    returns => {
+	type => 'array',
+	items => {
+	    type => "object",
+	    properties => {
+		lv => {
+		    description => "The LVM Thin Pool name (LVM logical volume).",
+		    type => 'string',
+		},
+	    },
+	},
+    },
+    code => sub {
+	my ($param) = @_;
+
+	return PVE::Storage::LvmThinPlugin::list_thinpools($param->{vg});
+    }});
+
+__PACKAGE__->register_method({
+    name => 'zfsscan',
+    path => 'zfs',
+    method => 'GET',
+    description => "Scan zfs pool list on local node.",
+    protected => 1,
+    proxyto => "node",
+    permissions => {
+	check => ['perm', '/storage', ['Datastore.Allocate']],
+    },
+    parameters => {
+	additionalProperties => 0,
+	properties => {
+	    node => get_standard_option('pve-node'),
+	},
+    },
+    returns => {
+	type => 'array',
+	items => {
+	    type => "object",
+	    properties => {
+		pool => {
+		    description => "ZFS pool name.",
+		    type => 'string',
+		},
+	    },
+	},
+    },
+    code => sub {
+	my ($param) = @_;
+
+	return PVE::Storage::scan_zfs();
+    }});
diff --git a/PVE/CLI/pvesm.pm b/PVE/CLI/pvesm.pm
index a2246cc..bc48617 100755
--- a/PVE/CLI/pvesm.pm
+++ b/PVE/CLI/pvesm.pm
@@ -16,6 +16,7 @@ use PVE::Tools qw(extract_param);
 use PVE::API2::Storage::Config;
 use PVE::API2::Storage::Content;
 use PVE::API2::Storage::PruneBackups;
+use PVE::API2::Storage::Scan;
 use PVE::API2::Storage::Status;
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::PTY;
@@ -406,333 +407,6 @@ __PACKAGE__->register_method ({
     }
 });
 
-__PACKAGE__->register_method ({
-    name => 'nfsscan',
-    path => 'nfs',
-    method => 'GET',
-    description => "Scan remote NFS server.",
-    protected => 1,
-    proxyto => "node",
-    permissions => {
-	check => ['perm', '/storage', ['Datastore.Allocate']],
-    },
-    parameters => {
-	additionalProperties => 0,
-	properties => {
-	    node => get_standard_option('pve-node'),
-	    server => {
-		description => "The server address (name or IP).",
-		type => 'string', format => 'pve-storage-server',
-	    },
-	},
-    },
-    returns => {
-	type => 'array',
-	items => {
-	    type => "object",
-	    properties => {
-		path => {
-		    description => "The exported path.",
-		    type => 'string',
-		},
-		options => {
-		    description => "NFS export options.",
-		    type => 'string',
-		},
-	    },
-	},
-    },
-    code => sub {
-	my ($param) = @_;
-
-	my $server = $param->{server};
-	my $res = PVE::Storage::scan_nfs($server);
-
-	my $data = [];
-	foreach my $k (sort keys %$res) {
-	    push @$data, { path => $k, options => $res->{$k} };
-	}
-	return $data;
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'cifsscan',
-    path => 'cifs',
-    method => 'GET',
-    description => "Scan remote CIFS server.",
-    protected => 1,
-    proxyto => "node",
-    permissions => {
-	check => ['perm', '/storage', ['Datastore.Allocate']],
-    },
-    parameters => {
-	additionalProperties => 0,
-	properties => {
-	    node => get_standard_option('pve-node'),
-	    server => {
-		description => "The server address (name or IP).",
-		type => 'string', format => 'pve-storage-server',
-	    },
-	    username => {
-		description => "User name.",
-		type => 'string',
-		optional => 1,
-	    },
-	    password => {
-		description => "User password.",
-		type => 'string',
-		optional => 1,
-	    },
-	    domain => {
-		description => "SMB domain (Workgroup).",
-		type => 'string',
-		optional => 1,
-	    },
-	},
-    },
-    returns => {
-	type => 'array',
-	items => {
-	    type => "object",
-	    properties => {
-		share => {
-		    description => "The cifs share name.",
-		    type => 'string',
-		},
-		description => {
-		    description => "Descriptive text from server.",
-		    type => 'string',
-		},
-	    },
-	},
-    },
-    code => sub {
-	my ($param) = @_;
-
-	my $server = $param->{server};
-
-	my $username = $param->{username};
-	my $password = $param->{password};
-	my $domain = $param->{domain};
-
-	my $res = PVE::Storage::scan_cifs($server, $username, $password, $domain);
-
-	my $data = [];
-	foreach my $k (sort keys %$res) {
-	    push @$data, { share => $k, description => $res->{$k} };
-	}
-
-	return $data;
-    }});
-
-# Note: GlusterFS currently does not have an equivalent of showmount.
-# As workaround, we simply use nfs showmount.
-# see http://www.gluster.org/category/volumes/
-
-__PACKAGE__->register_method ({
-    name => 'glusterfsscan',
-    path => 'glusterfs',
-    method => 'GET',
-    description => "Scan remote GlusterFS server.",
-    protected => 1,
-    proxyto => "node",
-    permissions => {
-	check => ['perm', '/storage', ['Datastore.Allocate']],
-    },
-    parameters => {
-	additionalProperties => 0,
-	properties => {
-	    node => get_standard_option('pve-node'),
-	    server => {
-		description => "The server address (name or IP).",
-		type => 'string', format => 'pve-storage-server',
-	    },
-	},
-    },
-    returns => {
-	type => 'array',
-	items => {
-	    type => "object",
-	    properties => {
-		volname => {
-		    description => "The volume name.",
-		    type => 'string',
-		},
-	    },
-	},
-    },
-    code => sub {
-	my ($param) = @_;
-
-	my $server = $param->{server};
-	my $res = PVE::Storage::scan_nfs($server);
-
-	my $data = [];
-	foreach my $path (sort keys %$res) {
-	    if ($path =~ m!^/([^\s/]+)$!) {
-		push @$data, { volname => $1 };
-	    }
-	}
-	return $data;
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'iscsiscan',
-    path => 'iscsi',
-    method => 'GET',
-    description => "Scan remote iSCSI server.",
-    protected => 1,
-    proxyto => "node",
-    permissions => {
-	check => ['perm', '/storage', ['Datastore.Allocate']],
-    },
-    parameters => {
-	additionalProperties => 0,
-	properties => {
-	    node => get_standard_option('pve-node'),
-	    portal => {
-		description => "The iSCSI portal (IP or DNS name with optional port).",
-		type => 'string', format => 'pve-storage-portal-dns',
-	    },
-	},
-    },
-    returns => {
-	type => 'array',
-	items => {
-	    type => "object",
-	    properties => {
-		target => {
-		    description => "The iSCSI target name.",
-		    type => 'string',
-		},
-		portal => {
-		    description => "The iSCSI portal name.",
-		    type => 'string',
-		},
-	    },
-	},
-    },
-    code => sub {
-	my ($param) = @_;
-
-	my $res = PVE::Storage::scan_iscsi($param->{portal});
-
-	my $data = [];
-	foreach my $k (sort keys %$res) {
-	    push @$data, { target => $k, portal => join(',', @{$res->{$k}}) };
-	}
-
-	return $data;
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'lvmscan',
-    path => 'lvm',
-    method => 'GET',
-    description => "List local LVM volume groups.",
-    protected => 1,
-    proxyto => "node",
-    permissions => {
-	check => ['perm', '/storage', ['Datastore.Allocate']],
-    },
-    parameters => {
-	additionalProperties => 0,
-	properties => {
-	    node => get_standard_option('pve-node'),
-	},
-    },
-    returns => {
-	type => 'array',
-	items => {
-	    type => "object",
-	    properties => {
-		vg => {
-		    description => "The LVM logical volume group name.",
-		    type => 'string',
-		},
-	    },
-	},
-    },
-    code => sub {
-	my ($param) = @_;
-
-	my $res = PVE::Storage::LVMPlugin::lvm_vgs();
-	return PVE::RESTHandler::hash_to_array($res, 'vg');
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'lvmthinscan',
-    path => 'lvmthin',
-    method => 'GET',
-    description => "List local LVM Thin Pools.",
-    protected => 1,
-    proxyto => "node",
-    permissions => {
-	check => ['perm', '/storage', ['Datastore.Allocate']],
-    },
-    parameters => {
-	additionalProperties => 0,
-	properties => {
-	    node => get_standard_option('pve-node'),
-	    vg => {
-		type => 'string',
-		pattern => '[a-zA-Z0-9\.\+\_][a-zA-Z0-9\.\+\_\-]+', # see lvm(8) manpage
-		maxLength => 100,
-	    },
-	},
-    },
-    returns => {
-	type => 'array',
-	items => {
-	    type => "object",
-	    properties => {
-		lv => {
-		    description => "The LVM Thin Pool name (LVM logical volume).",
-		    type => 'string',
-		},
-	    },
-	},
-    },
-    code => sub {
-	my ($param) = @_;
-
-	return PVE::Storage::LvmThinPlugin::list_thinpools($param->{vg});
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'zfsscan',
-    path => 'zfs',
-    method => 'GET',
-    description => "Scan zfs pool list on local node.",
-    protected => 1,
-    proxyto => "node",
-    permissions => {
-	check => ['perm', '/storage', ['Datastore.Allocate']],
-    },
-    parameters => {
-	additionalProperties => 0,
-	properties => {
-	    node => get_standard_option('pve-node'),
-	},
-    },
-    returns => {
-	type => 'array',
-	items => {
-	    type => "object",
-	    properties => {
-		pool => {
-		    description => "ZFS pool name.",
-		    type => 'string',
-		},
-	    },
-	},
-    },
-    code => sub {
-	my ($param) = @_;
-
-	return PVE::Storage::scan_zfs();
-    }});
-
 __PACKAGE__->register_method ({
     name => 'prunebackups',
     path => 'prunebackups',
@@ -847,7 +521,7 @@ our $cmddef = {
     free => [ "PVE::API2::Storage::Content", 'delete', ['volume'],
 	      { node => $nodename } ],
     scan => {
-	nfs => [ __PACKAGE__, 'nfsscan', ['server'], { node => $nodename }, sub  {
+	nfs => [ "PVE::API2::Storage::Scan", 'nfsscan', ['server'], { node => $nodename }, sub  {
 	    my $res = shift;
 
 	    my $maxlen = 0;
@@ -859,7 +533,7 @@ our $cmddef = {
 		printf "%-${maxlen}s %s\n", $rec->{path}, $rec->{options};
 	    }
 	}],
-	cifs => [ __PACKAGE__, 'cifsscan', ['server'], { node => $nodename }, sub  {
+	cifs => [ "PVE::API2::Storage::Scan", 'cifsscan', ['server'], { node => $nodename }, sub  {
 	    my $res = shift;
 
 	    my $maxlen = 0;
@@ -871,14 +545,14 @@ our $cmddef = {
 		printf "%-${maxlen}s %s\n", $rec->{share}, $rec->{description};
 	    }
 	}],
-	glusterfs => [ __PACKAGE__, 'glusterfsscan', ['server'], { node => $nodename }, sub  {
+	glusterfs => [ "PVE::API2::Storage::Scan", 'glusterfsscan', ['server'], { node => $nodename }, sub  {
 	    my $res = shift;
 
 	    foreach my $rec (@$res) {
 		printf "%s\n", $rec->{volname};
 	    }
 	}],
-	iscsi => [ __PACKAGE__, 'iscsiscan', ['portal'], { node => $nodename }, sub  {
+	iscsi => [ "PVE::API2::Storage::Scan", 'iscsiscan', ['portal'], { node => $nodename }, sub  {
 	    my $res = shift;
 
 	    my $maxlen = 0;
@@ -890,19 +564,19 @@ our $cmddef = {
 		printf "%-${maxlen}s %s\n", $rec->{target}, $rec->{portal};
 	    }
 	}],
-	lvm => [ __PACKAGE__, 'lvmscan', [], { node => $nodename }, sub  {
+	lvm => [ "PVE::API2::Storage::Scan", 'lvmscan', [], { node => $nodename }, sub  {
 	    my $res = shift;
 	    foreach my $rec (@$res) {
 		printf "$rec->{vg}\n";
 	    }
 	}],
-	lvmthin => [ __PACKAGE__, 'lvmthinscan', ['vg'], { node => $nodename }, sub  {
+	lvmthin => [ "PVE::API2::Storage::Scan", 'lvmthinscan', ['vg'], { node => $nodename }, sub  {
 	    my $res = shift;
 	    foreach my $rec (@$res) {
 		printf "$rec->{lv}\n";
 	    }
 	}],
-	zfs => [ __PACKAGE__, 'zfsscan', [], { node => $nodename }, sub  {
+	zfs => [ "PVE::API2::Storage::Scan", 'zfsscan', [], { node => $nodename }, sub  {
 	    my $res = shift;
 
 	    foreach my $rec (@$res) {
-- 
2.20.1






More information about the pve-devel mailing list