File Coverage

lib/Net/ISC/DHCPd.pm
Criterion Covered Total %
statement 21 63 33.3
branch 0 18 0.0
condition 0 5 0.0
subroutine 7 13 53.8
pod 1 1 100.0
total 29 100 29.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.1707
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 2     2   20450 use Class::Load 0.20;
  2         42099  
  2         100  
39 2     2   958 use Moose 0.90;
  2         643686  
  2         15  
40 2     2   10852 use Moose::Util::TypeConstraints;
  2         4  
  2         17  
41 2     2   4085 use MooseX::Types::Path::Class 0.05 qw(File);
  2         188456  
  2         13  
42 2     2   2674 use Net::ISC::DHCPd::Types ':all';
  2         6  
  2         12  
43 2     2   8512 use File::Temp 0.20;
  2         177  
  2         157  
44 2     2   23 use v5.12.5;
  2         5  
  2         1073  
45              
46             our $VERSION = eval '0.1707';
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     __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     __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     __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 0     0 1   my $self = shift;
161 0   0       my $what = shift || q();
162 0           my($child_error, $errno, $output);
163              
164 0 0         if($what eq 'config') {
    0          
165 0           my $tmp = File::Temp->new;
166 0           print $tmp $self->config->generate;
167 0           $output = $self->_run('-t', '-cf', $tmp->filename);
168 0           ($child_error, $errno) = ($?, $!);
169             }
170             elsif($what eq 'leases') {
171 0           $output = $self->_run('-t', '-lf', $self->leases->file);
172 0           ($child_error, $errno) = ($?, $!);
173             }
174             else {
175 0           $self->errstr('Invalid argument');
176 0           return;
177             }
178              
179             # let's set this anyway...
180 0           $self->errstr($output);
181              
182 0 0 0       if($child_error and $child_error == -1) {
    0          
183 0           $self->errstr($errno);
184 0           ($!, $?) = ($errno, $child_error);
185 0           return;
186             }
187             elsif($child_error) {
188 0           ($!, $?) = ($errno, $child_error);
189 0           return;
190             }
191              
192 0           return 1;
193             }
194              
195             sub _run {
196 0     0     my $self = shift;
197 0           my @args = @_;
198              
199 0 0         pipe my $reader, my $writer or return '';
200              
201 0 0         if(my $pid = fork) { # parent
    0          
202 0           close $writer;
203 0           wait; # for child process...
204 0           local $/;
205 0           return readline $reader;
206             }
207             elsif(defined $pid) { # child
208 0           close $reader;
209 0 0         open STDERR, '>&', $writer or confess $!;
210 0 0         open STDOUT, '>&', $writer or confess $!;
211 0           { exec $self->binary, @args }
  0            
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;