diff options
Diffstat (limited to 'config-db/OpenSLX')
-rw-r--r-- | config-db/OpenSLX/ConfigDB.pm | 301 | ||||
-rw-r--r-- | config-db/OpenSLX/DBSchema.pm | 173 | ||||
-rw-r--r-- | config-db/OpenSLX/MetaDB/DBI.pm | 543 |
3 files changed, 661 insertions, 356 deletions
diff --git a/config-db/OpenSLX/ConfigDB.pm b/config-db/OpenSLX/ConfigDB.pm index 95183c95..289f6f7f 100644 --- a/config-db/OpenSLX/ConfigDB.pm +++ b/config-db/OpenSLX/ConfigDB.pm @@ -561,6 +561,15 @@ sub fetchSystemByFilter $filter, $resultCols, $attrFilter ); + # unless specific result cols have been given, we mix in the attributes + # of each system, too: + if (!defined $resultCols) { + foreach my $system (@systems) { + $system->{attrs} + = $self->{'meta-db'}->fetchSystemAttrs($system->{id}); + } + } + return wantarray() ? @systems : shift @systems; } @@ -596,91 +605,16 @@ sub fetchSystemByID # unless specific result cols have been given, we mix in the attributes # of each system, too: -# if (!defined $resultCols) { -# foreach my $system (@systems) { -# $system->{attrs} -# = $self->{'meta-db'}->fetchSystemAttrs($system->{id}); -# } -# } + if (!defined $resultCols) { + foreach my $system (@systems) { + $system->{attrs} + = $self->{'meta-db'}->fetchSystemAttrs($system->{id}); + } + } return wantarray() ? @systems : shift @systems; } -=item C<fetchSystemAttrs($systemID, [$attrNames])> - -Fetches and returns the information about the attributes of the system -with the given ID. - -=over - -=item Param C<$systemID> - -The ID of the system whose attributes you are interested in. - -=item Param C<$attrNames> [Optional] - -A comma-separated list of attribute names that shall be returned. If not -defined,all available attributes will be returned. - -=item Return Value - -An array of hash-refs containing the resulting data rows (or a single hash-ref -mapping all attribute names to the respective value). - -=back - -=cut - -sub fetchSystemAttrs -{ - my $self = shift; - my $systemID = shift; - my $attrNames = shift; - - my @attrs = $self->{'meta-db'}->fetchSystemAttrs($systemID, $attrNames); - - return wantarray() ? @attrs : shift @attrs; -} - -=item C<fetchSystemAttrsAsHash($systemID, [$attrNames])> - -Fetches and returns the information about the attributes of the system -with the given ID. - -=over - -=item Param C<$systemID> - -The ID of the system whose attributes you are interested in. - -=item Param C<$attrNames> [Optional] - -A comma-separated list of attribute names that shall be returned. If not -defined,all available attributes will be returned. - -=item Return Value - -A single hash-ref mapping all attribute names to their respective value. - -=back - -=cut - -sub fetchSystemAttrsAsHash -{ - my $self = shift; - my $systemID = shift; - my $attrNames = shift; - - my @attrs = $self->{'meta-db'}->fetchSystemAttrs($systemID, $attrNames); - - my $Result = {}; - foreach my $attr (@attrs) { - $Result->{$attr->{name}} = $attr->{value}; - } - return $Result; -} - =item C<fetchSystemIDsOfExport($id)> Fetches the IDs of all systems that make use of the export with the given ID. @@ -787,10 +721,23 @@ An array of hash-refs containing the resulting data rows. sub fetchClientByFilter { - my $self = shift; - my $filter = shift; + my $self = shift; + my $filter = shift; + my $resultCols = shift; + my $attrFilter = shift; - my @clients = $self->{'meta-db'}->fetchClientByFilter($filter); + my @clients = $self->{'meta-db'}->fetchClientByFilter( + $filter, $resultCols, $attrFilter + ); + + # unless specific result cols have been given, we mix in the attributes + # of each client, too: + if (!defined $resultCols) { + foreach my $client (@clients) { + $client->{attrs} + = $self->{'meta-db'}->fetchClientAttrs($client->{id}); + } + } return wantarray() ? @clients : shift @clients; } @@ -825,6 +772,15 @@ sub fetchClientByID my @clients = $self->{'meta-db'}->fetchClientByID($ids, $resultCols); + # unless specific result cols have been given, we mix in the attributes + # of each client, too: + if (!defined $resultCols) { + foreach my $client (@clients) { + $client->{attrs} + = $self->{'meta-db'}->fetchClientAttrs($client->{id}); + } + } + return wantarray() ? @clients : shift @clients; } @@ -911,8 +867,20 @@ sub fetchGroupByFilter my $self = shift; my $filter = shift; my $resultCols = shift; + my $attrFilter = shift; - my @groups = $self->{'meta-db'}->fetchGroupByFilter($filter, $resultCols); + my @groups = $self->{'meta-db'}->fetchGroupByFilter( + $filter, $resultCols, $attrFilter + ); + + # unless specific result cols have been given, we mix in the attributes + # of each group, too: + if (!defined $resultCols) { + foreach my $group (@groups) { + $group->{attrs} + = $self->{'meta-db'}->fetchGroupAttrs($group->{id}); + } + } return wantarray() ? @groups : shift @groups; } @@ -947,6 +915,15 @@ sub fetchGroupByID my @groups = $self->{'meta-db'}->fetchGroupByID($ids, $resultCols); + # unless specific result cols have been given, we mix in the attributes + # of each group, too: + if (!defined $resultCols) { + foreach my $group (@groups) { + $group->{attrs} + = $self->{'meta-db'}->fetchGroupAttrs($group->{id}); + } + } + return wantarray() ? @groups : shift @groups; } @@ -1707,6 +1684,43 @@ sub changeClient return $self->{'meta-db'}->changeClient($clientIDs, $valRows); } +=item C<setClientAttr($clientID, $attrName, $attrValue)> + +Sets a value for an attribute of the given client. If the client already +has a value for this attribute, it will be overwritten. + +=over + +=item Param C<clientID> + +The ID of the client whose attribute shall be changed. + +=item Param C<attrName> + +The name of the attribute to change. + +=item Param C<attrValue> + +The new value for the attribute. + +=item Return Value + +C<1> if the attribute could be set, C<undef> if not. + +=back + +=cut + +sub setClientAttr +{ + my $self = shift; + my $clientID = shift; + my $attrName = shift; + my $attrValue = shift; + + return $self->{'meta-db'}->setClientAttr($clientID, $attrName, $attrValue); +} + =item C<setSystemIDsOfClient($clientID, @$systemIDs)> Specifies all systems that should be offered for booting by the given client. @@ -1987,6 +2001,43 @@ sub removeGroup return $self->{'meta-db'}->removeGroup($groupIDs); } +=item C<setGroupAttr($groupID, $attrName, $attrValue)> + +Sets a value for an attribute of the given group. If the group already +has a value for this attribute, it will be overwritten. + +=over + +=item Param C<groupID> + +The ID of the group whose attribute shall be changed. + +=item Param C<attrName> + +The name of the attribute to change. + +=item Param C<attrValue> + +The new value for the attribute. + +=item Return Value + +C<1> if the attribute could be set, C<undef> if not. + +=back + +=cut + +sub setGroupAttr +{ + my $self = shift; + my $groupID = shift; + my $attrName = shift; + my $attrValue = shift; + + return $self->{'meta-db'}->setGroupAttr($groupID, $attrName, $attrValue); +} + =item C<changeGroup(@$groupIDs, @$valRows)> Changes the data of one or more groups. @@ -2588,13 +2639,17 @@ sub mergeAttributes my $target = shift; my $source = shift; - foreach my $key (keys %$source) { - next if !isAttribute($key); - my $sourceVal = $source->{$key} || ''; - my $targetVal = $target->{$key} || ''; - if (length($sourceVal) && !length($targetVal)) { - vlog(3, _tr("merging %s (val=%s)", $key, $sourceVal)); - $target->{$key} = $sourceVal; + my $sourceAttrs = $source->{attrs} || {}; + + $target->{attrs} ||= {}; + my $targetAttrs = $target->{attrs}; + + foreach my $key (keys %$sourceAttrs) { + my $sourceVal = $sourceAttrs->{$key}; + my $targetVal = $targetAttrs->{$key}; + if (defined $sourceVal && !defined $targetVal) { + vlog(0, _tr("merging %s (val=%s)", $key, $sourceVal)); + $targetAttrs->{$key} = $sourceVal; } } @@ -2628,11 +2683,16 @@ sub pushAttributes my $target = shift; my $source = shift; - foreach my $key (grep { isAttribute($_) } keys %$source) { - my $sourceVal = $source->{$key} || ''; - if (length($sourceVal)) { + my $sourceAttrs = $source->{attrs} || {}; + + $target->{attrs} ||= {}; + my $targetAttrs = $target->{attrs}; + + foreach my $key (keys %$sourceAttrs) { + my $sourceVal = $sourceAttrs->{$key}; + if (defined $sourceVal) { vlog(3, _tr("pushing %s (val=%s)", $key, $sourceVal)); - $target->{$key} = $sourceVal; + $targetAttrs->{$key} = $sourceVal; } } @@ -2826,54 +2886,7 @@ sub _checkAndUpgradeDBSchemaIfNecessary $DbSchema->{version}, $currVersion ) ); - foreach my $v (sort { $a <=> $b } keys %DbSchemaHistory) { - next if $v <= $currVersion; - my $changeSet = $DbSchemaHistory{$v}; - foreach my $c (0 .. scalar(@$changeSet) - 1) { - my $changeDescr = @{$changeSet}[$c]; - my $cmd = $changeDescr->{cmd}; - if ($cmd eq 'add-table') { - $metaDB->schemaAddTable( - $changeDescr->{'table'}, - $changeDescr->{'cols'}, - $changeDescr->{'vals'} - ); - } elsif ($cmd eq 'drop-table') { - $metaDB->schemaDropTable($changeDescr->{'table'}); - } elsif ($cmd eq 'rename-table') { - $metaDB->schemaRenameTable( - $changeDescr->{'old-table'}, - $changeDescr->{'new-table'}, - $changeDescr->{'cols'} - ); - } elsif ($cmd eq 'add-columns') { - $metaDB->schemaAddColumns( - $changeDescr->{'table'}, - $changeDescr->{'new-cols'}, - $changeDescr->{'new-default-vals'}, - $changeDescr->{'cols'} - ); - } elsif ($cmd eq 'drop-columns') { - $metaDB->schemaDropColumns( - $changeDescr->{'table'}, - $changeDescr->{'drop-cols'}, - $changeDescr->{'cols'} - ); - } elsif ($cmd eq 'rename-columns') { - $metaDB->schemaRenameColumns( - $changeDescr->{'table'}, - $changeDescr->{'col-renames'}, - $changeDescr->{'cols'} - ); - } elsif ($cmd eq 'perl-func') { - if (!$changeDescr->{code}->($self)) { - croak _tr('problem in perl-func cmd!'); - } - } else { - croak _tr('UnknownDbSchemaCommand', $cmd); - } - } - } + $metaDB->schemaUpgradeDBFrom($currVersion); $metaDB->schemaSetDBVersion($DbSchema->{version}); vlog(1, _tr('upgrade done')); } else { diff --git a/config-db/OpenSLX/DBSchema.pm b/config-db/OpenSLX/DBSchema.pm index 54596c9f..801f50a9 100644 --- a/config-db/OpenSLX/DBSchema.pm +++ b/config-db/OpenSLX/DBSchema.pm @@ -33,12 +33,7 @@ use OpenSLX::Basics; use POSIX qw(locale_h); my $lang = setlocale(LC_MESSAGES); -my $country; -if ($lang =~ m[^\w\w_(\w\w)]) { - $country = lc($1); -} else { - $country = 'us'; -} +my $country = $lang =~ m[^\w\w_(\w\w)] ? lc($1) : 'us'; ################################################################################ ### DB-schema definition @@ -73,12 +68,22 @@ $DbSchema = { ], 'vals' => [ { # add default client - 'id' => 0, - 'name' => '<<<default>>>', - 'comment' => 'internal client that holds default values', + 'id' => 0, + 'name' => '<<<default>>>', + 'comment' => 'internal client that holds default values', + 'unbootable' => 0, }, ], }, + 'client_attr' => { + # attributes of clients + 'cols' => [ + 'id:pk', # primary key + 'client_id:fk', # foreign key to client + 'name:s.128', # attribute name + 'value:s.255', # attribute value + ], + }, 'client_system_ref' => { # clients referring to the systems they should offer for booting 'cols' => [ @@ -134,6 +139,15 @@ $DbSchema = { 'comment:s.1024', # internal comment (optional, for admins) ], }, + 'group_attr' => { + # attributes of groups + 'cols' => [ + 'id:pk', # primary key + 'group_id:fk', # foreign key to group + 'name:s.128', # attribute name + 'value:s.255', # attribute value + ], + }, 'group_client_ref' => { # groups referring to their clients 'cols' => [ @@ -394,146 +408,9 @@ $DbSchema = { }; ################################################################################ -### DB-schema history -### -### This hash contains a description of all the different changes that have -### taken place on the schema. Each version contains a changeset (array) -### with the commands that take the schema from the last version to the -### current. -### -### The following 'cmd'-types are supported: -### -### add-table => creates a new table -### 'table' => contains the name of the new table -### 'cols' => contains a list of column descriptions -### 'vals' => optional, contains list of data hashes to be inserted -### into new table -### -### drop-table => drops an existing table -### 'table => contains the name of the table to be dropped -### -### rename-table => renames a table -### 'old-table' => contains the old name of the table -### 'new-table' => contains the new name of the table -### 'cols' => contains a full list of column descriptions -### -### add-columns => adds columns to a table -### 'table' => the name of the table the columns should be added to -### 'new-cols' => contains a list of new column descriptions -### 'new-default-vals' => optional, a list of data hashes to be used -### as default values for the new columns -### 'cols' => contains a full list of resulting column descriptions -### -### drop-columns => drops columns from a table -### 'table' => the name of the table the columns should be dropped from -### 'drop-cols' => a list of column names to be dropped -### 'cols' => contains a full list of resulting column descriptions -### -### perl-func => a perl function invoked with config-DB object as param -### 'code' => the function (sub) that shall be executed -### -################################################################################ - -%DbSchemaHistory = ( - '0.01' => [ - # there's no need to upgrade to the initial schema version, as we - # create the newest schema automatically if none exists yet. - ], - '0.2' => [ - # move attributes into separate tables ... - # - # ... system attributes ... - { - 'cmd' => 'add-table', - 'table' => 'system_attr', - 'cols' => [ - 'id:pk', - 'system_id:fk', - 'name:s.128', - 'value:s.255', - ], - }, - { - 'cmd' => 'perl-func', - 'code' => sub { - my $configDB = shift; - foreach my $system ($configDB->fetchSystemByFilter()) { - foreach my $key (keys %$system) { - next if substr($key, 0, 5) ne 'attr_'; - my $attrValue = $system->{$key} || ''; - next if $system->{id}>0 && !length($attrValue); - my $newAttrName = substr($key, 5); - $configDB->setSystemAttr( - $system->{id}, $newAttrName, $attrValue - ); - } - } - 1; - } - }, - { - 'cmd' => 'drop-columns', - 'table' => 'system', - 'drop-cols' => [ - 'attr_automnt_dir', - 'attr_automnt_src', - 'attr_country', - 'attr_dm_allow_shutdown', - 'attr_hw_graphic', - 'attr_hw_monitor', - 'attr_hw_mouse', - 'attr_late_dm', - 'attr_netbios_workgroup', - 'attr_nis_domain', - 'attr_nis_servers', - 'attr_ramfs_fsmods', - 'attr_ramfs_miscmods', - 'attr_ramfs_nicmods', - 'attr_ramfs_screen', - 'attr_sane_scanner', - 'attr_scratch', - 'attr_slxgrp', - 'attr_start_alsasound', - 'attr_start_atd', - 'attr_start_cron', - 'attr_start_dreshal', - 'attr_start_ntp', - 'attr_start_nfsv4', - 'attr_start_printer', - 'attr_start_samba', - 'attr_start_snmp', - 'attr_start_sshd', - 'attr_start_syslog', - 'attr_start_x', - 'attr_start_xdmcp', - 'attr_tex_enable', - 'attr_timezone', - 'attr_tvout', - 'attr_vmware', - ], - 'cols' => [ - 'id:pk', - 'export_id:fk', - 'name:s.64', - 'label:s.64', - 'kernel:s.128', - 'kernel_params:s.512', - 'hidden:b', - 'comment:s.1024', - ], - }, - # - # ... client attributes ... - # - # ... group attributes ... - ], -); - - -################################################################################ ### -### Load all available AttrInfo modules and build the complete hash containing -### info about all known attributes from that. +### Load the available AttrInfo-modules and build a hash containing info about +### all known attributes from the data contained in those modules. ### ################################################################################ diff --git a/config-db/OpenSLX/MetaDB/DBI.pm b/config-db/OpenSLX/MetaDB/DBI.pm index 774ab90e..98754777 100644 --- a/config-db/OpenSLX/MetaDB/DBI.pm +++ b/config-db/OpenSLX/MetaDB/DBI.pm @@ -78,14 +78,13 @@ sub _trim sub _buildFilterClause { - my $self = shift; - my $filter = shift || {}; - my $connector = shift; + my $self = shift; + my $filter = shift || {}; + my $filterClause = shift || ''; - my $filterClause = ''; - my ($quotedVal); + my ($connector, $quotedVal); foreach my $col (keys %$filter) { - $connector = !defined $connector ? 'WHERE' : 'AND'; + $connector = !length($filterClause) ? 'WHERE' : 'AND'; if (defined $filter->{$col}) { $quotedVal = $self->{dbh}->quote($filter->{$col}); $filterClause .= " $connector $col = $quotedVal"; @@ -94,42 +93,48 @@ sub _buildFilterClause } } - return $filterClause; + return $filterClause || ''; } sub _buildAttrFilterClause { - my $self = shift; - my $attrFilter = shift || {}; - my $connector = shift; + my $self = shift; + my $attrFilter = shift || {}; + my $table = shift; + my $filterClause = shift || ''; + + my %tableMap = ( + 'client' => 'client', + 'group' => 'groups', + 'system' => 'system', + ); - my $attrFilterClause = ''; - my ($quotedName, $quotedValue); + my ($connector, $quotedName, $quotedValue); foreach my $name (keys %$attrFilter) { - $connector = !defined $connector ? 'WHERE' : 'AND'; + $connector = !length($filterClause) ? 'WHERE' : 'AND'; $quotedName = $self->{dbh}->quote($name); if (defined $attrFilter->{$name}) { $quotedValue = $self->{dbh}->quote($attrFilter->{$name}); - $attrFilterClause .= <<" End-of-Here"; + $filterClause .= <<" End-of-Here"; $connector EXISTS ( - SELECT name FROM system_attr + SELECT name FROM ${table}_attr WHERE name = $quotedName AND value = $quotedValue - AND system_id = system.id + AND ${table}_id = $tableMap{$table}.id ) End-of-Here } else { - $attrFilterClause .= <<" End-of-Here"; + $filterClause .= <<" End-of-Here"; $connector NOT EXISTS ( - SELECT name FROM system_attr + SELECT name FROM ${table}_attr WHERE name = $quotedName - AND system_id = system.id + AND ${table}_id = $tableMap{$table}.id ) End-of-Here } } - return $attrFilterClause; + return $filterClause; } sub _doSelect @@ -245,13 +250,13 @@ sub fetchSystemByFilter my $attrFilter = shift; $resultCols = '*' unless (defined $resultCols); - my $filterClause = $self->_buildFilterClause($filter, 'AND'); - my $attrFilterClause = $self->_buildAttrFilterClause($attrFilter, 'AND'); + my $filterClause = $self->_buildFilterClause($filter); + $filterClause = $self->_buildAttrFilterClause( + $attrFilter, 'system', $filterClause + ); my $sql = <<" End-of-Here"; SELECT $resultCols FROM system - WHERE 1=1 $filterClause - $attrFilterClause End-of-Here return $self->_doSelect($sql); } @@ -273,17 +278,17 @@ sub fetchSystemAttrs { my $self = shift; my $systemID = $self->{dbh}->quote(shift); - my $attrNames = shift; my $sql = <<" End-of-Here"; - SELECT id, name, value FROM system_attr + SELECT name, value FROM system_attr WHERE system_id = $systemID End-of-Here - if (defined $attrNames) { - my $attrList = join ',', map { $self->{dbh}->quote($_) } @$attrNames; - $sql .= " AND name IN ($attrList)"; + my @attrs = $self->_doSelect($sql); + my $Result = {}; + foreach my $attr (@attrs) { + $Result->{$attr->{name}} = $attr->{value}; } - return $self->_doSelect($sql); + return $Result; } sub fetchSystemIDsOfExport @@ -324,10 +329,17 @@ sub fetchClientByFilter my $self = shift; my $filter = shift; my $resultCols = shift; + my $attrFilter = shift; $resultCols = '*' unless (defined $resultCols); my $filterClause = $self->_buildFilterClause($filter); - my $sql = "SELECT $resultCols FROM client $filterClause"; + $filterClause = $self->_buildAttrFilterClause( + $attrFilter, 'client', $filterClause + ); + my $sql = <<" End-of-Here"; + SELECT $resultCols FROM client + $filterClause + End-of-Here return $self->_doSelect($sql); } @@ -344,6 +356,23 @@ sub fetchClientByID return $self->_doSelect($sql); } +sub fetchClientAttrs +{ + my $self = shift; + my $clientID = $self->{dbh}->quote(shift); + + my $sql = <<" End-of-Here"; + SELECT name, value FROM client_attr + WHERE client_id = $clientID + End-of-Here + my @attrs = $self->_doSelect($sql); + my $Result = {}; + foreach my $attr (@attrs) { + $Result->{$attr->{name}} = $attr->{value}; + } + return $Result; +} + sub fetchClientIDsOfSystem { my $self = shift; @@ -371,10 +400,17 @@ sub fetchGroupByFilter my $self = shift; my $filter = shift; my $resultCols = shift; + my $attrFilter = shift; $resultCols = '*' unless (defined $resultCols); my $filterClause = $self->_buildFilterClause($filter); - my $sql = "SELECT $resultCols FROM groups $filterClause"; + $filterClause = $self->_buildAttrFilterClause( + $attrFilter, 'group', $filterClause + ); + my $sql = <<" End-of-Here"; + SELECT $resultCols FROM groups + $filterClause + End-of-Here return $self->_doSelect($sql); } @@ -391,6 +427,23 @@ sub fetchGroupByID return $self->_doSelect($sql); } +sub fetchGroupAttrs +{ + my $self = shift; + my $groupID = $self->{dbh}->quote(shift); + + my $sql = <<" End-of-Here"; + SELECT name, value FROM group_attr + WHERE group_id = $groupID + End-of-Here + my @attrs = $self->_doSelect($sql); + my $Result = {}; + foreach my $attr (@attrs) { + $Result->{$attr->{name}} = $attr->{value}; + } + return $Result; +} + sub fetchGroupIDsOfSystem { my $self = shift; @@ -505,20 +558,22 @@ sub _doUpdate my $dbh = $self->{'dbh'}; my $valRow = (@$valRows)[0]; - return if !defined $valRow || !scalar keys %$valRow; + return 1 if !defined $valRow || !scalar keys %$valRow; my $idx = 0; foreach my $valRow (@$valRows) { my $id = $IDs->[$idx++]; my %valData = %$valRow; - delete $valData{'id'}; - # filter column 'id' if present, as we don't want to update it + # fail if asked to change the column 'id', as that is bogus + return if exists $valData{id} && $valData{id} ne $id; + # filter column 'id' if present, as we don't want to write it + delete $valData{id}; my @cols = map { "$_ = " . $self->quote($valRow->{$_}) } grep { $_ ne 'id' } # filter column 'id' if present, as we don't want # to update it! keys %$valRow; - return if !@cols; + next if !@cols; my $cols = join ', ', @cols; my $sql = "UPDATE $table SET $cols"; if (defined $id) { @@ -661,7 +716,26 @@ sub addSystem my $self = shift; my $valRows = shift; - return $self->_doInsert('system', $valRows); + # separate the attribute hashes ... + my @attrValRows + = map { + my $attrs = $_->{attrs}; + delete $_->{attrs}; + $attrs; + } + @$valRows; + + # ... store the systems to get the IDs ... + my @systemIDs = $self->_doInsert('system', $valRows); + + # ... finally store the individual attribute sets + foreach my $id (@systemIDs) { + my $attrs = shift @attrValRows; + next if !defined $attrs; + return if !$self->setSystemAttrs($id, $attrs); + } + + return @systemIDs; } sub removeSystem @@ -678,37 +752,44 @@ sub changeSystem my $systemIDs = shift; my $valRows = shift; + # separate the attribute hashes and store them individually + my @attrValRows + = map { + my $attrs = $_->{attrs}; + delete $_->{attrs}; + $attrs; + } + @$valRows; + foreach my $id (@$systemIDs) { + my $attrs = shift @attrValRows; + next if !defined $attrs; + return if !$self->setSystemAttrs($id, $attrs); + } + + # finally update all systems in one go return $self->_doUpdate('system', $systemIDs, $valRows); } -sub setSystemAttr +sub setSystemAttrs { - my $self = shift; - my $systemID = shift; - my $attrName = shift; - my $attrValue = shift; - - my $quotedSystemID = $self->{dbh}->quote($systemID); - my $quotedAttrName = $self->{dbh}->quote($attrName); - - my $sql = <<" End-of-Here"; - SELECT id FROM system_attr - WHERE system_id = $quotedSystemID - AND name = $quotedAttrName - End-of-Here - my $id = $self->_doSelect($sql, 'id'); - if ($id) { - return $self->_doUpdate( - 'system_attr', [ $id ], [ { value => $attrValue } ] + my $self = shift; + my $systemID = shift; + my $attrs = shift; + + # we take the simple path and remove all attributes ... + return if !$self->_doDelete('system_attr', [ $systemID ], 'system_id'); + + # ... and (re-)insert the given ones + foreach my $key (keys %$attrs) { + return if !$self->_doInsert( + 'system_attr', [ { + system_id => $systemID, + name => $key, + value => $attrs->{$key}, + } ] ); } - return $self->_doInsert( - 'system_attr', [ { - system_id => $systemID, - name => $attrName, - value => $attrValue, - } ] - ); + return 1; } sub setClientIDsOfSystem @@ -742,7 +823,26 @@ sub addClient my $self = shift; my $valRows = shift; - return $self->_doInsert('client', $valRows); + # separate the attribute hashes ... + my @attrValRows + = map { + my $attrs = $_->{attrs}; + delete $_->{attrs}; + $attrs; + } + @$valRows; + + # ... store the clients to get the IDs ... + my @clientIDs = $self->_doInsert('client', $valRows); + + # ... finally store the individual attribute sets + foreach my $id (@clientIDs) { + my $attrs = shift @attrValRows; + next if !defined $attrs; + return if !$self->setClientAttrs($id, $attrs); + } + + return @clientIDs; } sub removeClient @@ -759,9 +859,46 @@ sub changeClient my $clientIDs = shift; my $valRows = shift; + # separate the attribute hashes and store them individually + my @attrValRows + = map { + my $attrs = $_->{attrs}; + delete $_->{attrs}; + $attrs; + } + @$valRows; + foreach my $id (@$clientIDs) { + my $attrs = shift @attrValRows; + next if !defined $attrs; + return if !$self->setClientAttrs($id, $attrs); + } + + # finally update all systems in one go return $self->_doUpdate('client', $clientIDs, $valRows); } +sub setClientAttrs +{ + my $self = shift; + my $clientID = shift; + my $attrs = shift; + + # we take the simple path and remove all attributes ... + return if !$self->_doDelete('client_attr', [ $clientID ], 'client_id'); + + # ... and (re-)insert the given ones + foreach my $key (keys %$attrs) { + return if !$self->_doInsert( + 'client_attr', [ { + client_id => $clientID, + name => $key, + value => $attrs->{$key}, + } ] + ); + } + return 1; +} + sub setSystemIDsOfClient { my $self = shift; @@ -793,7 +930,26 @@ sub addGroup my $self = shift; my $valRows = shift; - return $self->_doInsert('groups', $valRows); + # separate the attribute hashes ... + my @attrValRows + = map { + my $attrs = $_->{attrs}; + delete $_->{attrs}; + $attrs; + } + @$valRows; + + # ... store the groups to get the IDs ... + my @groupIDs = $self->_doInsert('groups', $valRows); + + # ... finally store the individual attribute sets + foreach my $id (@groupIDs) { + my $attrs = shift @attrValRows; + next if !defined $attrs; + return if !$self->setGroupAttrs($id, $attrs); + } + + return @groupIDs; } sub removeGroup @@ -810,9 +966,46 @@ sub changeGroup my $groupIDs = shift; my $valRows = shift; + # separate the attribute hashes and store them individually + my @attrValRows + = map { + my $attrs = $_->{attrs}; + delete $_->{attrs}; + $attrs; + } + @$valRows; + foreach my $id (@$groupIDs) { + my $attrs = shift @attrValRows; + next if !defined $attrs; + return if !$self->setGroupAttrs($id, $attrs); + } + + # finally update all groups in one go return $self->_doUpdate('groups', $groupIDs, $valRows); } +sub setGroupAttrs +{ + my $self = shift; + my $groupID = shift; + my $attrs = shift; + + # we take the simple path and remove all attributes ... + return if !$self->_doDelete('group_attr', [ $groupID ], 'group_id'); + + # ... and (re-)insert the given ones + foreach my $key (keys %$attrs) { + return if !$self->_doInsert( + 'group_attr', [ { + group_id => $groupID, + name => $key, + value => $attrs->{$key}, + } ] + ); + } + return 1; +} + sub setClientIDsOfGroup { my $self = shift; @@ -896,6 +1089,16 @@ sub schemaFetchDBVersion return $row->{schema_version}; } +sub schemaUpgradeDBFrom +{ + my $self = shift; + my $currVersion = shift; + + $self->_upgradeDBTo0_2() if $currVersion < 0.2; + + return 1; +} + sub schemaSetDBVersion { my $self = shift; @@ -1114,6 +1317,218 @@ sub schemaChangeColumns return; } +sub _upgradeDBTo0_2 +{ + my $self = shift; + + # move attributes into separate tables ... + # + # ... system attributes ... + $self->schemaAddTable( + 'system_attr', + [ + 'id:pk', + 'system_id:fk', + 'name:s.128', + 'value:s.255', + ] + ); + foreach my $system ($self->fetchSystemByFilter()) { + my %attrs; + foreach my $key (keys %$system) { + next if substr($key, 0, 5) ne 'attr_'; + my $attrValue = $system->{$key} || ''; + next if $system->{id} > 0 && !length($attrValue); + my $newAttrName = substr($key, 5); + $attrs{$newAttrName} = $attrValue; + } + $self->setSystemAttrs($system->{id}, \%attrs); + } + $self->schemaDropColumns( + 'system', + [ + 'attr_automnt_dir', + 'attr_automnt_src', + 'attr_country', + 'attr_dm_allow_shutdown', + 'attr_hw_graphic', + 'attr_hw_monitor', + 'attr_hw_mouse', + 'attr_late_dm', + 'attr_netbios_workgroup', + 'attr_nis_domain', + 'attr_nis_servers', + 'attr_ramfs_fsmods', + 'attr_ramfs_miscmods', + 'attr_ramfs_nicmods', + 'attr_ramfs_screen', + 'attr_sane_scanner', + 'attr_scratch', + 'attr_slxgrp', + 'attr_start_alsasound', + 'attr_start_atd', + 'attr_start_cron', + 'attr_start_dreshal', + 'attr_start_ntp', + 'attr_start_nfsv4', + 'attr_start_printer', + 'attr_start_samba', + 'attr_start_snmp', + 'attr_start_sshd', + 'attr_start_syslog', + 'attr_start_x', + 'attr_start_xdmcp', + 'attr_tex_enable', + 'attr_timezone', + 'attr_tvout', + 'attr_vmware', + ], + [ + 'id:pk', + 'export_id:fk', + 'name:s.64', + 'label:s.64', + 'kernel:s.128', + 'kernel_params:s.512', + 'hidden:b', + 'comment:s.1024', + ] + ); + # + # ... client attributes ... + $self->schemaAddTable( + 'client_attr', + [ + 'id:pk', + 'client_id:fk', + 'name:s.128', + 'value:s.255', + ] + ); + foreach my $client ($self->fetchClientByFilter()) { + my %attrs; + foreach my $key (keys %$client) { + next if substr($key, 0, 5) ne 'attr_'; + my $attrValue = $client->{$key} || ''; + next if !length($attrValue); + my $newAttrName = substr($key, 5); + $attrs{$newAttrName} = $attrValue; + } + $self->setClientAttrs($client->{id}, \%attrs); + } + $self->schemaDropColumns( + 'client', + [ + 'attr_automnt_dir', + 'attr_automnt_src', + 'attr_country', + 'attr_dm_allow_shutdown', + 'attr_hw_graphic', + 'attr_hw_monitor', + 'attr_hw_mouse', + 'attr_late_dm', + 'attr_netbios_workgroup', + 'attr_nis_domain', + 'attr_nis_servers', + 'attr_sane_scanner', + 'attr_scratch', + 'attr_slxgrp', + 'attr_start_alsasound', + 'attr_start_atd', + 'attr_start_cron', + 'attr_start_dreshal', + 'attr_start_ntp', + 'attr_start_nfsv4', + 'attr_start_printer', + 'attr_start_samba', + 'attr_start_snmp', + 'attr_start_sshd', + 'attr_start_syslog', + 'attr_start_x', + 'attr_start_xdmcp', + 'attr_tex_enable', + 'attr_timezone', + 'attr_tvout', + 'attr_vmware', + ], + [ + 'id:pk', + 'name:s.128', + 'mac:s.20', + 'boot_type:s.20', + 'unbootable:b', + 'kernel_params:s.128', + 'comment:s.1024', + ] + ); + # + # ... group attributes ... + $self->schemaAddTable( + 'group_attr', + [ + 'id:pk', + 'group_id:fk', + 'name:s.128', + 'value:s.255', + ] + ); + foreach my $group ($self->fetchGroupByFilter()) { + my %attrs; + foreach my $key (keys %$group) { + next if substr($key, 0, 5) ne 'attr_'; + my $attrValue = $group->{$key} || ''; + next if !length($attrValue); + my $newAttrName = substr($key, 5); + $attrs{$newAttrName} = $attrValue; + } + $self->setGroupAttrs($group->{id}, \%attrs); + } + $self->schemaDropColumns( + 'groups', + [ + 'attr_automnt_dir', + 'attr_automnt_src', + 'attr_country', + 'attr_dm_allow_shutdown', + 'attr_hw_graphic', + 'attr_hw_monitor', + 'attr_hw_mouse', + 'attr_late_dm', + 'attr_netbios_workgroup', + 'attr_nis_domain', + 'attr_nis_servers', + 'attr_sane_scanner', + 'attr_scratch', + 'attr_slxgrp', + 'attr_start_alsasound', + 'attr_start_atd', + 'attr_start_cron', + 'attr_start_dreshal', + 'attr_start_ntp', + 'attr_start_nfsv4', + 'attr_start_printer', + 'attr_start_samba', + 'attr_start_snmp', + 'attr_start_sshd', + 'attr_start_syslog', + 'attr_start_x', + 'attr_start_xdmcp', + 'attr_tex_enable', + 'attr_timezone', + 'attr_tvout', + 'attr_vmware', + ], + [ + 'id:pk', + 'name:s.128', + 'priority:i', + 'comment:s.1024', + ] + ); + + return 1; +} + 1; =head1 NAME |