File Coverage

lib/Net/ISC/DHCPd.pm
Criterion Covered Total %
statement 49 63 77.7
branch 12 18 66.6
condition 3 5 60.0
subroutine 9 13 69.2
pod 1 1 100.0
total 74 100 74.0


line stmt bran cond sub pod time code
1             package Net::ISC::DHCPd;
2              
3             =head1 NAME
4              
5             Net::ISC::DHCPd - Interacts with ISC DHCPd
6              
7             =head1 VERSION
8              
9             0.1708
10              
11             =head1 SYNOPSIS
12              
13             my $dhcpd = Net::ISC::DHCPd->new(
14             config => { file => "path/to/config" },
15             leases => { file => "path/to/leases" },
16             omapi => { key => "some key" },
17             );
18              
19             $dhcpd->config->parse;
20              
21             See the tests bundled to this distribution for more examples.
22              
23             =head1 DESCRIPTION
24              
25             This namespace contains three semi-separate projects, which this module
26             binds together: L<dhcpd.conf|Net::ISC::DHCPd::Config>,
27             L<dhcpd.leases|Net::ISC::DHCPd::Leases> and L<omapi|Net::ISC::DHCPd::OMAPI>.
28             It is written with L<Moose> which provides classes and roles to represents
29             things like a host, a lease or any other thing.
30              
31             The distribution as a whole is targeted an audience who configure and/or
32             analyze the L<Internet Systems Consortium DHCP Server|http://www.isc.org/software/dhcp>.
33             If you are not familiar with the server, check out
34             L<the man pages|http://www.google.com/search?q=man+dhcpd>.
35              
36             =cut
37              
38 5     5   81893 use Class::Load 0.20;
  5         107885  
  5         207  
39 5     5   2544 use Moose 0.90;
  5         1640887  
  5         35  
40 5     5   27484 use Moose::Util::TypeConstraints;
  5         5  
  5         41  
41 5     5   10241 use MooseX::Types::Path::Class 0.05 qw(File);
  5         446657  
  5         35  
42 5     5   7575 use Net::ISC::DHCPd::Types ':all';
  5         18  
  5         45  
43 5     5   22705 use File::Temp 0.20;
  5         204  
  5         491  
44 5     5   51 use v5.12.5;
  5         10  
  5         2941  
