#! /usr/bin/perl # ----------------------------------------------------------------------------- # Copyright (c) 2006, 2007 - OpenSLX GmbH # # This program is free software distributed under the GPL version 2. # See http://openslx.org/COPYING # # If you have any feedback please consult http://openslx.org/feedback and # send your suggestions, praise, or complaints to feedback@openslx.org # # General information about OpenSLX can be found at http://openslx.org/ # ----------------------------------------------------------------------------- use strict; use warnings; my $abstract = q[ slxconfig This script can be used to display or change the OpenSLX configuration database. You can create systems that use a specific vendor-OS and you can create clients for these systems, too. ]; use Getopt::Long qw(:config pass_through); use Pod::Usage; # add the folder this script lives in and the lib-folder to perl's # search path for modules: use FindBin; use lib "$FindBin::RealBin"; use lib "$FindBin::RealBin/../lib"; use lib "$FindBin::RealBin/../config-db"; # development path to config-db use OpenSLX::Basics; use OpenSLX::ConfigDB; use OpenSLX::ConfigFolder; use OpenSLX::DBSchema; use OpenSLX::Utils; my ( $helpReq, $manReq, $verbose, $versionReq, ); GetOptions( 'help|?' => \$helpReq, 'man' => \$manReq, 'verbose' => \$verbose, 'version' => \$versionReq, ) or pod2usage(2); pod2usage(-msg => $abstract, -verbose => 0, -exitval => 1) if $helpReq; if ($manReq) { $ENV{LANG} = 'en_EN'; # avoid dubious problem with perldoc in combination with UTF-8 that # leads to strange dashes and single-quotes being used pod2usage(-verbose => 2) } if ($versionReq) { system('slxversion'); exit 1; } openslxInit(); my $openslxDB = OpenSLX::ConfigDB->new(); $openslxDB->connect(); my $action = shift @ARGV || ''; if ($action =~ m[^add-system$]i) { addSystemToConfigDB(@ARGV); } elsif ($action =~ m[^add-client$]i) { addClientToConfigDB(@ARGV); } elsif ($action =~ m[^change-system$]i) { changeSystemInConfigDB(@ARGV); } elsif ($action =~ m[^change-client$]i) { changeClientInConfigDB(@ARGV); } elsif ($action =~ m[^list-c]) { print _tr("List of clients:\n"); listClients(@ARGV); } elsif ($action =~ m[^list-e]) { print _tr("List of exports:\n"); listExports(@ARGV); } elsif ($action =~ m[^list-s]) { print _tr("List of systems:\n"); listSystems(@ARGV); } elsif ($action =~ m[^list-v]) { print _tr("List of vendor-OSes:\n"); listVendorOSes(@ARGV); } elsif ($action =~ m[^search-c]) { print _tr("Matching clients:\n"); searchClients(@ARGV); } elsif ($action =~ m[^search-e]) { print _tr("Matching exports:\n"); searchExports(@ARGV); } elsif ($action =~ m[^search-s]) { print _tr("Matching systems:\n"); searchSystems(@ARGV); } elsif ($action =~ m[^search-v]) { print _tr("Matching vendor-OSes:\n"); searchVendorOSes(@ARGV); } elsif ($action =~ m[^remove-client$]i) { removeClientFromConfigDB(@ARGV); } elsif ($action =~ m[^remove-system$]i) { removeSystemFromConfigDB(@ARGV); } else { vlog(0, _tr(unshiftHereDoc(<<' END-OF-HERE'), $0)); You need to specify exactly one of these actions: add-client add-system change-client change-system list-client list-export list-system list-vendoros remove-client remove-system search-client search-export search-system search-vendoros Try '%s --help' for more info. END-OF-HERE } $openslxDB->disconnect(); sub parseKeyValueArgs { my $allowedKeys = shift; my $table = shift; my %dataHash; while (my $param = shift) { if ($param !~ m[^\s*([\w\-]+)\s*=(.+)$]) { die _tr("value specification %s has unknown format, expected =\n", $param); } my $key = lc($1); my $value = $2; if (!grep { $_ eq $key } @$allowedKeys) { die _tr("unknown attribute '%s' specified for %s\n", $key, $table); } $dataHash{$key} = $value; } return \%dataHash; } sub dumpElements { my $objName = shift; my $nameClause = shift || sub { "\t$_->{name}\n" }; if ($verbose) { foreach my $elem (@_) { print "$objName '$elem->{name}':\n"; print join( '', map { my $spc = ' 'x25; my $val = $elem->{$_} || ''; $val =~ s[\n][\n\t$spc ]g; "\t$_" .substr($spc, length($_)) ." = $val\n"; } sort keys %$elem ); } } else { print join('', sort map { $nameClause->($_); } @_); } return; } sub listClients { my $name = shift; my %nameSpec; # set verbose mode if any params have been passed in: if (defined $name) { $verbose = 1; $nameSpec{name} = $name; } dumpElements( 'client', undef, map { my @sysIDs = $openslxDB->aggregatedSystemIDsOfClient($_); $_->{systems} = join "\n", map { $_->{name} } sort { $a->{name} cmp $b->{name} } $openslxDB->fetchSystemByID(\@sysIDs, 'name'); $_; } sort { $a->{name} cmp $b->{name} } $openslxDB->fetchClientByFilter(\%nameSpec) ); return; } sub listExports { my $name = shift; my %nameSpec; # set verbose mode if any params have been passed in: if (defined $name) { $verbose = 1; $nameSpec{name} = $name; } dumpElements( 'export', sub { "\t$_->{name}".substr(' ' x 30, length($_->{name}))."($_->{type})\n" }, map { my $vendorOS = $openslxDB->fetchVendorOSByID($_->{vendor_os_id}, 'name'); if (defined $vendorOS) { $_->{vendor_os_id} .= " ($vendorOS->{name})"; } $_; } sort { $a->{name} eq $b->{name} || $a->{type} cmp $b->{type} } $openslxDB->fetchExportByFilter(\%nameSpec) ); return; } sub listSystems { my $name = shift; my %nameSpec; # set verbose mode if any params have been passed in: if (defined $name) { $verbose = 1; $nameSpec{name} = $name; } dumpElements( 'system', undef, map { my @clientIDs = $openslxDB->aggregatedClientIDsOfSystem($_); $_->{clients} = join "\n", map { $_->{name} } sort { $a->{name} cmp $b->{name} } $openslxDB->fetchClientByID(\@clientIDs, 'name'); my $export = $openslxDB->fetchExportByID($_->{export_id}); if (defined $export) { $_->{export_id} = "$export->{name} ($export->{type})"; } $_; } sort { $a->{name} cmp $b->{name} } $openslxDB->fetchSystemByFilter(\%nameSpec) ); return; } sub listVendorOSes { my $name = shift; my %nameSpec; # set verbose mode if any params have been passed in: if (defined $name) { $verbose = 1; $nameSpec{name} = $name; } dumpElements( 'vendor-OS', undef, sort { $a->{name} cmp $b->{name} } $openslxDB->fetchVendorOSByFilter(\%nameSpec) ); return; } sub searchClients { my @clientKeys = map { (/^(\w+)\W/) ? $1 : $_; } @{$DbSchema->{tables}->{client}}; my $clientData = parseKeyValueArgs(\@clientKeys, 'client', @_); # set verbose mode if any params have been passed in: $verbose = 1 if %$clientData; dumpElements( 'client', undef, map { my @sysIDs = $openslxDB->aggregatedSystemIDsOfClient($_); $_->{systems} = join "\n", map { $_->{name} } sort { $a->{name} cmp $b->{name} } $openslxDB->fetchSystemByID(\@sysIDs, 'name'); $_; } sort { $a->{name} cmp $b->{name} } $openslxDB->fetchClientByFilter($clientData) ); return; } sub searchExports { my @exportKeys = map { (/^(\w+)\W/) ? $1 : $_; } @{$DbSchema->{tables}->{export}}; my $exportData = parseKeyValueArgs(\@exportKeys, 'export', @_); # set verbose mode if any params have been passed in: $verbose = 1 if %$exportData; dumpElements( 'export', sub { "\t$_->{name}".substr(' ' x 30, length($_->{name}))."($_->{type})\n" }, map { my $vendorOS = $openslxDB->fetchVendorOSByID($_->{vendor_os_id}, 'name'); if (defined $vendorOS) { $_->{vendor_os_id} .= " ($vendorOS->{name})"; } $_; } sort { $a->{name} eq $b->{name} || $a->{type} cmp $b->{type} } $openslxDB->fetchExportByFilter($exportData) ); return; } sub searchSystems { my @systemKeys = map { (/^(\w+)\W/) ? $1 : $_; } @{$DbSchema->{tables}->{system}}; my $systemData = parseKeyValueArgs(\@systemKeys, 'system', @_); # set verbose mode if any params have been passed in: $verbose = 1 if %$systemData; dumpElements( 'system', undef, map { my @clientIDs = $openslxDB->aggregatedClientIDsOfSystem($_); $_->{clients} = join "\n", map { $_->{name} } sort { $a->{name} cmp $b->{name} } $openslxDB->fetchClientByID(\@clientIDs, 'name'); my $export = $openslxDB->fetchExportByID($_->{export_id}); if (defined $export) { $_->{export_id} = "$export->{name} ($export->{type})"; } $_; } sort { $a->{name} cmp $b->{name} } $openslxDB->fetchSystemByFilter($systemData) ); return; } sub searchVendorOSes { my @vendorOSKeys = map { (/^(\w+)\W/) ? $1 : $_; } @{$DbSchema->{tables}->{vendor_os}}; my $vendorOSData = parseKeyValueArgs(\@vendorOSKeys, 'vendor_os', @_); # set verbose mode if any params have been passed in: $verbose = 1 if %$vendorOSData; dumpElements('vendor-OS', undef, sort { $a->{name} cmp $b->{name} } $openslxDB->fetchVendorOSByFilter($vendorOSData)); return; } sub addClientToConfigDB { my $clientName = shift; if (!length($clientName)) { die _tr("you have to specify the name for the new client\n"); } my @clientKeys = map { (/^(\w+)\W/) ? $1 : $_; } @{$DbSchema->{tables}->{client}}; push @clientKeys, 'systems'; my $clientData = parseKeyValueArgs(\@clientKeys, 'client', @_); $clientData->{name} = $clientName; my @systemIDs; if (exists $clientData->{systems}) { @systemIDs = map { my $system = $openslxDB->fetchSystemByFilter({ 'name' => $_ }); if (!defined $system) { die _tr("system '%s' doesn't exist!\n", $_); } $system->{id}; } split '\s*,\s*', $clientData->{systems}; delete $clientData->{systems}; } if (!length($clientData->{mac})) { die _tr("you have to specify the MAC for the new client\n"); } if ($clientData->{mac} !~ m[^(?:[[:xdigit:]][[:xdigit:]]:){5}?[[:xdigit:]][[:xdigit:]]$]) { die _tr("unknown MAC-format given, expected something like '01:02:03:04:05:06'!\n"); } if ($openslxDB->fetchClientByFilter({ 'name' => $clientName })) { die _tr("the client '%s' already exists in the DB, giving up!\n", $clientName); } if ($openslxDB->fetchClientByFilter({ 'mac' => $clientData->{mac} })) { die _tr("a client with the MAC '%s' already exists in the DB, giving up!\n", $clientData->{mac}); } my $clientID = $openslxDB->addClient([$clientData]); vlog(0, _tr("client '%s' has been successfully added to DB (ID=%s)\n", $clientName, $clientID)); if (@systemIDs) { $openslxDB->addSystemIDsToClient($clientID, \@systemIDs); } if ($verbose) { listClients("id=$clientID"); } return; } sub addSystemToConfigDB { my $systemName = shift; if (!length($systemName)) { die _tr("you have to specify the name of the new system!\n"); } my @systemKeys = map { (/^(\w+)\W/) ? $1 : $_; } @{$DbSchema->{tables}->{system}}; push @systemKeys, 'clients', 'export'; my $systemData = parseKeyValueArgs(\@systemKeys, 'system', @_); $systemData->{name} = $systemName; my $exportName = $systemData->{export} || ''; delete $systemData->{export}; if (!length($exportName)) { $exportName = $systemName; # try falling back to given system name } my $export = $openslxDB->fetchExportByFilter({ 'name' => $exportName }); if (!defined $export) { die _tr("export '%s' could not be found in DB, giving up!\n", $exportName); } $systemData->{export_id} = $export->{id}; my @clientIDs; if (exists $systemData->{clients}) { @clientIDs = map { my $client = $openslxDB->fetchClientByFilter({ 'name' => $_ }); if (!defined $client) { die _tr("client '%s' doesn't exist in DB, giving up!\n", $_); } $client->{id}; } split '\s*,\s*', $systemData->{clients}; delete $systemData->{clients}; } else { # no clients given, so we add this system to the default client, # which will make this system bootable by *all* clients (unless # they are configured otherwise). push @clientIDs, 0; } if ($openslxDB->fetchSystemByFilter({ 'name' => $systemName })) { die _tr("the system '%s' already exists in the DB, giving up!\n", $systemName); } if ($systemName =~ m[\bkde\b]) { # activate kdm and X if system is based on kde: $systemData->{attr_start_xdmcp} = 'kdm' unless exists $systemData->{attr_start_xdmcp}; $systemData->{attr_start_x} = 'yes' unless exists $systemData->{attr_start_x}; } if ($systemName =~ m[\bgnome\b]) { # activate gdm and X if system is based on GNOME: $systemData->{attr_start_xdmcp} = 'gdm' unless exists $systemData->{attr_start_xdmcp}; $systemData->{attr_start_x} = 'yes' unless exists $systemData->{attr_start_x}; } my $systemConfigPath = "$openslxConfig{'private-path'}/config/$systemName/default"; if (!-e $systemConfigPath) { # create the default (empty) config folders for this system: createConfigFolderForSystem($systemName); } my $systemID = $openslxDB->addSystem([$systemData]); vlog(0, _tr("system '%s' has been successfully added to DB (ID=%s)\n", $systemName, $systemID)); if (@clientIDs) { $openslxDB->addClientIDsToSystem($systemID, \@clientIDs); } if ($verbose) { listSystems("id=$systemID"); } return; } sub changeClientInConfigDB { my $clientName = shift; if (!length($clientName)) { die _tr("you have to specify the name for the client you'd like to change!\n"); } my @clientKeys = map { (/^(\w+)\W/) ? $1 : $_; } @{$DbSchema->{tables}->{client}}; push @clientKeys, 'systems', 'add-systems', 'remove-systems'; my $clientData = parseKeyValueArgs(\@clientKeys, 'client', @_); my $client = $openslxDB->fetchClientByFilter({'name' => $clientName}); if (!defined $client) { die _tr("the client '%s' doesn't exists in the DB, giving up!\n", $clientName); } my @systemIDs; if (exists $clientData->{systems}) { @systemIDs = map { my $system = $openslxDB->fetchSystemByFilter({ 'name' => $_ }); if (!defined $system) { die _tr("system '%s' doesn't exist!\n", $_); } $system->{id}; } split ",", $clientData->{systems}; delete $clientData->{systems}; } if (exists $clientData->{'add-systems'}) { @systemIDs = $openslxDB->fetchSystemIDsOfClient($client->{id}); push @systemIDs, map { my $system = $openslxDB->fetchSystemByFilter({ 'name' => $_ }); if (!defined $system) { die _tr("system '%s' doesn't exist!\n", $_); } $system->{id}; } split ",", $clientData->{'add-systems'}; delete $clientData->{'add-systems'}; } if (exists $clientData->{'remove-systems'}) { @systemIDs = $openslxDB->fetchSystemIDsOfClient($client->{id}); foreach my $sysName (split ",", $clientData->{'remove-systems'}) { my $system = $openslxDB->fetchSystemByFilter({ 'name' => $sysName }); if (!defined $system) { die _tr("system '%s' doesn't exist!\n", $sysName); } @systemIDs = grep { $_ != $system->{id} } @systemIDs; } delete $clientData->{'remove-systems'}; } if ($clientData->{mac} && $clientData->{mac} !~ m[^(?:[[:xdigit:]][[:xdigit:]]:){5}?[[:xdigit:]][[:xdigit:]]$]) { die _tr("unknown MAC-format given, expected something like '01:02:03:04:05:06'!\n"); } $openslxDB->changeClient($client->{id}, [$clientData]); vlog(0, _tr("client '%s' has been successfully changed\n", $clientName)); if (@systemIDs) { $openslxDB->setSystemIDsOfClient($client->{id}, \@systemIDs); } if ($verbose) { listClients("id=$client->{id}"); } return; } sub changeSystemInConfigDB { my $systemName = shift; if (!length($systemName)) { die _tr("you have to specify the name of the system you'd like to change!\n"); } my @systemKeys = map { (/^(\w+)\W/) ? $1 : $_; } @{$DbSchema->{tables}->{system}}; push @systemKeys, 'clients', 'add-clients', 'remove-clients'; my $systemData = parseKeyValueArgs(\@systemKeys, 'system', @_); my $system = $openslxDB->fetchSystemByFilter({'name' => $systemName}); if (!defined $system) { die _tr("the system '%s' doesn't exists in the DB, giving up!\n", $systemName); } my @clientIDs; if (exists $systemData->{clients}) { @clientIDs = map { my $client = $openslxDB->fetchClientByFilter({ 'name' => $_ }); if (!defined $client) { die _tr("client '%s' doesn't exist in DB, giving up!\n", $_); } $client->{id}; } split ",", $systemData->{clients}; delete $systemData->{clients}; } if (exists $systemData->{'add-clients'}) { @clientIDs = $openslxDB->fetchClientIDsOfSystem($system->{id}); push @clientIDs, map { my $client = $openslxDB->fetchClientByFilter({ 'name' => $_ }); if (!defined $client) { die _tr("client '%s' doesn't exist!\n", $_); } $client->{id}; } split ",", $systemData->{'add-clients'}; delete $systemData->{'add-clients'}; } if (exists $systemData->{'remove-clients'}) { @clientIDs = $openslxDB->fetchClientIDsOfSystem($system->{id}); foreach my $clientName (split ",", $systemData->{'remove-clients'}) { my $client = $openslxDB->fetchClientByFilter({ 'name' => $clientName }); if (!defined $client) { die _tr("client '%s' doesn't exist!\n", $clientName); } @clientIDs = grep { $_ != $client->{id} } @clientIDs; } delete $systemData->{'remove-clients'}; } $openslxDB->changeSystem($system->{id}, [$systemData]); vlog(0, _tr("system '%s' has been successfully changed\n", $systemName)); if (@clientIDs) { $openslxDB->setClientIDsOfSystem($system->{id}, \@clientIDs); } if ($verbose) { listSystems("id=$system->{id}"); } return; } sub removeClientFromConfigDB { my $clientName = shift; if (!length($clientName)) { die _tr("you have to specify the name of the client you'd like to remove!\n"); } my $clientData = parseKeyValueArgs(['name'], 'client', @_); my $client = $openslxDB->fetchClientByFilter({'name' => $clientName}); if (!defined $client) { die _tr("the client '%s' doesn't exists in the DB, giving up!\n", $clientName); } if ($client->{id} == 0) { die _tr("you can't remove the default-client!\n"); } $openslxDB->removeClient($client->{id}); vlog(0, _tr("client '%s' has been successfully removed from DB\n", $clientName)); return; } sub removeSystemFromConfigDB { my $systemName = shift; if (!length($systemName)) { die _tr("you have to specify the name of the system you'd like to remove!\n"); } my $systemData = parseKeyValueArgs(['name'], 'system', @_); my $system = $openslxDB->fetchSystemByFilter({'name' => $systemName}); if (!defined $system) { die _tr("the system '%s' doesn't exists in the DB, giving up!\n", $systemName); } if ($system->{id} == 0) { die _tr("you can't remove the default-client!\n"); } $openslxDB->removeSystem($system->{id}); vlog(0, _tr("system '%s' has been successfully removed from DB\n", $systemName)); return; } =head1 NAME slxconfig - OpenSLX-script to view & change the configurational database =head1 SYNOPSIS slxconfig [options] =head3 Options --help brief help message --man show full documentation --verbose be more verbose --version show version =head3 Actions =over 8 =item B<< add-client mac= [= ...] >> adds a new client to the config-DB =item B<< add-system [export=] \ >> =item B<< = ...] >> adds a new system to the config-DB =item B<< change-client [= ...] >> changes the data of an existing system in the config-DB =item B<< change-system [= ...] >> changes the data of an exiisting system in the config-DB =item B<< list-client [] >> lists client with given name =item B<< list-export [] >> lists export with given name =item B<< list-system [] >> lists system with given name =item B<< list-vendoros [] >> lists vendor-OS with given name =item B<< remove-client >> removes a client from the config-DB =item B<< remove-system >> removes a system from the config-DB =item B<< search-client [= ...] >> shows all clients in config-DB (optionally matching given criteria) =item B<< search-export [= ...] >> shows all exports in config-DB (optionally matching given criteria) =item B<< search-system [= ...] >> shows all systems in config-DB (optionally matching given criteria) =item B<< search-vendoros [= ...] >> shows all vendor-OSes in config-DB (optionally matching given criteria) =back =head1 DESCRIPTION B can be used to view the contents of the configurational database. Additionally, you can add systems as well as clients and change their specific boot configuration. =head1 OPTIONS =over 8 =item B<< --help >> Prints a brief help message and exits. =item B<< --man >> Prints the manual page and exits. =item B<< --verbose >> Prints more information during execution of any action. =item B<< --version >> Prints the version and exits. =back =head1 EXAMPLES =head3 Listing existing Clients / Exports / Systems / Vendor-OSes =over 8 =item B<< slxconfig list-client >> =item B<< slxconfig list-export >> =item B<< slxconfig list-system >> =item B<< slxconfig list-vendoros >> lists all existing instances of the respective DB-objects. =item B<< slxconfig list-client id=3 >> lists the client with id=3 =item B<< slxconfig list-export type=nfs >> lists the exports of type 'nfs' =back =head3 Adding a new System to an exported Vendor-OS =over 8 =item B<< slxconfig add-system debian-4.0 >> adds a new system named 'debian-4.0' to the config-DB that will use the export of the same name. No client will be associated with this system, yet. =item B<< slxconfig add-system suse-10.1 export-name=suse-10.1-kde \ >> =item B<< clients=PC131,PC132,PC133 \ >> =item B<< label="Linux Desktop" >> adds a new system name 'suse-10.1' to the config-DB that will use the export named 'suse-10.1-kde'. The system will be labeled 'Linux Desktop' and the clients 'PC131, 'PC132' and 'PC133' are associated with this system (so they can boot it). =back =head3 Adding a new Client =over 8 =item B<< slxconfig add-client vmware-1 mac=01:02:03:04:05:06 >> adds a new client named 'vmware-1', being identified by the MAC '01:02:03:04:05:06' to the config-DB. No system will be associated with this client, yet (so it can't boot anything). =item B<< slxconfig add-client vmware-1 mac=01:02:03:04:05:06 \ >> =item B<< systems=suse-10.1,debian-4.0 \ >> =item B<< attr_start_x=no >> adds a new client named 'vmware-1', being identified by the MAC '01:02:03:04:05:06' to the config-DB. The systems 'suse-10.1' & 'Debian-4.0' will be associated with this client (so it will offer these systems for booting). During boot, the X-server will not be started by this client (so the systems will stay in console mode). =back =head3 Changing a System =over 8 =item B<< slxconfig change-system suse-10.1 attr_start_xdmcp=gnome >> will change the system named 'suse-10.1' such that it will use the GNOME session manager. =item B<< slxconfig change-system suse-10.1 add-clients=vmware-1 >> will associate the client 'vmware-1' with the system named 'suse-10.1'. =item B<< slxconfig change-system suse-10.1 remove-clients=vmware-1 >> will remove the client 'vmware-1' from the system named 'suse-10.1'. =back =head3 Changing a Client =over 8 =item B<< slxconfig change-client PC131 attr_start_snmp=yes >> will change the client named 'PC131' such that it will start the SNMP daemon on all systems that it boots. =item B<< slxconfig change-client PC131 add-systems=Debian-4.0 >> will associate the system 'Debian-4.0' with the client named 'PC131'. =item B<< slxconfig change-client PC131 remove-systems=Debian-4.0 >> will remove the system 'Debian-4.0' from the client named 'PC131'. =back =head3 Removing a System / Client =over 8 =item B<< slxconfig remove-system >> =item B<< slxconfig remove-client >> removes the system/client with the given name. =back =head1 SEE ALSO slxsettings, slxos-setup, slxos-export, slxconfig-demuxer =head1 GENERAL OPENSLX OPTIONS Being a part of OpenSLX, this script supports several other options which can be used to overrule the OpenSLX settings: --db-name= name of database --db-spec= full DBI-specification of database --db-type= type of database to connect to --locale= locale to use for translations --logfile= file to write logging output to --private-path= path to private data --public-path= path to public (client-accesible) data --temp-path= path to temporary data --verbose-level= level of logging verbosity (0-3) Please refer to the C-manpage for a more detailed description of these options. =cut