]> git.proxmox.com Git - pve-manager.git/blob - PVE/Status/Plugin.pm
update shipped appliance info index
[pve-manager.git] / PVE / Status / Plugin.pm
1 package PVE::Status::Plugin;
2
3 use strict;
4 use warnings;
5
6 use PVE::JSONSchema;
7 use PVE::Cluster qw(cfs_register_file);
8 use PVE::SectionConfig;
9
10 use base qw(PVE::SectionConfig);
11
12 cfs_register_file('status.cfg',
13 sub { __PACKAGE__->parse_config(@_); },
14 sub { __PACKAGE__->write_config(@_); }
15 );
16
17 my $defaultData = {
18 propertyList => {
19 id => {
20 description => "The ID of the entry.",
21 type => 'string', format => 'pve-configid',
22 },
23 type => {
24 description => "Plugin type.",
25 type => 'string', format => 'pve-configid',
26 },
27 disable => {
28 description => "Flag to disable the plugin.",
29 type => 'boolean',
30 optional => 1,
31 },
32 server => {
33 type => 'string', format => 'address',
34 description => "server dns name or IP address",
35 },
36 port => {
37 type => 'integer',
38 description => "server network port",
39 minimum => 1,
40 maximum => 64*1024,
41 },
42 mtu => {
43 type => 'integer',
44 description => "MTU for metrics transmission over UDP",
45 default => 1500,
46 minimum => 512,
47 maximum => 64*1024,
48 optional => 1,
49 },
50 },
51 };
52
53 sub private {
54 return $defaultData;
55 }
56
57 sub parse_section_header {
58 my ($class, $line) = @_;
59
60 if ($line =~ m/^(\S+):\s*(\S+)?\s*$/) {
61 my $type = lc($1);
62 my $id = $2 // $type;
63 my $errmsg = undef; # set if you want to skip whole section
64 eval { PVE::JSONSchema::pve_verify_configid($id) };
65 $errmsg = $@ if $@;
66 my $config = {}; # to return additional attributes
67 return ($type, $id, $errmsg, $config);
68 }
69 return undef;
70 }
71
72 sub _connect {
73 my ($class, $cfg, $id) = @_;
74 die "please implement inside plugin";
75 }
76
77 sub _disconnect {
78 my ($class, $connection, $cfg) = @_;
79
80 $connection->close(); # overwrite if not a simple socket
81 }
82
83 # UDP cannot do more than 64k at once. Overwrite for different protocol limits.
84 sub _send_batch_size {
85 my ($class, $cfg) = @_;
86
87 # default to 1500 MTU, empty IPv6 UDP packet needs 48 bytes overhead
88 my $mtu = $cfg->{mtu} // 1500;
89 return $mtu - 50; # a bit more than 48byte to allow for safe room
90 }
91
92 # call with the smalles $data chunks possible
93 sub add_metric_data {
94 my ($class, $txn, $data) = @_;
95 return if !defined($data);
96
97 my $batch_size = $class->_send_batch_size($txn->{cfg});
98 my $data_length = length($data) // 0;
99 my $dataq_len = length($txn->{data}) // 0;
100
101 if (($dataq_len + $data_length) >= $batch_size) {
102 $class->flush_data($txn);
103 }
104 $txn->{data} //= '';
105 $txn->{data} .= "$data";
106 }
107
108 sub flush_data {
109 my ($class, $txn) = @_;
110
111 if (!$txn->{connection}) {
112 return if !$txn->{data}; # OK, if data was already sent/flushed
113 die "cannot flush metric data, no connection available!\n";
114 }
115 return if !defined($txn->{data}) || $txn->{data} eq '';
116
117 my $data = delete $txn->{data};
118 eval { $class->send($txn->{connection}, $data, $txn->{cfg}) };
119 die "metrics send error '$txn->{id}': $@" if $@;
120 }
121
122 sub send {
123 my ($class, $connection, $data, $cfg) = @_;
124
125 defined($connection->send($data))
126 or die "failed to send metrics: $!\n";
127 }
128
129 sub test_connection {
130 my ($class, $cfg, $id) = @_;
131
132 # do not check connection for disabled plugins
133 return if $cfg->{disable};
134
135 my $conn = $class->_connect($cfg, $id);
136 $class->_disconnect($conn, $cfg);
137 }
138
139 sub update_node_status {
140 my ($class, $txn, $node, $data, $ctime) = @_;
141 die "please implement inside plugin";
142 }
143
144 sub update_qemu_status {
145 my ($class, $txn, $vmid, $data, $ctime, $nodename) = @_;
146 die "please implement inside plugin";
147 }
148
149 sub update_lxc_status {
150 my ($class, $txn, $vmid, $data, $ctime, $nodename) = @_;
151 die "please implement inside plugin";
152 }
153
154 sub update_storage_status {
155 my ($class, $txn, $nodename, $storeid, $data, $ctime) = @_;
156 die "please implement inside plugin";
157 }
158
159 sub on_add_hook {
160 my ($class, $id, $opts, $sensitive_opts) = @_;
161
162 # implement in subclass
163
164 return undef;
165 }
166
167 sub on_update_hook {
168 my ($class, $id, $opts, $sensitive_opts) = @_;
169
170 # implement in subclass
171
172 return undef;
173 }
174
175 sub on_delete_hook {
176 my ($class, $id, $opts) = @_;
177
178 # implement in subclass
179
180 return undef;
181 }
182
183 1;