summaryrefslogtreecommitdiffstats
path: root/src/config-db/OpenSLX/AttributeRoster.pm
diff options
context:
space:
mode:
Diffstat (limited to 'src/config-db/OpenSLX/AttributeRoster.pm')
-rw-r--r--src/config-db/OpenSLX/AttributeRoster.pm537
1 files changed, 537 insertions, 0 deletions
diff --git a/src/config-db/OpenSLX/AttributeRoster.pm b/src/config-db/OpenSLX/AttributeRoster.pm
new file mode 100644
index 00000000..88d6295f
--- /dev/null
+++ b/src/config-db/OpenSLX/AttributeRoster.pm
@@ -0,0 +1,537 @@
+# 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/
+# -----------------------------------------------------------------------------
+# AttributeRoster.pm
+# - provides information about all available attributes
+# -----------------------------------------------------------------------------
+package OpenSLX::AttributeRoster;
+
+use strict;
+use warnings;
+
+use Digest::MD5 qw(md5_hex);
+
+use OpenSLX::Basics;
+use OpenSLX::OSPlugin::Engine;
+use OpenSLX::OSPlugin::Roster;
+use OpenSLX::Utils;
+
+my %AttributeInfo;
+
+#=item C<_init()>
+#
+#Integrates info about all known attributes (from core and from the plugins)
+#into one big hash.
+#Returns info about all attributes.
+#
+#=cut
+#
+sub _init
+{
+ my $class = shift;
+
+ # set core attributes
+ %AttributeInfo = (
+ 'automnt_dir' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ !!!descriptive text missing here!!!
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => '',
+ },
+ 'automnt_src' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ !!!descriptive text missing here!!!
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => '',
+ },
+ 'boot_type' => {
+ applies_to_systems => 0,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ Selects the boot technology for this client.
+ Currently the following boot types are supported:
+ pxe (is the default)
+ uses PXE to boot client over LAN
+ preboot
+ generates a set of images (see preboot_media) that can
+ be used to remotely boot the systems referred to by
+ this client
+ pbs
+ preboot server (experimental)
+ End-of-Here
+ content_regex => qr{^(pxe|preboot|pbs)$},
+ content_descr => '"pxe" or "preboot"',
+ default => 'pxe',
+ },
+ 'boot_uri' => {
+ applies_to_systems => 0,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ specifies the wget(able) address of the remote bootloader
+ archive that shall be loaded from the preboot environment
+ End-of-Here
+ content_regex => undef,
+ content_descr => 'an uri supported by wget',
+ default => '',
+ },
+ 'country' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ !!!descriptive text missing here!!!
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => 'de',
+ },
+ 'hidden' => {
+ applies_to_systems => 1,
+ applies_to_clients => 0,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ specifies whether or not this system is offered for booting
+ End-of-Here
+ content_regex => qr{^(0|1)$},
+ content_descr => '0: system is bootable - 1: system is hidden',
+ default => '0',
+ },
+ 'kernel_params' => {
+ applies_to_systems => 1,
+ applies_to_clients => 0,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ params to build kernel cmdline for this system
+ End-of-Here
+ content_regex => undef,
+ content_descr => 'kernel cmdline fragment',
+ default => 'quiet',
+ },
+ 'kernel_params_client' => {
+ applies_to_systems => 0,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ client-specific params for kernel cmdline
+ End-of-Here
+ content_regex => undef,
+ content_descr => 'kernel cmdline fragment',
+ default => '',
+ },
+ 'preboot_media' => {
+ applies_to_systems => 0,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ List of preboot media supported by this client.
+ Currently the following preboot media are supported:
+ cd
+ generates a bootable CD-image that can be used to
+ remotely boot the systems referred to by this client
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => '',
+ },
+ 'preboot_server' => {
+ applies_to_systems => 0,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ !!experimental!! specifies location of openslx-preboot-server
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => '',
+ },
+ 'ramfs_fsmods' => {
+ applies_to_systems => 1,
+ applies_to_clients => 0,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ list of filesystem kernel modules to load
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => '',
+ },
+ 'ramfs_miscmods' => {
+ applies_to_systems => 1,
+ applies_to_clients => 0,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ list of miscellaneous kernel modules to load
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => '',
+ },
+ 'ramfs_nicmods' => {
+ applies_to_systems => 1,
+ applies_to_clients => 0,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ list of network card modules to load
+ End-of-Here
+ content_regex => qr{^\s*([-\w]+\s*)*$},
+ content_descr => 'a space-separated list of NIC modules',
+ default => 'forcedeth e1000 e100 tg3 via-rhine r8169 pcnet32',
+ },
+ 'hw_local_disk' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ how to handle local disk deploament - no/slxonly/all
+ End-of-Here
+ content_regex => undef,
+ content_descr => 'how to handle local disk (no/slxonly/all)',
+ default => 'all',
+ },
+ 'scratch' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ !!!descriptive text missing here!!!
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => '',
+ },
+ 'start_atd' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ !!!descriptive text missing here!!!
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => 'no',
+ },
+ 'start_cron' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ !!!descriptive text missing here!!!
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => 'no',
+ },
+ 'start_dreshal' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ !!!descriptive text missing here!!!
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => 'yes',
+ },
+ 'start_ntp' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ !!!descriptive text missing here!!!
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => 'initial',
+ },
+ 'start_nfsv4' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ !!!descriptive text missing here!!!
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => 'no',
+ },
+ 'start_snmp' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ !!!descriptive text missing here!!!
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => 'no',
+ },
+ 'start_sshd' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ !!!descriptive text missing here!!!
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => 'yes',
+ },
+ 'timezone' => {
+ applies_to_systems => 1,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ textual timezone (e.g. 'Europe/Berlin')
+ End-of-Here
+ content_regex => undef,
+ content_descr => undef,
+ default => 'Europe/Berlin',
+ },
+ 'unbootable' => {
+ applies_to_systems => 0,
+ applies_to_clients => 1,
+ description => unshiftHereDoc(<<' End-of-Here'),
+ specifies whether or not this client is allowed to boot
+ End-of-Here
+ content_regex => qr{^(0|1)$},
+ content_descr => '0: client can boot - 1: client is blocked',
+ default => '0',
+ },
+ );
+
+ # and add all plugin attributes, too
+ OpenSLX::OSPlugin::Roster->addAllStage3AttributesToHash(\%AttributeInfo);
+
+ return 1;
+}
+
+=item C<getAttrInfo()>
+
+Returns info about all attributes.
+
+=over
+
+=item Return Value
+
+An hash-ref with info about all known attributes.
+
+=back
+
+=cut
+
+sub getAttrInfo
+{
+ my $class = shift;
+ my $params = shift || {};
+
+ $class->_init() if !%AttributeInfo;
+
+ if (defined $params->{name}) {
+ my $attrInfo = $AttributeInfo{$params->{name}};
+ return if !defined $attrInfo;
+ return { $params->{name} => $AttributeInfo{$params->{name}} };
+ }
+ elsif (defined $params->{scope}) {
+ my %MatchingAttributeInfo;
+ my $selectedScope = lc($params->{scope});
+ foreach my $attr (keys %AttributeInfo) {
+ my $attrScope = '';
+ if ($attr =~ m{^(.+?)::}) {
+ $attrScope = lc($1);
+ }
+ if ((!$attrScope && $selectedScope eq 'core')
+ || $attrScope eq $selectedScope) {
+ $MatchingAttributeInfo{$attr} = $AttributeInfo{$attr};
+ }
+ }
+ return \%MatchingAttributeInfo;
+ }
+
+ return \%AttributeInfo;
+}
+
+=item C<getStage3Attrs()>
+
+Returns the stage3 attribute names (which apply to systems or clients).
+
+=over
+
+=item Return Value
+
+An array of attribute names.
+
+=back
+
+=cut
+
+sub getStage3Attrs
+{
+ my $class = shift;
+
+ $class->_init() if !%AttributeInfo;
+
+ return
+ grep {
+ $AttributeInfo{$_}->{applies_to_systems}
+ || $AttributeInfo{$_}->{applies_to_client}
+ }
+ keys %AttributeInfo
+}
+
+=item C<getSystemAttrs()>
+
+Returns the attribute names that apply to systems.
+
+=over
+
+=item Return Value
+
+An array of attribute names.
+
+=back
+
+=cut
+
+sub getSystemAttrs
+{
+ my $class = shift;
+
+ $class->_init() if !%AttributeInfo;
+
+ return
+ grep { $AttributeInfo{$_}->{"applies_to_systems"} }
+ keys %AttributeInfo
+}
+
+=item C<getClientAttrs()>
+
+Returns the attribute names that apply to clients.
+
+=over
+
+=item Return Value
+
+An array of attribute names.
+
+=back
+
+=cut
+
+sub getClientAttrs
+{
+ my $class = shift;
+
+ $class->_init() if !%AttributeInfo;
+
+ return
+ grep { $AttributeInfo{$_}->{"applies_to_clients"} }
+ keys %AttributeInfo
+}
+
+=item C<findProblematicValues()>
+
+Checks if the given stage3 attribute values are allowed (and make sense).
+
+This method returns an array-ref of problems found. If there were no problems,
+this methods returns undef.
+
+=cut
+
+sub findProblematicValues
+{
+ my $class = shift;
+ my $stage3Attrs = shift || {};
+ my $vendorOSName = shift;
+ my $installedPlugins = shift;
+
+ $class->_init() if !%AttributeInfo;
+
+ my @problems;
+
+ my %attrsByPlugin;
+ foreach my $key (sort keys %{$stage3Attrs}) {
+ my $value = $stage3Attrs->{$key};
+ if ($key =~ m{^(.+)::.+?$}) {
+ my $pluginName = $1;
+ if ($installedPlugins
+ && !grep { $_->{plugin_name} eq $pluginName } @$installedPlugins) {
+ # avoid checking attributes of plugins that are not installed
+ next;
+ }
+ $attrsByPlugin{$pluginName} ||= {};
+ $attrsByPlugin{$pluginName}->{$key} = $value;
+ }
+
+ # undefined values are always allowed
+ next if !defined $value;
+
+ # check the value against the regex of the attribute (if any)
+ my $attrInfo = $AttributeInfo{$key};
+ if (!$attrInfo) {
+ push @problems, _tr('attribute "%s" is unknown!', $key);
+ next;
+ }
+ my $regex = $attrInfo->{content_regex};
+ if ($regex && $value !~ $regex) {
+ push @problems, _tr(
+ "the value '%s' for attribute %s is not allowed.\nAllowed values are: %s",
+ $value, $key, $attrInfo->{content_descr}
+ );
+ }
+ }
+
+ # if no vendorOS-name has been provided or there are no plugins installed,
+ # we can't do any further checks
+ if ($vendorOSName && $installedPlugins) {
+ # now give each installed plugin a chance to check it's own attributes
+ # by itself
+ foreach my $pluginInfo (
+ sort { $a->{plugin_name} cmp $b->{plugin_name} } @$installedPlugins
+ ) {
+ my $pluginName = $pluginInfo->{plugin_name};
+ vlog 2, "checking attrs of plugin: $pluginName\n";
+ # create & start OSPlugin-engine for vendor-OS and current plugin
+ my $engine = OpenSLX::OSPlugin::Engine->new;
+ if (!$engine->initialize($pluginName, $vendorOSName)) {
+ warn _tr(
+ 'unable to create engine for plugin "%s"!', $pluginName
+ );
+ next;
+ }
+ $engine->checkStage3AttrValues(
+ $attrsByPlugin{$pluginName}, \@problems
+ );
+ }
+ }
+
+ return if !@problems;
+
+ return \@problems;
+}
+
+=item C<computeMD5HashOverAllAttrs()>
+
+Returns a MD5 hash representing the list of all attributes (including plugins).
+
+=cut
+
+sub computeMD5HashOverAllAttrs
+{
+ my $class = shift;
+
+ $class->_init() if !%AttributeInfo;
+
+ my %attrNames;
+ @attrNames{keys %AttributeInfo} = ();
+
+ my $pluginInfo = OpenSLX::OSPlugin::Roster->getAvailablePlugins();
+ if ($pluginInfo) {
+ foreach my $pluginName (sort keys %$pluginInfo) {
+ my $attrInfo
+ = OpenSLX::OSPlugin::Roster->getPluginAttrInfo($pluginName);
+ @attrNames{keys %$attrInfo} = ();
+ }
+ }
+
+ my $attrNamesAsString = join ',', sort keys %attrNames;
+
+ return md5_hex($attrNamesAsString);
+}
+
+1;