From 416ab8a37f1b07dc9f6c0fb3ff1a8ff2036510b5 Mon Sep 17 00:00:00 2001 From: Sebastian Schmelzer Date: Thu, 2 Sep 2010 17:50:49 +0200 Subject: change dir structure --- src/config-db/slxconfig | 1785 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1785 insertions(+) create mode 100755 src/config-db/slxconfig (limited to 'src/config-db/slxconfig') diff --git a/src/config-db/slxconfig b/src/config-db/slxconfig new file mode 100755 index 00000000..d4749f97 --- /dev/null +++ b/src/config-db/slxconfig @@ -0,0 +1,1785 @@ +#! /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 Clone qw(clone); +use Getopt::Long qw(:config pass_through); +use List::Util qw(max); +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::AttributeRoster; +use OpenSLX::Basics; +use OpenSLX::ConfigDB; +use OpenSLX::ConfigFolder; +use OpenSLX::Utils; + +my %option; + +GetOptions( + 'help|?' => \$option{helpReq}, + 'inherited' => \$option{inherited}, + 'man' => \$option{manReq}, + 'verbose' => \$option{verbose}, + 'version' => \$option{versionReq}, +) or pod2usage(2); +pod2usage(-msg => $abstract, -verbose => 0, -exitval => 1) if $option{helpReq}; +if ($option{manReq}) { + # avoid dubious problem with perldoc in combination with UTF-8 that + # leads to strange dashes and single-quotes being used + $ENV{LC_ALL} = 'POSIX'; + pod2usage(-verbose => 2); +} +if ($option{versionReq}) { + system('slxversion'); + exit 1; +} + +# if the user requested to see inherited attributes, we activate verbose mode, +# too, such that we actually show attributes +if ($option{inherited}) { + $option{verbose} = 1; +} + +openslxInit(); + +my $openslxDB = OpenSLX::ConfigDB->new(); +$openslxDB->connect(); + +my $action = shift @ARGV || ''; +if ($action =~ m[^add-c]i) { + addClientToConfigDB(@ARGV); +} +elsif ($action =~ m[^add-g]i) { + addGroupToConfigDB(@ARGV); +} +elsif ($action =~ m[^add-s]i) { + addSystemToConfigDB(@ARGV); +} +elsif ($action =~ m[^change-v]i) { + changeVendorOSInConfigDB(@ARGV); +} +elsif ($action =~ m[^change-e]i) { + changeExportInConfigDB(@ARGV); +} +elsif ($action =~ m[^change-g]i) { + changeGroupInConfigDB(@ARGV); +} +elsif ($action =~ m[^change-s]i) { + changeSystemInConfigDB(@ARGV); +} +elsif ($action =~ m[^change-c]i) { + changeClientInConfigDB(@ARGV); +} +elsif ($action =~ m[^cleanup-db]i) { + cleanupConfigDB(@ARGV); +} +elsif ($action =~ m[^list-a]) { + listAttributes(@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-g]) { + print _tr("List of groups:\n"); + listGroups(@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-g]) { + print _tr("Matching groups:\n"); + searchGroups(@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-c]i) { + removeClientFromConfigDB(@ARGV); +} +elsif ($action =~ m[^remove-g]i) { + removeGroupFromConfigDB(@ARGV); +} +elsif ($action =~ m[^remove-s]i) { + removeSystemFromConfigDB(@ARGV); +} +else { + vlog(0, _tr(unshiftHereDoc(<<' END-OF-HERE'), $0)); + You need to specify exactly one of these actions: + add-client + add-group + add-system + change-client + change-export + change-group + change-system + change-vendor-os + cleanup-db + list-attributes + list-client + list-export + list-group + list-system + list-vendor-os + remove-client + remove-group + remove-system + search-client + search-export + search-group + search-system + search-vendor-os + 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 key '%s' specified for %s\n", $key, $table); + } + + # replace escaped newlines and tab chars by the respective real thing + $value =~ s{\\n}{\n}gms; + $value =~ s{\\t}{\t}gms; + + # accept '-' as placeholder for undefined + if ($value eq '-') { + $value = undef; + } + + $dataHash{$key} = $value; + } + + return \%dataHash; +} + +sub parseKeyValueArgsWithAttrs +{ + my $allowedKeys = shift; + my $allowedAttrKeys = shift; + my $table = shift; + + my (%dataHash, %attrHash); + 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; + + # replace escaped newlines and tab chars by the respective real thing + $value =~ s{\\n}{\n}gms; + $value =~ s{\\t}{\t}gms; + + # accept '-' as placeholder for undefined + if ($value eq '-') { + $value = undef; + } + + if (grep { $_ eq $key } @$allowedKeys) { + $dataHash{$key} = $value; + } elsif (grep { $_ eq $key } @$allowedAttrKeys) { + $attrHash{$key} = $value; + } else { + die _tr("unknown key '%s' specified for %s\n", $key, $table); + } + } + + if (wantarray) { + return (\%dataHash, \%attrHash); + } + else { + if (%attrHash) { + $dataHash{attrs} = \%attrHash; + } + return \%dataHash; + } +} + +sub checkGivenStage3Attrs +{ + my $stage3Attrs = shift; + my $vendorOSID = shift; + + my $attrProblems; + + if ($vendorOSID) { + my $vendorOS = $openslxDB->fetchVendorOSByID($vendorOSID); + my @installedPlugins = $openslxDB->fetchInstalledPlugins($vendorOSID); + $attrProblems = OpenSLX::AttributeRoster->findProblematicValues( + $stage3Attrs, $vendorOS->{name}, \@installedPlugins + ); + } + else { + $attrProblems = OpenSLX::AttributeRoster->findProblematicValues( + $stage3Attrs + ); + } + + if ($attrProblems) { + my $complaint = join "\n", @$attrProblems; + die $complaint; + } + + return 1; +} + +sub cleanupConfigDB +{ + return $openslxDB->cleanupAnyInconsistencies(); +} + +sub mergeNonExistingAttributes +{ + my $target = shift; + my $source = shift; + + my $sourceAttrs = $source->{attrs} || {}; + + $target->{attrs} ||= {}; + my $targetAttrs = $target->{attrs}; + + foreach my $key (keys %$sourceAttrs) { + next if exists $targetAttrs->{$key}; + $targetAttrs->{$key} = $sourceAttrs->{$key}; + } + + return 1; +} + +sub dumpElements +{ + my $objName = shift; + my $nameClause = shift || sub { "\t$_->{name}\n" }; + + if ($option{verbose}) { + my $ind = ' ' x 4; + foreach my $elem (@_) { + print "$objName '$elem->{name}':\n"; + my $spcLen = max map { length($_) } keys %$elem; + print join( + '', + map { + my $elemVal = defined $elem->{$_} ? $elem->{$_} : '-'; + if (ref($elemVal) eq 'HASH') { + my $spcLen + = max(map { length($_) } keys %$elemVal) || 0; + my $spc = ' ' x $spcLen; + my $subLines = join( + "\n", + map { + my $spc = ' ' x $spcLen; + my $val + = defined $elemVal->{$_} + ? $elemVal->{$_} + : ''; + $val =~ s[\n][\n$ind$spc ]g; + "$ind$_" . substr($spc, length($_)) . " = $val"; + } + sort { + # drop [] construct (origin) from key for + # sorting purposes + (my $aa = $a) =~ s{^\s*\[.+\]\s*}{}; + (my $bb = $b) =~ s{^\s*\[.+\]\s*}{}; + return $aa cmp $bb; + } keys %$elemVal + ); + $subLines ||= "$ind"; + " $_:\n$subLines\n"; + } elsif (ref($elemVal) eq 'ARRAY') { + my $subLines + = join( "\n", map { "$ind$_" } sort @$elemVal); + $subLines ||= "$ind"; + " $_:\n$subLines\n"; + } else { + my $spc = ' ' x $spcLen; + $elemVal =~ s[\n][\n$ind$spc ]g; + "$ind$_" . substr($spc, length($_)) . " = $elemVal\n"; + } + } + sort { + my $refCmp = ref($elem->{$a}) cmp ref($elem->{$b}); + return $refCmp ? $refCmp : $a cmp $b; + } + grep { + $_ ne 'name'; + } + keys %$elem + ); + } + } + else { + print join('', sort map { $nameClause->($_); } @_); + } + + return 1; +} + +sub listAttributes +{ + my $attrSpec = shift; + + my $listHeader = _tr("List of known attributes:\n"); + my $attrInfo + = OpenSLX::AttributeRoster->getAttrInfo( { scope => $attrSpec } ); + if ($attrInfo && keys %$attrInfo) { + $listHeader + = _tr("List of known attributes for scope '%s':\n", $attrSpec); + } + else { + $attrInfo = + OpenSLX::AttributeRoster->getAttrInfo( { name => $attrSpec } ); + $listHeader = _tr("Details for attribute '%s':\n", $attrSpec); + $option{verbose} = 1; + } + + print $listHeader; + dumpElements( + 'attribute', undef, + map { + my $attr = clone($attrInfo->{$_}); + $attr->{name} = $_; + delete $attr->{content_regex}; # no use for display purposes + $attr; + } + sort keys %$attrInfo + ); + + return 1; +} + +sub listClients +{ + my $name = _cleanName(shift); + + my %nameSpec; + + # set verbose mode if any params have been passed in: + if (defined $name) { + $option{verbose} = 1; + $nameSpec{name} = $name; + } + + dumpElements( + 'client', undef, + _expandClients( + sort { $a->{name} cmp $b->{name} } + $openslxDB->fetchClientByFilter(\%nameSpec) + ) + ); + + return 1; +} + +sub listGroups +{ + my $name = _cleanName(shift); + + my %nameSpec; + + # set verbose mode if any params have been passed in: + if (defined $name) { + $option{verbose} = 1; + $nameSpec{name} = $name; + } + + dumpElements( + 'group', undef, + _expandGroups( + sort { $a->{name} cmp $b->{name} } + $openslxDB->fetchGroupByFilter(\%nameSpec) + ) + ); + + return 1; +} + +sub listExports +{ + my $name = _cleanName(shift); + + my %nameSpec; + + # set verbose mode if any params have been passed in: + if (defined $name) { + $option{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 1; +} + +sub listSystems +{ + my $name = _cleanName(shift); + + my %nameSpec; + + # set verbose mode if any params have been passed in: + if (defined $name) { + $option{verbose} = 1; + $nameSpec{name} = $name; + } + + dumpElements( + 'system', undef, + _expandSystems( + sort { $a->{name} cmp $b->{name} } + $openslxDB->fetchSystemByFilter(\%nameSpec) + ) + ); + + return 1; +} + +sub listVendorOSes +{ + my $name = _cleanName(shift); + + my %nameSpec; + + # set verbose mode if any params have been passed in: + if (defined $name) { + $option{verbose} = 1; + $nameSpec{name} = $name; + } + + dumpElements('vendor-OS', undef, + map { + my @plugins = $openslxDB->fetchInstalledPlugins($_->{id}); + my %attrHash; + foreach my $plugin (@plugins) { + foreach my $attr (keys %{$plugin->{attrs}}) { + $attrHash{$attr} = $plugin->{attrs}->{$attr}; + } + } + $_->{ATTRIBUTES} = \%attrHash; + $_->{PLUGINS} + = @plugins + ? join(',', sort map { $_->{plugin_name} } @plugins) + : ''; + $_; + } + sort { $a->{name} cmp $b->{name} } + $openslxDB->fetchVendorOSByFilter(\%nameSpec)); + + return 1; +} + +sub searchClients +{ + my @clientKeys = $openslxDB->getColumnsOfTable('client'); + my @clientAttrKeys = OpenSLX::AttributeRoster->getClientAttrs(); + my ($clientData, $clientAttrs) = parseKeyValueArgsWithAttrs( + \@clientKeys, \@clientAttrKeys, 'client', @_ + ); + + # set verbose mode if any params have been passed in: + $option{verbose} = 1 if %$clientData; + + dumpElements( + 'client', undef, + _expandClients( + sort { $a->{name} cmp $b->{name} } + $openslxDB->fetchClientByFilter($clientData, undef, $clientAttrs) + ) + ); + + return 1; +} + +sub searchGroups +{ + my @groupKeys = $openslxDB->getColumnsOfTable('groups'); + my @groupAttrKeys = OpenSLX::AttributeRoster->getClientAttrs(); + my ($groupData, $groupAttrs) = parseKeyValueArgsWithAttrs( + \@groupKeys, \@groupAttrKeys, 'group', @_ + ); + + # set verbose mode if any params have been passed in: + $option{verbose} = 1 if %$groupData; + + dumpElements( + 'group', undef, + _expandGroups( + sort { $a->{name} cmp $b->{name} } + $openslxDB->fetchGroupByFilter($groupData, undef, $groupAttrs) + ) + ); + + return 1; +} + +sub searchExports +{ + my @exportKeys = $openslxDB->getColumnsOfTable('export'); + my $exportData = parseKeyValueArgs(\@exportKeys, 'export', @_); + + # set verbose mode if any params have been passed in: + $option{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 1; +} + +sub searchSystems +{ + my @systemKeys = $openslxDB->getColumnsOfTable('system'); + my @systemAttrKeys = OpenSLX::AttributeRoster->getSystemAttrs(); + my ($systemData, $systemAttrs) = parseKeyValueArgsWithAttrs( + \@systemKeys, \@systemAttrKeys, 'system', @_ + ); + + # set verbose mode if any params have been passed in: + $option{verbose} = 1 if %$systemData; + + dumpElements( + 'system', undef, + _expandSystems( + sort { $a->{name} cmp $b->{name} } + $openslxDB->fetchSystemByFilter($systemData, undef, $systemAttrs) + ) + ); + + return 1; +} + +sub searchVendorOSes +{ + my @vendorOSKeys = $openslxDB->getColumnsOfTable('vendor_os'); + my $vendorOSData = parseKeyValueArgs(\@vendorOSKeys, 'vendor_os', @_); + + # set verbose mode if any params have been passed in: + $option{verbose} = 1 if %$vendorOSData; + + dumpElements( + 'vendor-OS', undef, + map { + my @plugins = $openslxDB->fetchInstalledPlugins($_->{id}); + $_->{plugins} + = @plugins + ? join(',', sort map { $_->{plugin_name} } @plugins) + : ''; + $_; + } + sort { $a->{name} cmp $b->{name} } + $openslxDB->fetchVendorOSByFilter($vendorOSData) + ); + + return 1; +} + +sub changeVendorOSInConfigDB +{ + my $vendorOSName = _cleanName(shift || ''); + + if (!length($vendorOSName)) { + die _tr( + "you have to specify the name for the vendor-OS you'd like to change!\n" + ); + } + + my @keys = $openslxDB->getColumnsOfTable('vendor_os'); + my $vendorOSData = parseKeyValueArgs(\@keys, 'vendor_os', @_); + + my $vendorOS = $openslxDB->fetchVendorOSByFilter({'name' => $vendorOSName}); + if (!defined $vendorOS) { + die _tr("the vendor-OS '%s' doesn't exists in the DB, giving up!\n", + $vendorOSName); + } + + $openslxDB->changeVendorOS($vendorOS->{id}, [$vendorOSData]); + vlog( + 0, _tr("vendor-OS '%s' has been successfully changed\n", $vendorOSName) + ); + + listVendorOSes("id=$vendorOS->{id}") if $option{verbose}; + + return 1; +} + +sub changeExportInConfigDB +{ + my $exportName = _cleanName(shift || ''); + + if (!length($exportName)) { + die _tr( + "you have to specify the name for the export you'd like to change!\n" + ); + } + + my @exportKeys = $openslxDB->getColumnsOfTable('export'); + my $exportData = parseKeyValueArgs(\@exportKeys, 'export', @_); + + my $export = $openslxDB->fetchExportByFilter({'name' => $exportName}); + if (!defined $export) { + die _tr("the export '%s' doesn't exists in the DB, giving up!\n", + $exportName); + } + + $openslxDB->changeExport($export->{id}, [$exportData]); + vlog(0, _tr("export '%s' has been successfully changed\n", $exportName)); + + listExports("id=$export->{id}") if $option{verbose}; + + return 1; +} + +sub addClientToConfigDB +{ + my $clientName = _cleanName(shift || ''); + + if (!length($clientName)) { + die _tr("you have to specify the name for the new client\n"); + } + + my @clientKeys = $openslxDB->getColumnsOfTable('client'); + push @clientKeys, 'systems'; + my @clientAttrKeys = OpenSLX::AttributeRoster->getClientAttrs(); + my $clientData = parseKeyValueArgsWithAttrs( + \@clientKeys, \@clientAttrKeys, 'client', @_ + ); + $clientData->{name} = $clientName; + + checkGivenStage3Attrs($clientData->{attrs}); + + 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 (!$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 ($option{verbose}) { + listClients("id=$clientID"); + } + + return 1; +} + +sub addGroupToConfigDB +{ + my $groupName = _cleanName(shift || ''); + if (!length($groupName)) { + die _tr("you have to specify the name for the new group\n"); + } + + my @groupKeys = $openslxDB->getColumnsOfTable('groups'); + push @groupKeys, 'systems', 'clients'; + my @groupAttrKeys = OpenSLX::AttributeRoster->getClientAttrs(); + my $groupData = parseKeyValueArgsWithAttrs( + \@groupKeys, \@groupAttrKeys, 'group', @_ + ); + $groupData->{name} = $groupName; + + checkGivenStage3Attrs($groupData->{attrs}); + + my @systemIDs; + if (exists $groupData->{systems}) { + @systemIDs = map { + my $system = $openslxDB->fetchSystemByFilter({'name' => $_}); + if (!defined $system) { + die _tr("system '%s' doesn't exist!\n", $_); + } + $system->{id}; + } + split '\s*,\s*', $groupData->{systems}; + delete $groupData->{systems}; + } + my @clientIDs; + if (exists $groupData->{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*', $groupData->{clients}; + delete $groupData->{clients}; + } + + if (!defined $groupData->{priority} || !length($groupData->{priority})) { + $groupData->{priority} = 50; + vlog(0, _tr("priority of new group has been set to default (50).")); + } + + if ($openslxDB->fetchGroupByFilter({'name' => $groupName})) { + die _tr("the group '%s' already exists in the DB, giving up!\n", + $groupName); + } + my $groupID = $openslxDB->addGroup([$groupData]); + vlog( + 0, + _tr( + "group '%s' has been successfully added to DB (ID=%s)\n", + $groupName, $groupID + ) + ); + if (@systemIDs) { + $openslxDB->addSystemIDsToGroup($groupID, \@systemIDs); + } + if (@clientIDs) { + $openslxDB->addClientIDsToGroup($groupID, \@clientIDs); + } + listGroups("id=$groupID") if $option{verbose}; + + return 1; +} + +sub addSystemToConfigDB +{ + my $systemName = _cleanName(shift || ''); + + if (!length($systemName)) { + die _tr("you have to specify the name of the new system!\n"); + } + + my @systemKeys = $openslxDB->getColumnsOfTable('system'); + push @systemKeys, 'clients', 'export'; + my @systemAttrKeys = OpenSLX::AttributeRoster->getSystemAttrs(); + my $systemData = parseKeyValueArgsWithAttrs( + \@systemKeys, \@systemAttrKeys, 'system', @_ + ); + $systemData->{name} = $systemName; + $systemData->{attrs} ||= {}; + + 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}; + + checkGivenStage3Attrs($systemData->{attrs}, $export->{vendor_os_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). + my $defaultClient = + $openslxDB->fetchClientByFilter({'name' => '<<>>'}); + push @clientIDs, $defaultClient->{id}; + } + + if ($openslxDB->fetchSystemByFilter({'name' => $systemName})) { + die _tr("the system '%s' already exists in the DB, giving up!\n", + $systemName); + } + + 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); + } + listSystems("id=$systemID") if $option{verbose}; + + return 1; +} + +sub changeClientInConfigDB +{ + my $clientName = _cleanName(shift || ''); + + if (!length($clientName)) { + die _tr( + "you have to specify the name of the client you'd like to change!\n" + ); + } + + my @clientKeys = $openslxDB->getColumnsOfTable('client'); + push @clientKeys, 'systems', 'add-systems', 'remove-systems'; + my @clientAttrKeys = OpenSLX::AttributeRoster->getClientAttrs(); + my $clientData = parseKeyValueArgsWithAttrs( + \@clientKeys, \@clientAttrKeys, '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); + } + + checkGivenStage3Attrs($clientData->{attrs}); + + mergeNonExistingAttributes($clientData, $client); + + 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->{name} && $client->{name} eq '<<>>') { + die _tr( + "you can't rename the default client - no changes were made!\n"); + } + + 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); + } + listClients("id=$client->{id}") if $option{verbose}; + + return 1; +} + +sub changeGroupInConfigDB +{ + my $groupName = _cleanName(shift || ''); + + if (!length($groupName)) { + die _tr( + "you have to specify the name of the group you'd like to change!\n" + ); + } + + my @groupKeys = $openslxDB->getColumnsOfTable('group'); + push @groupKeys, qw( + systems add-systems remove-systems clients add-clients remove-clients + ); + my @groupAttrKeys = OpenSLX::AttributeRoster->getClientAttrs(); + my $groupData = parseKeyValueArgsWithAttrs( + \@groupKeys, \@groupAttrKeys, 'group', @_ + ); + + my $group = $openslxDB->fetchGroupByFilter({'name' => $groupName}); + if (!defined $group) { + die _tr("the group '%s' doesn't exists in the DB, giving up!\n", + $groupName); + } + + checkGivenStage3Attrs($groupData->{attrs}); + + mergeNonExistingAttributes($groupData, $group); + + my (@systemIDs, @clientIDs); + if (exists $groupData->{systems}) { + @systemIDs = map { + my $system = $openslxDB->fetchSystemByFilter({'name' => $_}); + if (!defined $system) { + die _tr("system '%s' doesn't exist!\n", $_); + } + $system->{id}; + } + split ",", $groupData->{systems}; + delete $groupData->{systems}; + } + if (exists $groupData->{'add-systems'}) { + @systemIDs = $openslxDB->fetchSystemIDsOfGroup($group->{id}); + push @systemIDs, map { + my $system = $openslxDB->fetchSystemByFilter({'name' => $_}); + if (!defined $system) { + die _tr("system '%s' doesn't exist!\n", $_); + } + $system->{id}; + } + split ",", $groupData->{'add-systems'}; + delete $groupData->{'add-systems'}; + } + if (exists $groupData->{'remove-systems'}) { + @systemIDs = $openslxDB->fetchSystemIDsOfGroup($group->{id}); + foreach my $sysName (split ',', $groupData->{'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 $groupData->{'remove-systems'}; + } + if (exists $groupData->{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 ",", $groupData->{clients}; + delete $groupData->{clients}; + } + if (exists $groupData->{'add-clients'}) { + @clientIDs = $openslxDB->fetchClientIDsOfGroup($group->{id}); + push @clientIDs, map { + my $client = $openslxDB->fetchClientByFilter({'name' => $_}); + if (!defined $client) { + die _tr("client '%s' doesn't exist!\n", $_); + } + $client->{id}; + } + split ",", $groupData->{'add-clients'}; + delete $groupData->{'add-clients'}; + } + if (exists $groupData->{'remove-clients'}) { + @clientIDs = $openslxDB->fetchClientIDsOfGroup($group->{id}); + foreach my $clientName (split ",", $groupData->{'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 $groupData->{'remove-clients'}; + } + + if (defined $groupData->{priority} && $groupData->{priority} !~ m{^\d+$}) { + die _tr("unknown priority-format given, expected an integer!\n"); + } + + $openslxDB->changeGroup($group->{id}, [$groupData]); + vlog(0, _tr("group '%s' has been successfully changed\n", $groupName)); + if (@systemIDs) { + $openslxDB->setSystemIDsOfGroup($group->{id}, \@systemIDs); + } + if (@clientIDs) { + $openslxDB->setClientIDsOfGroup($group->{id}, \@clientIDs); + } + listGroups("id=$group->{id}") if $option{verbose}; + + return 1; +} + +sub changeSystemInConfigDB +{ + my $systemName = _cleanName(shift || ''); + + if (!length($systemName)) { + die _tr( + "you have to specify the name of the system you'd like to change!\n" + ); + } + + 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 @systemKeys = $openslxDB->getColumnsOfTable('system'); + push @systemKeys, 'clients', 'add-clients', 'remove-clients'; + my @systemAttrKeys = OpenSLX::AttributeRoster->getSystemAttrs(); + my $systemData = parseKeyValueArgsWithAttrs( + \@systemKeys, \@systemAttrKeys, 'system', @_ + ); + + my $export = $openslxDB->fetchExportByID($system->{export_id}); + checkGivenStage3Attrs($systemData->{attrs}, $export->{vendor_os_id}); + + mergeNonExistingAttributes($systemData, $system); + + 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'}; + } + if ($systemData->{name} && $system->{name} eq '<<>>') { + die _tr( + "you can't rename the default system - no changes were made!\n"); + } + + $openslxDB->changeSystem($system->{id}, $systemData); + vlog(0, _tr("system '%s' has been successfully changed\n", $systemName)); + if (@clientIDs) { + $openslxDB->setClientIDsOfSystem($system->{id}, \@clientIDs); + } + listSystems("id=$system->{id}")if $option{verbose}; + + return 1; +} + +sub removeClientFromConfigDB +{ + my $clientName = _cleanName(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->{name} eq '<<>>') { + 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 1; +} + +sub removeGroupFromConfigDB +{ + my $groupName = _cleanName(shift || ''); + + if (!length($groupName)) { + die _tr( + "you have to specify the name of the group you'd like to remove!\n" + ); + } + + my $groupData = parseKeyValueArgs(['name'], 'group', @_); + + my $group = $openslxDB->fetchGroupByFilter({'name' => $groupName}); + if (!defined $group) { + die _tr("the group '%s' doesn't exists in the DB, giving up!\n", + $groupName); + } + $openslxDB->removeGroup($group->{id}); + vlog(0, + _tr("group '%s' has been successfully removed from DB\n", $groupName) + ); + + return 1; +} + +sub removeSystemFromConfigDB +{ + my $systemName = _cleanName(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->{name} eq '<<>>') { + die _tr("you can't remove the default system!\n"); + } + $openslxDB->removeSystem($system->{id}); + vlog(0, + _tr("system '%s' has been successfully removed from DB\n", $systemName) + ); + + return 1; +} + +sub _expandClients +{ # expands info for given clients + return + map { + my @sysIDs = $openslxDB->fetchSystemIDsOfClient($_->{id}); + $_->{systems} + = join "\n", + map { $_->{name} } + sort { $a->{name} cmp $b->{name} } + $openslxDB->fetchSystemByID(\@sysIDs, 'name'); + if ($option{inherited}) { + my $mergedClient = clone($_); + my $originInfo = {}; + $openslxDB->mergeDefaultAndGroupAttributesIntoClient( + $mergedClient, $originInfo + ); + my $mergedAttrs = $mergedClient->{attrs} || {}; + $_->{attrs} = {}; + foreach my $attr (keys %$mergedAttrs) { + my $origin = $originInfo->{$attr}; + my $enhancedName = $origin ? "[$origin] $attr" : $attr; + $_->{attrs}->{$enhancedName} = $mergedAttrs->{$attr}; + } + } + # rename attrs to ATTRIBUTES for display + $_->{ATTRIBUTES} = $_->{attrs}; + delete $_->{attrs}; + $_; + } + @_; +} + +sub _expandGroups +{ # expands info for given groups + return + map { + my @systemIDs = $openslxDB->fetchSystemIDsOfGroup($_->{id}); + $_->{systems} + = join "\n", map { $_->{name} } + sort { $a->{name} cmp $b->{name} } + $openslxDB->fetchSystemByID(\@systemIDs, 'name'); + my @clientIDs = $openslxDB->fetchClientIDsOfGroup($_->{id}); + $_->{clients} + = join "\n", map { $_->{name} } + sort { $a->{name} cmp $b->{name} } + $openslxDB->fetchClientByID(\@clientIDs, 'name'); + # rename attrs to ATTRIBUTES for display + $_->{ATTRIBUTES} = $_->{attrs}; + delete $_->{attrs}; + $_; + } + @_; +} + +sub _expandSystems +{ # expands info for given systems + return + map { + my @clientIDs = $openslxDB->fetchClientIDsOfSystem($_->{id}); + $_->{clients} + = join "\n", + map { $_->{name} } + sort { $a->{name} cmp $b->{name} } + $openslxDB->fetchClientByID(\@clientIDs, 'name'); + my @activePlugins; + my $export = $openslxDB->fetchExportByID($_->{export_id}); + if (defined $export) { + $_->{export_id} = "$export->{id} ($export->{name})"; + + # fetch detailed info about active plugins + my @installedPlugins = $openslxDB->fetchInstalledPlugins( + $export->{vendor_os_id} + ); + my $mergedSystem = clone($_); + my $originInfo = {}; + $openslxDB->mergeDefaultAttributesIntoSystem( + $mergedSystem, \@installedPlugins, $originInfo + ); + my $mergedAttrs = $mergedSystem->{attrs} || {}; + foreach my $plugin (@installedPlugins) { + next if !$mergedAttrs->{"$plugin->{plugin_name}::active"}; + push @activePlugins, $plugin; + } + if ($option{inherited}) { + $_->{attrs} = {}; + foreach my $attr (keys %$mergedAttrs) { + my $origin = $originInfo->{$attr}; + my $enhancedName = $origin ? "[$origin] $attr" : $attr; + $_->{attrs}->{$enhancedName} = $mergedAttrs->{$attr}; + } + } + } + $_->{PLUGINS} = [ sort map { $_->{plugin_name} } @activePlugins ]; + # rename attrs to ATTRIBUTES for display + $_->{ATTRIBUTES} = $_->{attrs}; + delete $_->{attrs}; + $_; + } + @_; +} + +sub _cleanName +{ # removes 'name=""' constructs from the name, as it is rather tempting + # for the user to type that ... (and we'd like to play along with DWIM) + my $name = shift; + + return unless defined $name; + + if ($name =~ m[^name=(.+)$]) { + return $1; + } + + # for convenience, we alias default to <<>> + $name = '<<>>' if $name eq 'default'; + + return $name; +} + +=head1 NAME + +slxconfig - OpenSLX-script to view & change the configurational database + +=head1 SYNOPSIS + +slxconfig [options] + +=head3 Options + + --help brief help message + --inherited show inherited attributes, too + --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<< add-group [priority=] [= ...] >> + +adds a new group to the config-DB + +=item B<< change-vendor-os [= ...] >> + +changes the data of an existing vendor-OS in the config-DB. + +=item B<< change-export [= ...] >> + +changes the data of an existing export in the config-DB + +=item B<< change-client [= ...] >> + +changes the data of an existing client in the config-DB + +Note: you can use the special value '-' to unset a key (mostly useful +for attributes). + +=item B<< change-group [= ...] >> + +changes the data of an existing group in the config-DB + +Note: you can use the special value '-' to unset a key (mostly useful +for attributes). + +=item B<< change-system [= ...] >> + +changes the data of an existing system in the config-DB + +Note: you can use the special value '-' to unset a key (mostly useful +for attributes). + +=item B<< cleanup-db >> + +utility command that looks for any inconsistencies in the DB (stale references +and/or references to plugins that do not exists) and removes them. + +You should only invoke this if you are a developer and have removed one or +more plugins from the repository and would like to get rid of the left-overs +in your local DB. + +=item B<< list-attributes [] >> + +lists all attributes, the ones in the given scope or the one with the given +name + +=item B<< list-client [] >> + +lists client with given name + +=item B<< list-export [] >> + +lists export with given name + +=item B<< list-group [] >> + +lists group with given name + +=item B<< list-system [] >> + +lists system with given name + +=item B<< list-vendor-os [] >> + +lists vendor-OS with given name + +=item B<< remove-client >> + +removes a client from the config-DB + +=item B<< remove-group >> + +removes a group 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-group [= ...] >> + +shows all groups in config-DB (optionally matching given criteria) + +=item B<< search-system [= ...] >> + +shows all systems in config-DB (optionally matching given +criteria) + +=item B<< search-vendor-os [= ...] >> + +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 / Groups / Systems / Vendor-OSes + +=over 8 + +=item B<< slxconfig list-client >> + +=item B<< slxconfig list-export >> + +=item B<< slxconfig list-group >> + +=item B<< slxconfig list-system >> + +=item B<< slxconfig list-vendor-os >> + +lists all existing instances of the respective DB-objects + +=item B<< slxconfig list-system "<<>>" >> + +Lists the details of the default-system. + +=item B<< slxconfig --inherited list-system suse-10.2::nfs >> + +Lists the details of the 'suse-10.2::nfs'-system with all the attributes +that it inherits from the default-system or the default-client. + +=back + +=head3 Listing known attributes + +=over 8 + +=item B<< slxconfig list-attr >> + +lists all known attributes (--verbose will give details). + +=item B<< slxconfig list-attr >> + +lists all known attributes for the given scope (use 'core' to see only +non-scoped attributes). + +=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-11.1 export-name=suse-11.1-kde \ >> + +=item B<< clients=PC131,PC132,PC133 \ >> + +=item B<< label="Linux Desktop" >> + +adds a new system name 'suse-11.1' to the config-DB that will +use the export named 'suse-11.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-11.1,debian-4.0 \ >> + +=item B<< boot_type=pxe >> + +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-11.1' & +'Debian-4.0' will be associated with this client (so it will +offer these systems for booting). + +This client will use PXE for booting (which is the default, anyway). + +=back + +=head3 Changing a System + +=over 8 + +=item B<< slxconfig change-system suse-11.1 boot_type=preboot-cd >> + +will change the system named 'suse-11.1' such that it will use a preboot-CD +environment for booting. + +=item B<< slxconfig change-system suse-11.1 add-clients=vmware-1 >> + +will associate the client 'vmware-1' with the system named +'suse-11.1'. + +=item B<< slxconfig change-system suse-11.1 remove-clients=vmware-1 >> + +will remove the client 'vmware-1' from the system named +'suse-11.1'. + +=back + +=head3 Changing a Client + +=over 8 + +=item B<< slxconfig change-client PC131 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 Client / Group / System + +=over 8 + +=item B<< slxconfig remove-client >> + +=item B<< slxconfig remove-group >> + +=item B<< slxconfig remove-system >> + +removes the client/group/system with the given name. + +=back + +=head3 Searching for Clients / Exports / Groups / Systems / Vendor-OSes + +=over 8 + +=item B<< slxconfig search-client mac='01:02:03:04:05:06' >> + +displays all clients with the MAC '01:02:03:04:05:06' (should be only one) + +=item B<< slxconfig search-export type=nfs >> + +displays the exports of type 'nfs' + +=item B<< slxconfig list-group priority=50 >> + +displays the groups that have the default priority (50) + +=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 + --log-level= level of logging verbosity (0-3) + --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 + +Please refer to the C-manpage for a more detailed description +of these options. + +=cut -- cgit v1.2.3-55-g7522