2 * Copyright (c) 2008-2012 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
22 %module "Amanda::Disklist"
23 %include "amglue/amglue.swg"
24 %include "exception.i"
25 %import "Amanda/Config.swg"
27 %include "Amanda/Disklist.pod"
36 use Amanda::Debug qw( :logging );
37 use Amanda::Config qw( :getconf config_dir_relative );
40 /* handle creation of opaque objects from Amanda::Config */
41 %types(interface_t *, dumptype_t *);
44 /* Utility functions for read_disklist_internal */
45 #define hv_store_const(h, k, v) hv_store((h), (k), sizeof((k))-1, (v), 0)
46 #define safe_newSVpv(str) ((str)? newSVpv((str), 0) : &PL_sv_undef)
54 char *name = interface_name(iface->config);
55 HV *ifaceclass_stash = NULL;
58 svp = hv_fetch(ifaces, name, strlen(name), TRUE);
60 croak("internal error"); /* shouldn't happen with lval = TRUE */
63 /* no existing iface, so set up a new one */
67 /* make a new hashref and bless it */
69 ref = newRV_noinc((SV *)h);
70 if (!ifaceclass_stash) {
71 ifaceclass_stash = gv_stashpv(ifaceclass, GV_ADD);
73 sv_bless(ref, ifaceclass_stash);
76 /* fill in the relevant value - a reference to the config */
77 hv_store_const(h, "config",
79 SWIG_NewPointerObj(iface->config,
80 /* can't use $descriptor here.. */
81 SWIGTYPE_p_interface_t, 0)));
95 HV *hostclass_stash = NULL;
100 svp = hv_fetch(hosts, dp->hostname, strlen(dp->hostname), TRUE);
102 croak("internal error"); /* shouldn't happen with lval = TRUE */
105 /* this host already exists */
107 /* no existing host, so set up a new one */
111 /* make a new hashref and bless it */
113 ref = newRV_noinc((SV *)h);
114 g_assert(SvREFCNT((SV *)h) == 1);
115 if (!hostclass_stash) {
116 hostclass_stash = gv_stashpv(hostclass, GV_ADD);
118 sv_bless(ref, hostclass_stash);
120 g_assert(SvREFCNT(*svp) == 1);
122 /* fill in the relevant values */
123 hv_store_const(h, "hostname", safe_newSVpv(dp->hostname));
124 hv_store_const(h, "amandad_path", safe_newSVpv(dp->amandad_path));
125 hv_store_const(h, "client_username", safe_newSVpv(dp->client_username));
126 hv_store_const(h, "ssh_keys", safe_newSVpv(dp->ssh_keys));
127 hv_store_const(h, "auth", safe_newSVpv(dp->auth));
128 hv_store_const(h, "maxdumps", newSViv(dp->host->maxdumps));
129 hv_store_const(h, "disks", newRV_noinc((SV *)newAV()));
131 /* and make a link to the relevant interface object */
132 ref = get_iface(ifaces, ifaceclass, dp->host->netif);
134 hv_store_const(h, "interface", ref);
137 /* push the name of the disk into @{$self->{disks}}; we don't store
138 * a ref to the disk object, as that would create a circular link */
139 g_assert(SvROK(*svp));
140 g_assert(SvTYPE(SvRV(*svp)) == SVt_PVHV);
141 sv = *hv_fetch((HV *)SvRV(*svp), "disks", sizeof("disks")-1, 0);
144 g_assert(SvTYPE(SvRV(sv)) == SVt_PVAV);
145 av_push((AV *)SvRV(sv), safe_newSVpv(dp->name));
151 /* typemaps to pass AV's and HV's in directly (as perl refs) */
153 if (!SvROK($input) || SvTYPE(SvRV($input)) != SVt_PVHV) {
154 SWIG_exception_fail(SWIG_TypeError, "must provide a hashref");
157 $1 = (HV *)SvRV($input);
161 if (!SvROK($input) || SvTYPE(SvRV($input)) != SVt_PVAV) {
162 SWIG_exception_fail(SWIG_TypeError, "must provide an arrayref");
165 $1 = (AV *)SvRV($input);
169 static cfgerr_level_t
170 read_disklist_internal(
172 HV *disks, char *diskclass,
173 HV *hosts, char *hostclass,
174 HV *ifaces, char *ifaceclass)
176 cfgerr_level_t errlev;
179 HV *diskclass_stash = NULL;
185 errlev = read_diskfile(filename, &list);
186 if (errlev >= CFGERR_ERRORS)
189 for (dp = list.head; dp; dp = dp->next) {
195 /* make a new hashref and bless it */
197 diskref = newRV_noinc((SV *)h);
198 if (!diskclass_stash) {
199 diskclass_stash = gv_stashpv(diskclass, GV_ADD);
201 sv_bless(diskref, diskclass_stash);
203 hv_store_const(h, "name", safe_newSVpv(dp->name));
204 hv_store_const(h, "device", safe_newSVpv(dp->device));
205 hv_store_const(h, "spindle", newSViv(dp->spindle));
207 hv_store_const(h, "config",
209 SWIG_NewPointerObj(lookup_dumptype(dp->dtype_name),
210 /* can't use $descriptor here.. */
211 SWIGTYPE_p_dumptype_t, 0)));
213 /* create an uplink ref to the host object */
214 hostref = get_host(hosts, hostclass, ifaces, ifaceclass, dp);
215 SvREFCNT_inc(hostref);
216 hv_store_const(h, "host", hostref);
218 /* and store this disk in the two-level %disks hash */
219 svp = hv_fetch(disks, dp->hostname, strlen(dp->hostname), 1);
221 /* make a new hash for this host */
224 href = newRV_noinc((SV *)h);
225 sv_setsv(*svp, href);
227 g_assert(SvROK(*svp));
228 g_assert(SvTYPE(SvRV(*svp)) == SVt_PVHV);
229 h = (HV *)SvRV(*svp);
232 g_assert(SvROK(*svp));
233 g_assert(SvTYPE(SvRV(*svp)) == SVt_PVHV);
234 SvREFCNT_inc(diskref);
235 hv_store(h, dp->name, strlen(dp->name), diskref, 0);
238 /* free_disklist frees the globals, too, which is not what we want.
239 * So this leaks memory. */
240 /* free_disklist(&list); */
248 package Amanda::Disklist::Disk;
252 package Amanda::Disklist::Host;
255 my ($self, $disk) = @_;
256 return $Amanda::Disklist::disks{$self->{'hostname'}}{$disk};
261 return values %{$Amanda::Disklist::disks{$self->{'hostname'}}};
264 package Amanda::Disklist::Interface;
268 package Amanda::Disklist;
270 our (%disks, %hosts, %interfaces);
275 return read_disklist_internal(
276 ($params{filename} or config_dir_relative(getconf($CNF_DISKFILE))),
277 \%disks, ($params{disk_class} or "Amanda::Disklist::Disk"),
278 \%hosts, ($params{host_class} or "Amanda::Disklist::Host"),
279 \%interfaces, ($params{interface_class} or "Amanda::Disklist::Interface"),
285 return $hosts{$hostname};
289 return values %hosts;
293 my ($hostname, $diskname) = @_;
294 return $disks{$hostname}->{$diskname};
299 foreach my $disk (values %disks) {
300 push @rv, (values %$disk);
306 my ($interfacename) = @_;
307 return $interfaces{$interfacename};
311 return values %interfaces;
314 push @EXPORT_OK, qw( read_disklist
317 get_interface all_interfaces);
320 char *clean_dle_str_for_client(char *dle_str, am_feature_t *their_features);