]>
Commit | Line | Data |
---|---|---|
5bdc31fb AD |
1 | package PVE::Firewall::Helpers; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | ||
8bd9b3e4 CE |
6 | use Date::Parse qw(str2time); |
7 | use Errno qw(ENOENT); | |
8 | use File::Basename qw(fileparse); | |
9 | use IO::Zlib; | |
21d5ba9c | 10 | use PVE::Cluster; |
5bdc31fb AD |
11 | use PVE::Tools qw(file_get_contents file_set_contents); |
12 | ||
13 | use base 'Exporter'; | |
14 | our @EXPORT_OK = qw( | |
21d5ba9c | 15 | lock_vmfw_conf |
5bdc31fb AD |
16 | remove_vmfw_conf |
17 | clone_vmfw_conf | |
18 | ); | |
19 | ||
20 | my $pvefw_conf_dir = "/etc/pve/firewall"; | |
21 | ||
21d5ba9c TL |
22 | sub lock_vmfw_conf { |
23 | my ($vmid, $timeout, $code, @param) = @_; | |
24 | ||
25 | die "can't lock VM firewall config for undefined VMID\n" | |
26 | if !defined($vmid); | |
27 | ||
28 | my $res = PVE::Cluster::cfs_lock_firewall("vm-$vmid", $timeout, $code, @param); | |
29 | die $@ if $@; | |
30 | ||
31 | return $res; | |
32 | } | |
33 | ||
5bdc31fb AD |
34 | sub remove_vmfw_conf { |
35 | my ($vmid) = @_; | |
36 | ||
37 | my $vmfw_conffile = "$pvefw_conf_dir/$vmid.fw"; | |
38 | ||
39 | unlink $vmfw_conffile; | |
40 | } | |
41 | ||
42 | sub clone_vmfw_conf { | |
43 | my ($vmid, $newid) = @_; | |
44 | ||
45 | my $sourcevm_conffile = "$pvefw_conf_dir/$vmid.fw"; | |
46 | my $clonevm_conffile = "$pvefw_conf_dir/$newid.fw"; | |
47 | ||
48 | lock_vmfw_conf($newid, 10, sub { | |
49 | if (-f $clonevm_conffile) { | |
50 | unlink $clonevm_conffile; | |
51 | } | |
52 | if (-f $sourcevm_conffile) { | |
53 | my $data = file_get_contents($sourcevm_conffile); | |
54 | file_set_contents($clonevm_conffile, $data); | |
55 | } | |
56 | }); | |
57 | } | |
58 | ||
8bd9b3e4 CE |
59 | sub dump_fw_logfile { |
60 | my ($filename, $param, $callback) = @_; | |
61 | my ($start, $limit, $since, $until) = $param->@{qw(start limit since until)}; | |
62 | ||
63 | my $filter = sub { | |
64 | my ($line) = @_; | |
65 | ||
66 | if (defined($callback)) { | |
67 | return undef if !$callback->($line); | |
68 | } | |
69 | ||
70 | if ($since || $until) { | |
71 | my @words = split / /, $line; | |
72 | my $timestamp = str2time($words[3], $words[4]); | |
73 | return undef if $since && $timestamp < $since; | |
74 | return undef if $until && $timestamp > $until; | |
75 | } | |
76 | ||
77 | return $line; | |
78 | }; | |
79 | ||
80 | if (!defined($since) && !defined($until)) { | |
81 | return PVE::Tools::dump_logfile($filename, $start, $limit, $filter); | |
82 | } | |
83 | ||
84 | my %state = ( | |
85 | 'count' => 0, | |
86 | 'lines' => [], | |
87 | 'start' => $start, | |
88 | 'limit' => $limit, | |
89 | ); | |
90 | ||
91 | # Take into consideration also rotated logs | |
92 | my ($basename, $logdir, $type) = fileparse($filename); | |
93 | my $regex = qr/^\Q$basename\E(\.[\d]+(\.gz)?)?$/; | |
94 | my @files = (); | |
95 | ||
96 | PVE::Tools::dir_glob_foreach($logdir, $regex, sub { | |
97 | my ($file) = @_; | |
98 | push @files, $file; | |
99 | }); | |
100 | ||
101 | @files = reverse sort @files; | |
102 | ||
103 | my $filecount = 0; | |
104 | for my $filename (@files) { | |
105 | $state{'final'} = $filecount == $#files; | |
106 | $filecount++; | |
107 | ||
108 | my $fh; | |
109 | if ($filename =~ /\.gz$/) { | |
110 | $fh = IO::Zlib->new($logdir.$filename, "r"); | |
111 | } else { | |
112 | $fh = IO::File->new($logdir.$filename, "r"); | |
113 | } | |
114 | ||
115 | if (!$fh) { | |
116 | # If file vanished since reading dir entries, ignore | |
117 | next if $!{ENOENT}; | |
118 | ||
119 | my $lines = $state{'lines'}; | |
120 | my $count = ++$state{'count'}; | |
121 | push @$lines, ($count, { n => $count, t => "unable to open file - $!"}); | |
122 | last; | |
123 | } | |
124 | ||
125 | PVE::Tools::dump_logfile_by_filehandle($fh, $filter, \%state); | |
126 | ||
127 | close($fh); | |
128 | } | |
129 | ||
130 | return ($state{'count'}, $state{'lines'}); | |
131 | } | |
132 | ||
21d5ba9c | 133 | 1; |