c2b78fd4ea9702a1acaf40cba024737ec7e82f40
[debian/amanda] / installcheck / Amconfig.pm.in
1 # vim:ft=perl
2 # Copyright (c) 2006 Zmanda Inc.  All Rights Reserved.
3 #
4 # This program is free software; you can redistribute it and/or modify it
5 # under the terms of the GNU General Public License version 2 as published
6 # by the Free Software Foundation.
7 #
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11 # for more details.
12 #
13 # You should have received a copy of the GNU General Public License along
14 # with this program; if not, write to the Free Software Foundation, Inc.,
15 # 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 #
17 # Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120
18 # Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
19
20 package Amconfig;
21 use File::Path;
22 use Carp;
23
24 =head1 NAME
25
26 Amconfig - set up amanda configurations for installcheck testing
27
28 =head1 SYNOPSIS
29
30   use Amconfig;
31
32   my $testconf = Amconfig->new();
33   $testconf->add_param("runtapes", "5");
34   $testconf->add_subsec("tapetype", "DUCKTAPE", { length => "10G", filemark => "4096k" });
35   # ...
36   $testconf->write();
37
38 The resulting configuration is always named "TESTCONF".  The basic
39 configuration contains only a few parameters that are necessary just
40 to run Amanda applications in the test environment.  It also contains
41 a tapetype, C<TEST-TAPE>.
42
43 Note that it's quite possible to produce an invalid configuration with this
44 package (and, in fact, some of the tests do just that).
45
46 =head2 VTAPES
47
48 This module can set up a vtape configuration, replete with the proper
49 vtape directories, using C<setup_vtape>.  The vtapes are created under
50 the "TESTCONF" configuration directory, for ease of later deletion.  Do
51 not store anything large in these vtapes!
52
53 =head1 WARNING
54
55 Using this module I<will> destroy any existing configuration named
56 TESTDIR.  I<Please> do not use this on a production machine!
57
58 =head1 FUNCTIONS
59
60 =over
61
62 =item C<new()>
63
64 Create a new configuration object
65
66 =cut
67
68 sub new {
69     my $class = shift;
70
71     # An instance is a blessed hash containing parameters.  Start with
72     # some defaults to make sure things run.
73     my $infofile = '@CONFIG_DIR@/TESTCONF/curinfo';
74     my $logdir = '@CONFIG_DIR@/TESTCONF/log';
75     my $indexdir = '@CONFIG_DIR@/TESTCONF/index';
76
77     my $self = {
78         'infofile' => $infofile,
79         'logdir' => $logdir,
80         'indexdir' => $indexdir,
81
82         'vtapes' => [],
83
84         # Global params are stored as an arrayref, so that the same declaration
85         # can appear multiple times
86         'params' => [
87             'mailto' => '"nobody@invalidomain"',
88             'dumpuser' => '"' . (getpwuid($<))[0] . '"', # current username
89
90             # These dirs are under CONFIG_DIR just for ease of destruction.
91             # This is not a recommended layout!
92             'infofile' => "\"$infofile\"",
93             'logdir' => "\"$logdir\"",
94             'indexdir' => "\"$indexdir\"",
95
96             'tapetype' => '"TEST-TAPE"',
97         ],
98
99         # Subsections are stored as a hashref of arrayrefs, keyed by
100         # subsection name
101
102         'tapetypes' => {
103             'TEST-TAPE' => [
104                 'length' => '50 mbytes',
105                 'filemark' => '4 kbytes'
106             ],
107         },
108
109         'dumptypes' => { },
110
111         'interfaces' => { },
112
113         'holdingdisks' => { },
114
115         'dles' => [ ],
116     };
117     bless($self, $class);
118     return $self;
119 }
120
121 =item C<add_param($param, $value)>
122
123 Add the given parameter to the configuration file, overriding any
124 previous value.  Note that strings which should be quoted in the configuration
125 file itself must be double-quoted here, e.g.,
126
127   $testconf->add_param('org' => '"MyOrganization"');
128
129 =cut
130
131 sub add_param {
132     my $self = shift;
133     my ($param, $value) = @_;
134
135     push @{$self->{'params'}}, $param, $value;
136 }
137
138 =item C<add_tapetype($name, $values_hashref)>
139 =item C<add_dumptype($name, $values_hashref)>
140 =item C<addholdingdisk($name, $values_hashref)>
141 =item C<add_interface($name, $values_arrayref)>
142
143 Add the given subsection to the configuration file, including all
144 values in the arrayref.  The values should be specified as alternating
145 key/value pairs.
146
147 =cut
148
149 sub add_tapetype {
150     my $self = shift;
151     my ($name, $values_arrayref) = @_;
152     $self->{'tapetypes'}{$name} = $values_arrayref;
153 }
154
155 sub add_dumptype {
156     my $self = shift;
157     my ($name, $values_arrayref) = @_;
158     $self->{'dumptypes'}{$name} = $values_arrayref;
159 }
160
161 sub add_holdingdisk {
162     my $self = shift;
163     my ($name, $values_arrayref) = @_;
164     $self->{'holdingdisks'}{$name} = $values_arrayref;
165 }
166
167 sub add_interface {
168     my $self = shift;
169     my ($name, $values_arrayref) = @_;
170     $self->{'interfaces'}{$name} = $values_arrayref;
171 }
172
173 =item C<add_dle($line)>
174
175 Add a disklist entry; C<$line> is inserted verbatim into the disklist.
176
177 =cut
178
179 sub add_dle {
180     my $self = shift;
181     my ($line) = @_;
182     push @{$self->{'dles'}}, $line;
183 }
184
185 =item C<setup_vtape()>
186
187 Set up to use a single vtape (no changer).  This creates the proper
188 directory hierarchy and sets C<tapedev> to the relevant path.
189
190 =cut
191
192 sub setup_vtape {
193     my $self = shift;
194     my $tapepath = "@CONFIG_DIR@/TESTCONF/vtapes/tape1";
195     push @{$self->{'vtapes'}}, $tapepath;
196     
197     $self->add_param("tapedev", "\"file:$tapepath\"");
198 }
199
200 =item C<write()>
201
202 Write out the accumulated configuration file, along with any other
203 files necessary to run Amanda.
204
205 =cut
206
207 sub write {
208     my $self = shift;
209
210     my $testconf_dir = '@CONFIG_DIR@/TESTCONF';
211     if (-e $testconf_dir) {
212         rmtree($testconf_dir) or die("Could not remove '$testconf_dir'");
213     }
214     mkpath($testconf_dir);
215
216     # set up curinfo dir, etc.
217     mkpath($self->{'infofile'}) or die("Could not create infofile directory");
218     mkpath($self->{'logdir'}) or die("Could not create logdir directory");
219     mkpath($self->{'indexdir'}) or die("Could not create indexdir directory");
220
221     # create any vtapes
222     for my $vtape (@{$self->{'vtapes'}}) {
223         mkpath("$vtape/data") or die("Could not create vtape directory '$vtape/data'");
224     }
225
226     $self->_write_tapelist("$testconf_dir/tapelist");
227     $self->_write_disklist("$testconf_dir/disklist");
228     $self->_write_amanda_conf("$testconf_dir/amanda.conf");
229 }
230
231 sub _write_tapelist {
232     my $self = shift;
233     my ($filename) = @_;
234
235     # create an empty tapelist
236     open(my $tapelist, ">", $filename);
237     close($tapelist);
238 }
239
240 sub _write_disklist {
241     my $self = shift;
242     my ($filename) = @_;
243
244     # don't bother writing a disklist if there are no dle's
245     return unless $self->{'dles'};
246
247     open(my $disklist, ">", $filename);
248
249     for my $dle_line (@{$self->{'dles'}}) {
250         print $disklist "$dle_line\n";
251     }
252
253     close($disklist);
254 }
255
256 sub _write_amanda_conf {
257     my $self = shift;
258     my ($filename) = @_;
259
260     open my $amanda_conf, ">", $filename
261         or croak("Could not open '$filename'");
262
263     # write key/value pairs
264     my @params = @{$self->{'params'}};
265     while (@params) {
266         $param = shift @params;
267         $value = shift @params;
268         print $amanda_conf "$param $value\n";
269     }
270
271     # write out subsections
272     $self->_write_amanda_conf_subsection($amanda_conf, "tapetype", $self->{"tapetypes"});
273     $self->_write_amanda_conf_subsection($amanda_conf, "dumptype", $self->{"dumptypes"});
274     $self->_write_amanda_conf_subsection($amanda_conf, "interface", $self->{"interfaces"});
275     $self->_write_amanda_conf_subsection($amanda_conf, "holdingdisk", $self->{"holdingdisks"});
276
277     close($amanda_conf);
278 }
279
280 sub _write_amanda_conf_subsection {
281     my $self = shift;
282     my ($amanda_conf, $subsec_type, $subsec_ref) = @_;
283
284     for my $subsec_name (keys %$subsec_ref) {
285         my @values = @{$subsec_ref->{$subsec_name}};
286         
287         if ($subsec_type eq "holdingdisk") {
288             print $amanda_conf "\nholdingdisk $subsec_name {\n";
289         } else {
290             print $amanda_conf "\ndefine $subsec_type $subsec_name {\n";
291         }
292
293         while (@values) {
294             $param = shift @values;
295             $value = shift @values;
296             print $amanda_conf "$param $value\n";
297         }
298         print $amanda_conf "}\n";
299     }
300 }
301
302 1;