45              
46             our $VERSION = eval '0.1708';
47              
48             =head1 ATTRIBUTES
49              
50             =head2 config
51              
52             This attribute holds a read-only L<Net::ISC::DHCPd::Config> object.
53             It can be set from the constructor, using either an object or a hash-ref.
54             The hash-ref will then be passed on to the constructor.
55              
56             =cut
57              
58             has config => (
59             is => 'ro',
60             isa => ConfigObject,
61             coerce => 1,
62             lazy_build => 1,
63             );
64              
65 0     0   0 __PACKAGE__->meta->add_method(_build_config => sub { _build_child_obj(Config => @_) });
66              
67             =head2 leases
68              
69             This attribute holds a read-only L<Net::ISC::DHCPd::Leases> object.
70             It can be set from the constructor, using either an object or a hash-ref.
71             The hash-ref will then be passed on to the constructor.
72              
73             =cut
74              
75             has leases => (
76             is => 'ro',
77             isa => LeasesObject,
78             coerce => 1,
79             lazy_build => 1,
80             );
81              
82 0     0   0 __PACKAGE__->meta->add_method(_build_leases => sub { _build_child_obj(Leases => @_) });
83              
84             =head2 omapi
85              
86             This attribute holds a read-only L<Net::ISC::DHCPd::OMAPI> object.
87             It can be set from the constructor, using either an object or a hash-ref.
88             The hash-ref will then be passed on to the constructor.
89              
90             =cut
91              
92             has omapi => (
93             is => 'ro',
94             isa => OMAPIObject,
95             coerce => 1,
96             lazy_build => 1,
97             );
98              
99 0     0   0 __PACKAGE__->meta->add_method(_build_omapi => sub { _build_child_obj(OMAPI => @_) });
100              
101             =head2 binary
102              
103             This attribute holds a L<Path::Class::File> object to the dhcpd binary.
104             It is read-only and the default is "dhcpd3".
105              
106             =cut
107              
108             has binary => (
109             is => 'ro',
110             isa => File,
111             coerce => 1,
112             default => 'dhcpd3',
113             );
114              
115             =head2 errstr
116              
117             Holds the last know error as a plain string. This only applies to OMAPI.
118              
119             =cut
120              
121             has errstr => (
122             is => 'rw',
123             isa => 'Str',
124             default => '',
125             );
126              
127             =head1 METHODS
128              
129             =head2 parse
130              
131             $config->parse;
132              
133             This parses the config file or the leases file.
134              
135             =cut
136              
137             =head2 generate
138              
139             print $config->generate;
140              
141             This generates a copy of the config file in plaintext.
142              
143             =cut
144              
145              
146             =head2 test
147              
148             $bool = $self->test("config");
149             $bool = $self->test("leases");
150              
151             Will test either the config or leases file. It returns a boolean value
152             which indicates if it is valid or not: True means it is valid, while
153             false means it is invalid. Check L</errstr> on failure - it will contain
154             a descriptive string from either this module, C<$!> or the exit value
155             (integer stored as a string).
156              
157             =cut
158              
159             sub test {
160 9     9 1 24 my $self = shift;
161 9   50     55 my $what = shift || q();
162 9         18 my($child_error, $errno, $output);
163              
164 9 100       52 if($what eq 'config') {
    50          
165 4         40 my $tmp = File::Temp->new;
166 4         2004 print $tmp $self->config->generate;
167 4         24 $output = $self->_run('-t', '-cf', $tmp->filename);
168 3         114 ($child_error, $errno) = ($?, $!);
169             }
170             elsif($what eq 'leases') {
171 5         179 $output = $self->_run('-t', '-lf', $self->leases->file);
172 3         75 ($child_error, $errno) = ($?, $!);
173             }
174             else {
175 0         0 $self->errstr('Invalid argument');
176 0         0 return;
177             }
178              
179             # let's set this anyway...
180 6         1695 $self->errstr($output);
181              
182 6 50 66     67 if($child_error and $child_error == -1) {
    100          
183 0         0 $self->errstr($errno);
184 0         0 ($!, $?) = ($errno, $child_error);
185 0         0 return;
186             }
187             elsif($child_error) {
188 1         9 ($!, $?) = ($errno, $child_error);
189 1         23 return;
190             }
191              
192 5         87 return 1;
193             }
194              
195             sub _run {
196 9     9   45 my $self = shift;
197 9         30 my @args = @_;
198              
199 9 50       261 pipe my $reader, my $writer or return '';
200              
201 9 100       16347 if(my $pid = fork) { # parent
    50          
202 6         237 close $writer;
203 6         38294835 wait; # for child process...
204 6         147 local $/;
205 6         461 return readline $reader;
206             }
207             elsif(defined $pid) { # child
208 3         152 close $reader;
209 3 50       386 open STDERR, '>&', $writer or confess $!;
210 3 50       109 open STDOUT, '>&', $writer or confess $!;
211 3         24 { exec $self->binary, @args }
  3         896  
212 0           confess "Exec() failed";
213             }
214              
215 0           return ''; # fork failed. check $!
216             }
217              
218             # used from attributes
219             sub _build_child_obj {
220 0     0     my $type = shift;
221 0           my $self = shift;
222              
223 0           Class::Load::load_class("Net::ISC::DHCPd::$type");
224              
225 0           return "Net::ISC::DHCPd::$type"->new(@_);
226             }
227              
228             =head1 SEE ALSO
229              
230             =over 8
231              
232             =item Net::DHCP::Info
233              
234             C<Net::DHCP::Info> an older dhcpd.leases and dhcpd.conf parser, also written
235             by Jan Henning Thorsen. It has many limitations that these modules address.
236              
237             =item kea.isc.org
238              
239             C<kea.isc.org> a replacement DHCP server from ISC that is high-performance and
240             supports an API and on-line configuration directly.
241              
242             =back
243              
244             =head1 BUGS
245              
246             Please report any bugs or feature requests to
247             C<bug-net-isc-dhcpd at rt.cpan.org>, or through the web interface at
248             L<https://github.com/jhthorsen/net-isc-dhcpd/issues>.
249             I will be notified, and then you'll automatically be notified of progress on
250             your bug as I make changes.
251              
252             =head1 COPYRIGHT & LICENSE
253              
254             Copyright 2007 Jan Henning Thorsen, all rights reserved.
255              
256             This program is free software; you can redistribute it and/or modify it
257             under the same terms as Perl itself.
258              
259             =head1 AUTHOR
260              
261             Jan Henning Thorsen, C<< <jhthorsen at cpan.org> >>
262              
263             =head1 MAINTAINER
264              
265             Robert Drake, C<< <rdrake at cpan.org> >>
266              
267             =head1 CONTRIBUTORS
268              
269             Nito Martinez
270              
271             Alexey Illarionov
272              
273             Patrick
274              
275             napetrov
276              
277             zoffixznet
278              
279             =cut
280             __PACKAGE__->meta->make_immutable;
281             1;