X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=installcheck%2FAmanda_Config.pl;h=0aac704037a33df665b15fc18c03fa7707753dbb;hb=691567b16c13087b31ee4c2b6d038e57872fae82;hp=fece651687c31076a8fcc33d4b850f461dd5c365;hpb=d5853102f67d85d8e169f9dbe973ad573306c215;p=debian%2Famanda diff --git a/installcheck/Amanda_Config.pl b/installcheck/Amanda_Config.pl index fece651..0aac704 100644 --- a/installcheck/Amanda_Config.pl +++ b/installcheck/Amanda_Config.pl @@ -1,8 +1,9 @@ -# Copyright (c) 2007, 2008, 2009, 2010 Zmanda, Inc. All Rights Reserved. +# Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved. # -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 as published -# by the Free Software Foundation. +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY @@ -16,14 +17,16 @@ # Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com -use Test::More tests => 176; +use Test::More tests => 224; use strict; +use warnings; +use Data::Dumper; use lib "@amperldir@"; use Installcheck::Config; use Amanda::Paths; use Amanda::Tests; -use Amanda::Config qw( :init :getconf string_to_boolean ); +use Amanda::Config qw( :init :getconf string_to_boolean amandaify_property_name ); use Amanda::Debug; my $testconf; @@ -64,7 +67,7 @@ is(getconf($CNF_TAPEDEV), "null:TEST", # Check out error handling $testconf = Installcheck::Config->new(); -$testconf->add_param('tapebufs', '13'); # a deprecated keyword -> warning +$testconf->add_param('label_new_tapes', '"xx"'); # a deprecated keyword -> warning $testconf->write(); { @@ -97,6 +100,8 @@ $testconf = Installcheck::Config->new(); $testconf->add_client_param('property', '"client-prop" "yep"'); $testconf->add_client_param('property', 'priority "clIent-prop1" "foo"'); $testconf->add_client_param('property', 'append "clieNt-prop" "bar"'); +$testconf->add_client_param('property', '"ANotHer_prOp" "baz"'); +$testconf->add_client_param('property', 'append "ANOTHER-prop" "boo"'); $testconf->write(); my $cfg_result = config_init($CONFIG_INIT_CLIENT, undef); @@ -109,7 +114,10 @@ is_deeply(getconf($CNF_PROPERTY), { "client-prop1" => { priority => 1, values => [ "foo" ]}, "client-prop" => { priority => 0, append => 1, - values => [ "yep", "bar" ] }}, + values => [ "yep", "bar" ] }, + "another-prop" => { priority => 0, + append => 1, + values => [ "baz", "boo" ] }}, "Client PROPERTY parameter parsed correctly"); ## @@ -143,6 +151,10 @@ $testconf->add_param('debug_auth', '1'); $testconf->add_tapetype('mytapetype', [ 'comment' => '"mine"', 'length' => '128 M', + 'part_size' => '100M', + 'part_cache_type' => 'disk', + 'part_cache_dir' => '"/usr/bin"', + 'part_cache_max_size' => '50M', ]); $testconf->add_dumptype('mydump-type', [ # note dash 'comment' => '"mine"', @@ -163,7 +175,9 @@ $testconf->add_dumptype('mydump-type', [ # note dash 'include file optional' => '"rhyme"', 'property' => '"prop" "erty"', 'property' => '"DROP" "qwerty" "asdfg"', - 'estimate' => 'server calcsize client' + 'estimate' => 'server calcsize client', + 'allow_split' => 'no', + 'allow_split' => 'no', ]); $testconf->add_dumptype('second_dumptype', [ # note underscore '' => 'mydump-type', @@ -172,6 +186,7 @@ $testconf->add_dumptype('second_dumptype', [ # note underscore $testconf->add_dumptype('third_dumptype', [ '' => 'second_dumptype', 'comment' => '"refers to second_dumptype with an underscore"', + 'recovery-limit' => '"left" same-host "right"', ]); $testconf->add_interface('ethernet', [ 'comment' => '"mine"', @@ -198,12 +213,13 @@ $testconf->add_script('my_script', [ 'plugin' => '"script-email"', 'execute-on' => 'pre-host-backup, post-host-backup', 'execute-where' => 'client', - 'property' => '"mailto" "amandabackup" "amanda"', + 'property' => '"mailto" "backup" "amanda"', ]); $testconf->add_device('my_device', [ 'comment' => '"my device is mine, not yours"', 'tapedev' => '"tape:/dev/nst0"', 'device_property' => '"BLOCK_SIZE" "128k"', + 'device_property' => '"CoMmENT" "what up?"', ]); $testconf->add_changer('my_changer', [ 'comment' => '"my changer is mine, not yours"', @@ -213,309 +229,344 @@ $testconf->add_changer('my_changer', [ 'property' => '"testprop" "testval"', 'device_property' => '"testdprop" "testdval"', ]); +$testconf->add_interactivity('my_interactivity', [ + 'comment' => '"my interactivity is mine, not yours"', + 'plugin' => '"MY-interactivity"', + 'property' => '"testprop" "testval"', +]); + +$testconf->add_taperscan('my_taperscan', [ + 'comment' => '"my taperscan is mine, not yours"', + 'plugin' => '"MY-taperscan"', + 'property' => '"testprop" "testval"', +]); $testconf->write(); $cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, 'TESTCONF'); -is($cfg_result, $CFGERR_OK, - "Load test configuration") - or diag_config_errors(); - -SKIP: { - skip "error loading config", 3 unless $cfg_result == $CFGERR_OK; - - is(Amanda::Config::get_config_name(), "TESTCONF", - "config_name set"); - is(Amanda::Config::get_config_dir(), "$CONFIG_DIR/TESTCONF", - "config_dir set"); - is(Amanda::Config::get_config_filename(), - "$CONFIG_DIR/TESTCONF/amanda.conf", - "config_filename set"); +if (!is($cfg_result, $CFGERR_OK, + "Load test configuration")) { + diag_config_errors(); + die "aborting after config errors"; } -SKIP: { # global parameters - skip "error loading config", 13 unless $cfg_result == $CFGERR_OK; - - is(getconf($CNF_RESERVE), 75, - "integer global confparm"); - is(getconf($CNF_BUMPSIZE), $int64_num+0, - "int64 global confparm"); - is(getconf($CNF_TAPEDEV), "/dev/foo", - "string global confparm"); - is(getconf($CNF_DEVICE_OUTPUT_BUFFER_SIZE), $size_t_num+0, - "size global confparm"); - ok(getconf($CNF_AUTOFLUSH), - "boolean global confparm"); - is(getconf($CNF_USETIMESTAMPS), 0, - "boolean global confparm, passing an integer (0)"); - is(getconf($CNF_TAPERALGO), $Amanda::Config::ALGO_LAST, - "taperalgo global confparam"); - is_deeply([getconf($CNF_RESERVED_UDP_PORT)], [100,200], - "intrange global confparm"); - is(getconf($CNF_DISPLAYUNIT), "M", - "displayunit is correctly uppercased"); - is_deeply(getconf($CNF_DEVICE_PROPERTY), - { "foo" => { priority => 0, append => 0, values => ["bar"]}, - "blue" => { priority => 0, append => 0, - values => ["car", "tar"]} }, - "proplist global confparm"); - is_deeply(getconf($CNF_AUTOLABEL), - { template => undef, other_config => '', - non_amanda => 1, volume_error => '', empty => 1 }, - "'autolabel non-amanda empty' represented correctly"); - ok(getconf_seen($CNF_TAPEDEV), - "'tapedev' parm was seen"); - ok(!getconf_seen($CNF_CHANGERFILE), - "'changerfile' parm was not seen"); -} - -SKIP: { # derived values - skip "error loading config", 3 unless $cfg_result == $CFGERR_OK; +is(Amanda::Config::get_config_name(), "TESTCONF", + "config_name set"); +is(Amanda::Config::get_config_dir(), "$CONFIG_DIR/TESTCONF", + "config_dir set"); +is(Amanda::Config::get_config_filename(), + "$CONFIG_DIR/TESTCONF/amanda.conf", + "config_filename set"); + +is(getconf($CNF_RESERVE), 75, + "integer global confparm"); +is(getconf($CNF_BUMPSIZE), $int64_num+0, + "int64 global confparm"); +is(getconf($CNF_TAPEDEV), "/dev/foo", + "string global confparm"); +is(getconf($CNF_DEVICE_OUTPUT_BUFFER_SIZE), $size_t_num+0, + "size global confparm"); +ok(getconf($CNF_AUTOFLUSH), + "boolean global confparm"); +is(getconf($CNF_USETIMESTAMPS), 0, + "boolean global confparm, passing an integer (0)"); +is(getconf($CNF_TAPERALGO), $Amanda::Config::ALGO_LAST, + "taperalgo global confparam"); +is_deeply([getconf($CNF_RESERVED_UDP_PORT)], [100,200], + "intrange global confparm"); +is(getconf($CNF_DISPLAYUNIT), "M", + "displayunit is correctly uppercased"); +is_deeply(getconf($CNF_DEVICE_PROPERTY), + { "foo" => { priority => 0, append => 0, values => ["bar"]}, + "blue" => { priority => 0, append => 0, + values => ["car", "tar"]} }, + "proplist global confparm"); +is_deeply(getconf($CNF_AUTOLABEL), + { template => undef, other_config => '', + non_amanda => 1, volume_error => '', empty => 1 }, + "'autolabel non-amanda empty' represented correctly"); +ok(getconf_seen($CNF_TAPEDEV), + "'tapedev' parm was seen"); +ok(!getconf_seen($CNF_CHANGERFILE), + "'changerfile' parm was not seen"); + +is(Amanda::Config::getconf_unit_divisor(), 1024, + "correct unit divisor (from displayunit -> KB)"); +ok($Amanda::Config::debug_auth, + "debug_auth setting reflected in global variable"); +ok(!$Amanda::Config::debug_amandad, + "debug_amandad defaults to false"); + +my $ttyp = lookup_tapetype("mytapetype"); +ok($ttyp, "found mytapetype"); +is(tapetype_getconf($ttyp, $TAPETYPE_COMMENT), 'mine', + "tapetype comment"); +is(tapetype_getconf($ttyp, $TAPETYPE_LENGTH), 128 * 1024, + "tapetype comment"); + +ok(tapetype_seen($ttyp, $TAPETYPE_COMMENT), + "tapetype comment was seen"); +ok(!tapetype_seen($ttyp, $TAPETYPE_LBL_TEMPL), + "tapetype lbl_templ was not seen"); + +is(tapetype_getconf($ttyp, $TAPETYPE_PART_SIZE), 100*1024, + "tapetype part_size"); +is(tapetype_getconf($ttyp, $TAPETYPE_PART_CACHE_TYPE), $PART_CACHE_TYPE_DISK, + "tapetype part_cache_type"); +is(tapetype_getconf($ttyp, $TAPETYPE_PART_CACHE_DIR), "/usr/bin", + "tapetype part_cache_dir"); +is(tapetype_getconf($ttyp, $TAPETYPE_PART_CACHE_MAX_SIZE), 50*1024, + "tapetype part_cache_max_size"); + +is_deeply([ sort(+getconf_list("tapetype")) ], + [ sort("mytapetype", "TEST-TAPE") ], + "getconf_list lists all tapetypes"); + +my $dtyp = lookup_dumptype("mydump-type"); +ok($dtyp, "found mydump-type"); +is(dumptype_getconf($dtyp, $DUMPTYPE_COMMENT), 'mine', + "dumptype string"); +is(dumptype_getconf($dtyp, $DUMPTYPE_PRIORITY), 2, + "dumptype priority"); +is(dumptype_getconf($dtyp, $DUMPTYPE_BUMPSIZE), $int64_num+0, + "dumptype size"); +is(dumptype_getconf($dtyp, $DUMPTYPE_BUMPMULT), 1.75, + "dumptype real"); +is(dumptype_getconf($dtyp, $DUMPTYPE_STARTTIME), 1829, + "dumptype time"); +is(dumptype_getconf($dtyp, $DUMPTYPE_HOLDINGDISK), $HOLD_REQUIRED, + "dumptype holdingdisk"); +is(dumptype_getconf($dtyp, $DUMPTYPE_COMPRESS), $COMP_BEST, + "dumptype compress"); +is(dumptype_getconf($dtyp, $DUMPTYPE_ENCRYPT), $ENCRYPT_SERV_CUST, + "dumptype encrypt"); +is(dumptype_getconf($dtyp, $DUMPTYPE_STRATEGY), $DS_INCRONLY, + "dumptype strategy"); +is_deeply([dumptype_getconf($dtyp, $DUMPTYPE_COMPRATE)], [0.25, 0.75], + "dumptype comprate"); +is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_INCLUDE), + { 'file' => [ 'rhyme' ], + 'list' => [ 'bing', 'ting', 'string', 'fling' ], + 'optional' => 1 }, + "dumptype include list"); +is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_EXCLUDE), + { 'file' => [ 'foolist' ], + 'list' => [ 'foo', 'bar', 'true', 'star' ], + 'optional' => 0 }, + "dumptype exclude list"); +is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_ESTIMATELIST), + [ $ES_SERVER, $ES_CALCSIZE, $ES_CLIENT ], + "dumptype estimate list"); +is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_PROPERTY), + { "prop" => { priority => 0, append => 0, values => ["erty"]}, + "drop" => { priority => 0, append => 0, + values => ["qwerty", "asdfg"] }}, + "dumptype proplist"); +is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT), + [], + "dumptype recovery limit with no limit specified => empty"); + +ok(dumptype_seen($dtyp, $DUMPTYPE_EXCLUDE), + "'exclude' parm was seen"); +ok(!dumptype_seen($dtyp, $DUMPTYPE_RECORD), + "'record' parm was not seen"); + +is_deeply([ sort(+getconf_list("dumptype")) ], + [ sort(qw( + mydump-type second_dumptype third_dumptype + NO-COMPRESS COMPRESS-FAST COMPRESS-BEST COMPRESS-CUST + SRVCOMPRESS BSD-AUTH BSDTCP-AUTH NO-RECORD NO-HOLD + NO-FULL + )) ], + "getconf_list lists all dumptypes (including defaults)"); +is(dumptype_getconf($dtyp, $DUMPTYPE_ALLOW_SPLIT), 0, + "dumptype allow_split"); + +my $iface = lookup_interface("ethernet"); +ok($iface, "found ethernet"); +is(interface_name($iface), "ethernet", + "interface knows its name"); +is(interface_getconf($iface, $INTER_COMMENT), 'mine', + "interface comment"); +is(interface_getconf($iface, $INTER_MAXUSAGE), 100, + "interface maxusage"); + +$iface = lookup_interface("nic"); +ok($iface, "found nic"); +ok(interface_seen($iface, $INTER_COMMENT), + "seen set for parameters that appeared"); +ok(!interface_seen($iface, $INTER_MAXUSAGE), + "seen not set for parameters that did not appear"); + +is_deeply([ sort(+getconf_list("interface")) ], + [ sort('ethernet', 'nic', 'default') ], + "getconf_list lists all interfaces (in any order)"); + +skip "error loading config", 13 unless $cfg_result == $CFGERR_OK; +my $hdisk = lookup_holdingdisk("hd1"); +ok($hdisk, "found hd1"); +is(holdingdisk_name($hdisk), "hd1", + "hd1 knows its name"); +is(holdingdisk_getconf($hdisk, $HOLDING_COMMENT), 'mine', + "holdingdisk comment"); +is(holdingdisk_getconf($hdisk, $HOLDING_DISKDIR), '/mnt/hd1', + "holdingdisk diskdir (directory)"); +is(holdingdisk_getconf($hdisk, $HOLDING_DISKSIZE), 100*1024, + "holdingdisk disksize (use)"); +is(holdingdisk_getconf($hdisk, $HOLDING_CHUNKSIZE), 1024, + "holdingdisk chunksize"); + +$hdisk = lookup_holdingdisk("hd2"); +ok($hdisk, "found hd2"); +ok(holdingdisk_seen($hdisk, $HOLDING_COMMENT), + "seen set for parameters that appeared"); +ok(!holdingdisk_seen($hdisk, $HOLDING_CHUNKSIZE), + "seen not set for parameters that did not appear"); + +# only holdingdisks have this linked-list structure +# exposed +my $hdisklist = getconf($CNF_HOLDINGDISK); +my $first_disk = @$hdisklist[0]; +$hdisk = lookup_holdingdisk($first_disk); +like(holdingdisk_name($hdisk), qr/hd[12]/, + "one disk is first in list of holdingdisks"); +$hdisk = lookup_holdingdisk(@$hdisklist[1]); +like(holdingdisk_name($hdisk), qr/hd[12]/, + "another is second in list of holdingdisks"); +ok($#$hdisklist == 1, + "no third holding disk"); + +is_deeply([ sort(+getconf_list("holdingdisk")) ], + [ sort('hd1', 'hd2') ], + "getconf_list lists all holdingdisks (in any order)"); + +skip "error loading config", 5 unless $cfg_result == $CFGERR_OK; +my $app = lookup_application("my_app"); +ok($app, "found my_app"); +is(application_name($app), "my_app", + "my_app knows its name"); +is(application_getconf($app, $APPLICATION_COMMENT), 'my_app_comment', + "application comment"); +is(application_getconf($app, $APPLICATION_PLUGIN), 'amgtar', + "application plugin (amgtar)"); + +is_deeply([ sort(+getconf_list("application-tool")) ], + [ sort("my_app") ], + "getconf_list lists all applications"); +# test backward compatibility +is_deeply([ sort(+getconf_list("application")) ], + [ sort("my_app") ], + "getconf_list works for 'application-tool', too"); + +my $sc = lookup_pp_script("my_script"); +ok($sc, "found my_script"); +is(pp_script_name($sc), "my_script", + "my_script knows its name"); +is(pp_script_getconf($sc, $PP_SCRIPT_COMMENT), 'my_script_comment', + "script comment"); +is(pp_script_getconf($sc, $PP_SCRIPT_PLUGIN), 'script-email', + "script plugin (script-email)"); +is(pp_script_getconf($sc, $PP_SCRIPT_EXECUTE_WHERE), $ES_CLIENT, + "script execute_where (client)"); +is(pp_script_getconf($sc, $PP_SCRIPT_EXECUTE_ON), + $EXECUTE_ON_PRE_HOST_BACKUP|$EXECUTE_ON_POST_HOST_BACKUP, + "script execute_on"); + +is_deeply([ sort(+getconf_list("script")) ], + [ sort("my_script") ], + "getconf_list lists all script"); + +is_deeply([ sort(+getconf_list("script-tool")) ], + [ sort("my_script") ], + "getconf_list works for 'script-tool', too"); + +my $dc = lookup_device_config("my_device"); +ok($dc, "found my_device"); +is(device_config_name($dc), "my_device", + "my_device knows its name"); +is(device_config_getconf($dc, $DEVICE_CONFIG_COMMENT), 'my device is mine, not yours', + "device comment"); +is(device_config_getconf($dc, $DEVICE_CONFIG_TAPEDEV), 'tape:/dev/nst0', + "device tapedev"); +# TODO do we really need all of this equipment for device properties? +is_deeply(device_config_getconf($dc, $DEVICE_CONFIG_DEVICE_PROPERTY), + { "block-size" => { 'priority' => 0, 'values' => ["128k"], 'append' => 0 }, + "comment" => { 'priority' => 0, 'values' => ["what up?"], 'append' => 0 }, }, + "device config proplist"); + +is_deeply([ sort(+getconf_list("device")) ], + [ sort("my_device") ], + "getconf_list lists all devices"); + +skip "error loading config", 7 unless $cfg_result == $CFGERR_OK; +$dc = lookup_changer_config("my_changer"); +ok($dc, "found my_changer"); +is(changer_config_name($dc), "my_changer", + "my_changer knows its name"); +is(changer_config_getconf($dc, $CHANGER_CONFIG_COMMENT), 'my changer is mine, not yours', + "changer comment"); +is(changer_config_getconf($dc, $CHANGER_CONFIG_CHANGERDEV), '/dev/sg0', + "changer tapedev"); +is_deeply(changer_config_getconf($dc, $CHANGER_CONFIG_PROPERTY), + { 'testprop' => { + 'priority' => 0, + 'values' => [ 'testval' ], + 'append' => 0, + } + }, "changer properties represented correctly"); + +is_deeply(changer_config_getconf($dc, $CHANGER_CONFIG_DEVICE_PROPERTY), + { 'testdprop' => { + 'priority' => 0, + 'values' => [ 'testdval' ], + 'append' => 0, + } + }, "changer device properties represented correctly"); + +is_deeply([ sort(+getconf_list("changer")) ], + [ sort("my_changer") ], + "getconf_list lists all changers"); + +$dc = lookup_interactivity("my_interactivity"); +ok($dc, "found my_interactivity"); +is(interactivity_name($dc), "my_interactivity", + "my_interactivity knows its name"); +is(interactivity_getconf($dc, $INTERACTIVITY_COMMENT), 'my interactivity is mine, not yours', + "interactivity comment"); +is(interactivity_getconf($dc, $INTERACTIVITY_PLUGIN), 'MY-interactivity', + "interactivity plugin"); +is_deeply(interactivity_getconf($dc, $INTERACTIVITY_PROPERTY), + { 'testprop' => { + 'priority' => 0, + 'values' => [ 'testval' ], + 'append' => 0, + } + }, "interactivity properties represented correctly"); + +is_deeply([ sort(+getconf_list("interactivity")) ], + [ sort("my_interactivity") ], + "getconf_list lists all interactivity"); + +$dc = lookup_taperscan("my_taperscan"); +ok($dc, "found my_taperscan"); +is(taperscan_name($dc), "my_taperscan", + "my_taperscan knows its name"); +is(taperscan_getconf($dc, $TAPERSCAN_COMMENT), 'my taperscan is mine, not yours', + "taperscan comment"); +is(taperscan_getconf($dc, $TAPERSCAN_PLUGIN), 'MY-taperscan', + "taperscan plugin"); +is_deeply(taperscan_getconf($dc, $TAPERSCAN_PROPERTY), + { 'testprop' => { + 'priority' => 0, + 'values' => [ 'testval' ], + 'append' => 0, + } + }, "taperscan properties represented correctly"); + +is_deeply([ sort(+getconf_list("taperscan")) ], + [ sort("my_taperscan") ], + "getconf_list lists all taperscan"); - is(Amanda::Config::getconf_unit_divisor(), 1024, - "correct unit divisor (from displayunit -> KB)"); - ok($Amanda::Config::debug_auth, - "debug_auth setting reflected in global variable"); - ok(!$Amanda::Config::debug_amandad, - "debug_amandad defaults to false"); -} - -SKIP: { # tapetypes - skip "error loading config", 6 unless $cfg_result == $CFGERR_OK; - my $ttyp = lookup_tapetype("mytapetype"); - ok($ttyp, "found mytapetype"); - is(tapetype_getconf($ttyp, $TAPETYPE_COMMENT), 'mine', - "tapetype comment"); - is(tapetype_getconf($ttyp, $TAPETYPE_LENGTH), 128 * 1024, - "tapetype comment"); - - ok(tapetype_seen($ttyp, $TAPETYPE_COMMENT), - "tapetype comment was seen"); - ok(!tapetype_seen($ttyp, $TAPETYPE_LBL_TEMPL), - "tapetype lbl_templ was not seen"); - - is_deeply([ sort(+getconf_list("tapetype")) ], - [ sort("mytapetype", "TEST-TAPE") ], - "getconf_list lists all tapetypes"); -} - -SKIP: { # dumptypes - skip "error loading config", 18 unless $cfg_result == $CFGERR_OK; - - my $dtyp = lookup_dumptype("mydump-type"); - ok($dtyp, "found mydump-type"); - is(dumptype_getconf($dtyp, $DUMPTYPE_COMMENT), 'mine', - "dumptype string"); - is(dumptype_getconf($dtyp, $DUMPTYPE_PRIORITY), 2, - "dumptype priority"); - is(dumptype_getconf($dtyp, $DUMPTYPE_BUMPSIZE), $int64_num+0, - "dumptype size"); - is(dumptype_getconf($dtyp, $DUMPTYPE_BUMPMULT), 1.75, - "dumptype real"); - is(dumptype_getconf($dtyp, $DUMPTYPE_STARTTIME), 1829, - "dumptype time"); - is(dumptype_getconf($dtyp, $DUMPTYPE_HOLDINGDISK), $HOLD_REQUIRED, - "dumptype holdingdisk"); - is(dumptype_getconf($dtyp, $DUMPTYPE_COMPRESS), $COMP_BEST, - "dumptype compress"); - is(dumptype_getconf($dtyp, $DUMPTYPE_ENCRYPT), $ENCRYPT_SERV_CUST, - "dumptype encrypt"); - is(dumptype_getconf($dtyp, $DUMPTYPE_STRATEGY), $DS_INCRONLY, - "dumptype strategy"); - is_deeply([dumptype_getconf($dtyp, $DUMPTYPE_COMPRATE)], [0.25, 0.75], - "dumptype comprate"); - is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_INCLUDE), - { 'file' => [ 'rhyme' ], - 'list' => [ 'bing', 'ting', 'string', 'fling' ], - 'optional' => 1 }, - "dumptype include list"); - is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_EXCLUDE), - { 'file' => [ 'foolist' ], - 'list' => [ 'foo', 'bar', 'true', 'star' ], - 'optional' => 0 }, - "dumptype exclude list"); - is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_ESTIMATELIST), - [ $ES_SERVER, $ES_CALCSIZE, $ES_CLIENT ], - "dumptype estimate list"); - is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_PROPERTY), - { "prop" => { priority => 0, append => 0, values => ["erty"]}, - "drop" => { priority => 0, append => 0, - values => ["qwerty", "asdfg"] }}, - "dumptype proplist"); - - ok(dumptype_seen($dtyp, $DUMPTYPE_EXCLUDE), - "'exclude' parm was seen"); - ok(!dumptype_seen($dtyp, $DUMPTYPE_RECORD), - "'record' parm was not seen"); - - is_deeply([ sort(+getconf_list("dumptype")) ], - [ sort(qw( - mydump-type second_dumptype third_dumptype - NO-COMPRESS COMPRESS-FAST COMPRESS-BEST COMPRESS-CUST - SRVCOMPRESS BSD-AUTH NO-RECORD NO-HOLD - NO-FULL - )) ], - "getconf_list lists all dumptypes (including defaults)"); -} - -SKIP: { # interfaces - skip "error loading config", 8 unless $cfg_result == $CFGERR_OK; - my $iface = lookup_interface("ethernet"); - ok($iface, "found ethernet"); - is(interface_name($iface), "ethernet", - "interface knows its name"); - is(interface_getconf($iface, $INTER_COMMENT), 'mine', - "interface comment"); - is(interface_getconf($iface, $INTER_MAXUSAGE), 100, - "interface maxusage"); - - $iface = lookup_interface("nic"); - ok($iface, "found nic"); - ok(interface_seen($iface, $INTER_COMMENT), - "seen set for parameters that appeared"); - ok(!interface_seen($iface, $INTER_MAXUSAGE), - "seen not set for parameters that did not appear"); - - is_deeply([ sort(+getconf_list("interface")) ], - [ sort('ethernet', 'nic', 'default') ], - "getconf_list lists all interfaces (in any order)"); -} - -SKIP: { # holdingdisks - skip "error loading config", 13 unless $cfg_result == $CFGERR_OK; - my $hdisk = lookup_holdingdisk("hd1"); - ok($hdisk, "found hd1"); - is(holdingdisk_name($hdisk), "hd1", - "hd1 knows its name"); - is(holdingdisk_getconf($hdisk, $HOLDING_COMMENT), 'mine', - "holdingdisk comment"); - is(holdingdisk_getconf($hdisk, $HOLDING_DISKDIR), '/mnt/hd1', - "holdingdisk diskdir (directory)"); - is(holdingdisk_getconf($hdisk, $HOLDING_DISKSIZE), 100*1024, - "holdingdisk disksize (use)"); - is(holdingdisk_getconf($hdisk, $HOLDING_CHUNKSIZE), 1024, - "holdingdisk chunksize"); - - $hdisk = lookup_holdingdisk("hd2"); - ok($hdisk, "found hd2"); - ok(holdingdisk_seen($hdisk, $HOLDING_COMMENT), - "seen set for parameters that appeared"); - ok(!holdingdisk_seen($hdisk, $HOLDING_CHUNKSIZE), - "seen not set for parameters that did not appear"); - - # only holdingdisks have this linked-list structure - # exposed - my $hdisklist = getconf($CNF_HOLDINGDISK); - my $first_disk = @$hdisklist[0]; - $hdisk = lookup_holdingdisk($first_disk); - like(holdingdisk_name($hdisk), qr/hd[12]/, - "one disk is first in list of holdingdisks"); - $hdisk = lookup_holdingdisk(@$hdisklist[1]); - like(holdingdisk_name($hdisk), qr/hd[12]/, - "another is second in list of holdingdisks"); - ok($#$hdisklist == 1, - "no third holding disk"); - - is_deeply([ sort(+getconf_list("holdingdisk")) ], - [ sort('hd1', 'hd2') ], - "getconf_list lists all holdingdisks (in any order)"); -} - -SKIP: { # application - skip "error loading config", 5 unless $cfg_result == $CFGERR_OK; - my $app = lookup_application("my_app"); - ok($app, "found my_app"); - is(application_name($app), "my_app", - "my_app knows its name"); - is(application_getconf($app, $APPLICATION_COMMENT), 'my_app_comment', - "application comment"); - is(application_getconf($app, $APPLICATION_PLUGIN), 'amgtar', - "application plugin (amgtar)"); - - is_deeply([ sort(+getconf_list("application-tool")) ], - [ sort("my_app") ], - "getconf_list lists all applications"); - # test backward compatibility - is_deeply([ sort(+getconf_list("application")) ], - [ sort("my_app") ], - "getconf_list works for 'application-tool', too"); -} - -SKIP: { # script - skip "error loading config", 7 unless $cfg_result == $CFGERR_OK; - my $sc = lookup_pp_script("my_script"); - ok($sc, "found my_script"); - is(pp_script_name($sc), "my_script", - "my_script knows its name"); - is(pp_script_getconf($sc, $PP_SCRIPT_COMMENT), 'my_script_comment', - "script comment"); - is(pp_script_getconf($sc, $PP_SCRIPT_PLUGIN), 'script-email', - "script plugin (script-email)"); - is(pp_script_getconf($sc, $PP_SCRIPT_EXECUTE_WHERE), $ES_CLIENT, - "script execute_where (client)"); - is(pp_script_getconf($sc, $PP_SCRIPT_EXECUTE_ON), - $EXECUTE_ON_PRE_HOST_BACKUP|$EXECUTE_ON_POST_HOST_BACKUP, - "script execute_on"); - - is_deeply([ sort(+getconf_list("script")) ], - [ sort("my_script") ], - "getconf_list lists all script"); - - is_deeply([ sort(+getconf_list("script-tool")) ], - [ sort("my_script") ], - "getconf_list works for 'script-tool', too"); -} - -SKIP: { # device - skip "error loading config", 6 unless $cfg_result == $CFGERR_OK; - my $dc = lookup_device_config("my_device"); - ok($dc, "found my_device"); - is(device_config_name($dc), "my_device", - "my_device knows its name"); - is(device_config_getconf($dc, $DEVICE_CONFIG_COMMENT), 'my device is mine, not yours', - "device comment"); - is(device_config_getconf($dc, $DEVICE_CONFIG_TAPEDEV), 'tape:/dev/nst0', - "device tapedev"); - # TODO do we really need all of this equipment for device properties? - is_deeply(device_config_getconf($dc, $DEVICE_CONFIG_DEVICE_PROPERTY), - { "block_size" => { 'priority' => 0, 'values' => ["128k"], 'append' => 0 }, }, - "device config proplist"); - - is_deeply([ sort(+getconf_list("device")) ], - [ sort("my_device") ], - "getconf_list lists all devices"); -} - -SKIP: { # changer - skip "error loading config", 7 unless $cfg_result == $CFGERR_OK; - my $dc = lookup_changer_config("my_changer"); - ok($dc, "found my_changer"); - is(changer_config_name($dc), "my_changer", - "my_changer knows its name"); - is(changer_config_getconf($dc, $CHANGER_CONFIG_COMMENT), 'my changer is mine, not yours', - "changer comment"); - is(changer_config_getconf($dc, $CHANGER_CONFIG_CHANGERDEV), '/dev/sg0', - "changer tapedev"); - is_deeply(changer_config_getconf($dc, $CHANGER_CONFIG_PROPERTY), - { 'testprop' => { - 'priority' => 0, - 'values' => [ 'testval' ], - 'append' => 0, - } - }, "changer properties represented correctly"); - - is_deeply(changer_config_getconf($dc, $CHANGER_CONFIG_DEVICE_PROPERTY), - { 'testdprop' => { - 'priority' => 0, - 'values' => [ 'testdval' ], - 'append' => 0, - } - }, "changer device properties represented correctly"); - - is_deeply([ sort(+getconf_list("changer")) ], - [ sort("my_changer") ], - "getconf_list lists all changers"); -} ## # Test config overwrites (using the config from above) @@ -552,7 +603,7 @@ is($error_level, $CFGERR_ERRORS, "bogus config overwrite flagged as an error"); my $pid = open(my $kid, "-|"); die "Can't fork: $!" unless defined($pid); if (!$pid) { - Amanda::Config::dump_configuration(); + Amanda::Config::dump_configuration(1, 0); exit 1; } my $dump_first_line = <$kid>; @@ -568,14 +619,14 @@ $dump_filename =~ s/":$//g; is($dump_filename, $fn, "config filename is included correctly"); -like($dump, qr/DEVICE_PROPERTY\s+"foo" "bar"\n/i, - "DEVICE_PROPERTY appears in dump output"); +like($dump, qr/DEVICE-PROPERTY\s+"foo" "bar"\n/i, + "DEVICE-PROPERTY appears in dump output"); -like($dump, qr/AMRECOVER_CHECK_LABEL\s+(yes|no)/i, - "AMRECOVER_CHECK_LABEL has a trailing space"); +like($dump, qr/AMRECOVER-CHECK-LABEL\s+(yes|no)/i, + "AMRECOVER-CHECK-LABEL has a trailing space"); -like($dump, qr/AMRECOVER_CHECK_LABEL\s+(yes|no)/i, - "AMRECOVER_CHECK_LABEL has a trailing space"); +like($dump, qr/AMRECOVER-CHECK-LABEL\s+(yes|no)/i, + "AMRECOVER-CHECK-LABEL has a trailing space"); like($dump, qr/EXCLUDE\s+LIST "foo" "bar" "true" "star"/i, "EXCLUDE LIST is in the dump"); @@ -585,6 +636,8 @@ like($dump, qr/INCLUDE\s+LIST OPTIONAL "bing" "ting" "string" "fling"/i, "INCLUDE LIST is in the dump"); like($dump, qr/INCLUDE\s+FILE OPTIONAL "rhyme"/i, "INCLUDE FILE is in the dump"); +like($dump, qr/RECOVERY-LIMIT.*SAME-HOST/i, + "RECOVERY-LIST is in the dump"); ## # Test nested definitions inside a dumptype @@ -661,6 +714,105 @@ SKIP: { "'optional' has no effect when not on the last occurrence"); } +## +# Check out recovery-limit parsing + +$testconf = Installcheck::Config->new(); +$testconf->add_param('recovery-limit', '"foo" "bar"'); +$testconf->add_dumptype('rl1', [ + 'recovery-limit' => 'same-host server', +]); +$testconf->add_dumptype('rl2', [ + 'recovery-limit' => '"somehost"', +]); +$testconf->add_dumptype('rl3', [ + 'recovery-limit' => 'same-host server "somehost"', +]); +$testconf->add_dumptype('rl4', [ + 'recovery-limit' => '"foohost" same-host', +]); +$testconf->write(); + +$cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF"); +is($cfg_result, $CFGERR_OK, + "recovery-limit config loaded") + or diag_config_errors(); +SKIP: { + skip "error loading config", 5 unless $cfg_result == $CFGERR_OK; + my $dtyp; + + is_deeply(getconf($CNF_RECOVERY_LIMIT), + [ 'foo', 'bar' ], + "global recovery-limit parameter"); + + $dtyp = lookup_dumptype("rl1"); + is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT), + [ "SAMEHOST-SAMEHOST-SAMEHOST", "SERVER-SERVER-SERVER" ], + "same-host => undef in list"); + + $dtyp = lookup_dumptype("rl2"); + is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT), + [ "somehost" ], + "hostname => match pattern"); + + $dtyp = lookup_dumptype("rl3"); + is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT), + [ "SAMEHOST-SAMEHOST-SAMEHOST", "SERVER-SERVER-SERVER", "somehost" ], + "hostname and same-host parsed correctly"); + + $dtyp = lookup_dumptype("rl4"); + is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_RECOVERY_LIMIT), + [ "SAMEHOST-SAMEHOST-SAMEHOST", "foohost" ], # note that the order is an implementation detail + ".. even if same-host comes last"); +} + +## +# Check out dump-limit parsing + +$testconf = Installcheck::Config->new(); +$testconf->add_dumptype('dl1', [ + 'dump-limit' => 'same-host', +]); +$testconf->add_dumptype('dl2', [ + 'dump-limit' => 'server', +]); +$testconf->add_dumptype('dl3', [ + 'dump-limit' => 'same-host server', +]); +$testconf->write(); + +$cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF"); +is($cfg_result, $CFGERR_OK, + "dump-limit config loaded") + or diag_config_errors(); +SKIP: { + skip "error loading config", 5 unless $cfg_result == $CFGERR_OK; + my $dtyp; + + $dtyp = lookup_dumptype("dl1"); + is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_DUMP_LIMIT), + [ "SAMEHOST-SAMEHOST-SAMEHOST" ], + "same-host => \"SAMEHOST-SAMEHOST-SAMEHOST\" in list"); + + $dtyp = lookup_dumptype("dl2"); + is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_DUMP_LIMIT), + [ "SERVER-SERVER-SERVER" ], + "server => \"SERVER-SERVER-SERVER\" in list"); + + $dtyp = lookup_dumptype("dl3"); + is_deeply(dumptype_getconf($dtyp, $DUMPTYPE_DUMP_LIMIT), + [ "SAMEHOST-SAMEHOST-SAMEHOST", "SERVER-SERVER-SERVER" ], + "same-host and server"); +} + +$testconf->add_dumptype('dl4', [ + 'dump-limit' => 'same-host server "somehost"', +]); +$testconf->write(); +$cfg_result = config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF"); +isnt($cfg_result, $CFGERR_OK, + "dump-limit do not accept hostname"); + ## # Try an autolabel with a template and 'any' @@ -949,3 +1101,53 @@ for my $bv (@boolean_vals) { is(string_to_boolean($bv->{'val'}), $bv->{'expected'}, "string_to_boolean('$bv->{'val'}') is right"); } + +my @prop_names = ( + {'val' => '', 'expected' => ''}, + {'val' => 'prop-name', 'expected' => 'prop-name'}, + {'val' => 'PRoP-NaME', 'expected' => 'prop-name'}, + {'val' => 'prop_name', 'expected' => 'prop-name'}, + {'val' => 'FaNCy_ProP', 'expected' => 'fancy-prop'}, + {'val' => '_under_', 'expected' => '-under-'}, + {'val' => '-dash-', 'expected' => '-dash-'}, + {'val' => '-', 'expected' => '-'}, + {'val' => '_', 'expected' => '-'}, + ); + +for my $pn (@prop_names) { + is(amandaify_property_name($pn->{'val'}), $pn->{'expected'}, + "amandaify_property_name('$pn->{'val'}') is right"); +} + +$testconf = Installcheck::Config->new(); +$testconf->add_param('property', '"PrOP_nAme" "VALUE"'); +$testconf->write(); +config_init($CONFIG_INIT_EXPLICIT_NAME, "TESTCONF"); +my $properties = getconf($CNF_PROPERTY); + +@prop_names = ( + {'val' => 'prop-name'}, + {'val' => 'PRoP-NaME'}, + {'val' => 'prop_name'}, + {'val' => 'PROP_NAME'}, + {'val' => 'PRoP-NaME'}, + {'val' => 'prop_name'}, + ); + +for my $pn (@prop_names) { + is_deeply($properties->{$pn->{'val'}}->{values}, [ "VALUE" ], "property $pn->{'val'}"); +} + +$testconf = Installcheck::Config->new(); +$testconf->add_client_config_param('amdump-server', '"amdump.localhost"'); +$testconf->add_client_config_param('index-server', '"index.localhost"'); +$testconf->add_client_config_param('tape-server', '"tape.localhost"'); +$testconf->write(); +config_init($CONFIG_INIT_CLIENT | $CONFIG_INIT_EXPLICIT_NAME, "TESTCONF"); +my $amdump_server = getconf($CNF_AMDUMP_SERVER); +is ($amdump_server, "amdump.localhost", "amdump-server is \"amdump.localhost\""); +my $index_server = getconf($CNF_INDEX_SERVER); +is ($index_server, "index.localhost", "index-server is \"index.localhost\""); +my $tape_server = getconf($CNF_TAPE_SERVER); +is ($tape_server, "tape.localhost", "amdump is \"tape.localhost\""); +