]>
git.proxmox.com Git - pve-manager.git/blob - lib/PVE.old/Utils.pm
4 use POSIX qw
(:sys_wait_h strftime
);
10 use Authen
::PAM
qw(:constants);
11 use Time
::HiRes qw
(gettimeofday
);
15 my $clock_ticks = POSIX
::sysconf
(&POSIX
::_SC_CLK_TCK
);
20 root
=> [[ '/', 'w' ]],
21 audit
=> [[ '/', 'r' ]],
25 root
=> [[ '/server/' , 'w' ],
27 [ '/system/options.htm', 'r' ],
31 audit
=> [[ '/', 'r' ]],
35 my ($username, $group, $uri, $role) = @_;
39 $alist = $accmode_cnode->{$group};
41 $alist = $accmode->{$group};
43 return undef if !$alist;
45 foreach my $am (@$alist) {
47 return $m if $uri =~ m/^$d/;
53 # authentication tickets
55 sub load_auth_secret
{
56 my $secret = (split (/\s/, `md5sum /etc/pve/pve-root-ca.key`))[0];
58 die "unable to load authentication secret\n" if !$secret;
63 sub create_auth_ticket
{
64 my ($secret, $username, $group) = @_;
66 my $timestamp = time();
67 my $ticket = $username . '::' . $group . '::' . $timestamp . '::' .
68 Digest
::SHA1
::sha1_hex
($username, $group, $timestamp, $secret);
76 # we only allow a limited set of characters (colon is not allowed,
77 # because we store usernames in colon separated lists)!
78 return $username if $username =~ m/^[A-Za-z0-9\.\-_]+(\@[A-Za-z0-9\.\-_]+)?$/;
84 my ($secret, $ticket) = @_;
86 my $cookie_timeout = 2400; # seconds
88 my ($username, $group, $time, $mac) = split /::/, $ticket;
90 return undef if !verify_username
($username);
92 my $age = time() - $time;
94 if (($age > -300) && ($age < $cookie_timeout) &&
95 (Digest
::SHA1
::sha1_hex
($username, $group, $time, $secret) eq $mac)) {
96 return wantarray ?
($username, $group, $age) : $username;
102 sub verify_web_ticket
{
103 my ($secret, $ticket) = @_;
105 my $cookie_timeout = 2400; # seconds
107 my ($username, $group, $time, $mac, $webmac) = split /::/, $ticket;
109 return undef if !verify_username
($username);
111 my $age = time() - $time;
113 if (($age > -300) && ($age < $cookie_timeout) &&
114 (Digest
::SHA1
::sha1_hex
($username, $group, $time, $mac, $secret) eq $webmac)) {
115 return wantarray ?
($username, $group, $age) : $username;
121 # password should be utf8 encoded
122 sub pam_is_valid_user
{
123 my ($username, $password) = @_;
125 # user (www-data) need to be able to read /etc/passwd /etc/shadow
127 my $pamh = new Authen
::PAM
('common-auth', $username, sub {
130 my $msg_type = shift;
132 push @res, (0, $password);
139 my $err = $pamh->pam_strerror($pamh);
140 die "Error during PAM init: $err";
145 if (($res = $pamh->pam_authenticate(0)) != PAM_SUCCESS
) {
146 my $err = $pamh->pam_strerror($res);
147 die "PAM auth failed: $err\n";
150 if (($res = $pamh->pam_acct_mgmt (0)) != PAM_SUCCESS
) {
151 my $err = $pamh->pam_strerror($res);
152 die "PAM auth failed: $err\n";
155 $pamh = 0; # call destructor
161 my ($username, $password) = @_;
163 if (!verify_username
($username)) {
164 syslog
('info', "auth failed: invalid characters in username '$username'");
171 $valid = pam_is_valid_user
($username, $password);
176 syslog
('info', $err);
180 return undef if !$valid;
182 my ($name, $passwd, $uid, $gid) = getpwnam ($username);
183 my $groupname = getgrgid($gid) || 'nogroup';
185 # fixme: what groups are allowed?
186 if ($groupname ne 'root') {
187 syslog
('info', "auth failed: group '$groupname' is not in the list of allowed groups");
195 # WARN: $res->{filename} must not depend on PID, because we
196 # use it before we know the PID
203 # "UPID:$pid:$start:$type:$data"
204 if ($upid =~ m/^UPID:(\d+)(-(\d+))?:(\d+):([^:\s]+):(.*)$/) {
206 $res->{pstart
} = $3 || 0;
207 $res->{starttime
} = $4;
211 if ($res->{type
} eq 'vmops') {
212 if ($res->{data
} =~ m/^([^:\s]+):(\d+):(\d+):(\S+)$/) {
213 $res->{command
} = $1;
218 $res->{filename
} = "/tmp/vmops-$res->{veid}.out";
222 } elsif ($res->{type
} eq 'apldownload') {
223 if ($res->{data
} =~ m/^([^:\s]+):(.+)$/) {
226 $res->{filename
} = "/tmp/apldownload-$res->{user}.out";
237 my $uip_hash = shift;
239 my $d = $uip_hash; # shortcut
241 return "UPID:$d->{pid}-$d->{pstart}:$d->{starttime}:$d->{type}:$d->{data}";
245 # save $SIG{CHLD} handler implementation.
246 # simply set $SIG{CHLD} = &PVE::Utils::worker_reaper;
247 # and register forked processes with PVE::Utils::register_worker(pid)
248 # Note: using $SIG{CHLD} = 'IGNORE' or $SIG{CHLD} = sub { wait (); } or ...
249 # has serious side effects, because perls built in system() and open()
250 # functions can't get the correct exit status of a child. So we cant use
251 # that (also see perlipc)
257 foreach my $pid (keys %$WORKER_PIDS) {
258 my $waitpid = waitpid ($pid, WNOHANG
);
259 if (defined($waitpid) && ($waitpid == $pid)) {
260 delete ($WORKER_PIDS->{$pid});
265 sub register_worker
{
270 # do not register if already finished
271 my $waitpid = waitpid ($pid, WNOHANG
);
272 if (defined($waitpid) && ($waitpid == $pid)) {
273 delete ($WORKER_PIDS->{$pid});
277 $WORKER_PIDS->{$pid} = 1;
292 my ($vmhash, $func) = @_;
294 foreach my $ckey (keys %$vmhash) {
295 next if $ckey !~ m/^CID_(\d+)$/;
297 if (my $vmlist = $vmhash->{$ckey}) {
298 foreach my $vmkey (sort keys %$vmlist) {
299 next if $vmkey !~ m/^VEID_(\d+)$/;
301 my $d = $vmlist->{$vmkey};
302 &$func ($cid, $vmid, $d, $ckey, $vmkey);
309 my ($vmhash, $func) = @_;
311 foreach my $ckey (keys %$vmhash) {
312 next if $ckey !~ m/^CID_(\d+)$/;
314 if (my $vmlist = $vmhash->{$ckey}) {
315 &$func ($cid, $vmlist, $ckey);
321 my ($vmlist, $func) = @_;
323 foreach my $vmkey (keys %$vmlist) {
324 next if $vmkey !~ m/^VEID_(\d+)$/;
326 if (my $d = $vmlist->{$vmkey}) {
327 &$func ($veid, $d, $vmkey);
332 sub foreach_veid_sorted
{
333 my ($vmlist, $func) = @_;
336 foreach my $vmkey (keys %$vmlist) {
337 next if $vmkey !~ m/^VEID_(\d+)$/;
341 foreach my $vmid (sort @vma) {
342 my $vmkey = "VEID_$vmid";
343 if (my $d = $vmlist->{$vmkey}) {
344 &$func ($vmid, $d, $vmkey);
349 sub read_proc_uptime
{
353 my $fh = IO
::File-
>new ("/proc/uptime", "r");
358 if ($line =~ m
|^(\d
+\
.\d
+)\s
+(\d
+\
.\d
+)\s
*$|) {
360 return (int($1*100), int($2*100));
362 return (int($1), int($2));
370 sub read_proc_starttime
{
374 my $fh = IO
::File-
>new ("/proc/$pid/stat", "r");
380 if ($statstr =~ m/^$pid \(.*\) \S (-?\d+) -?\d+ -?\d+ -?\d+ -?\d+ \d+ \d+ \d+ \d+ \d+ (\d+) (\d+) (-?\d+) (-?\d+) -?\d+ -?\d+ -?\d+ 0 (\d+) (\d+) (-?\d+) \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ -?\d+ -?\d+ \d+ \d+ \d+/) {
391 my ($pid, $pstart) = @_;
393 my $st = read_proc_starttime
($pid);
397 return $st == $pstart;
405 my $res = { user
=> 0, nice
=> 0, system => 0, idle
=> 0 , sum
=> 0};
409 if (my $fh = IO
::File-
>new ("/proc/stat", "r")) {
410 while (defined (my $line = <$fh>)) {
411 if ($line =~ m
|^cpu\s
+(\d
+)\s
+(\d
+)\s
+(\d
+)\s
+(\d
+)\s
+(\d
+)\s
|) {
416 $res->{used
} = $1+$2+$3;
418 } elsif ($line =~ m
|^cpu\d
+\s
|) {
425 $cpucount = 1 if !$cpucount;
427 my $ctime = gettimeofday
; # floating point time in seconds
429 $res->{ctime
} = $ctime;
433 $last_proc_stat = $res if !$last_proc_stat;
435 my $diff = ($ctime - $last_proc_stat->{ctime
}) * $clock_ticks * $cpucount;
437 if ($diff > 1000) { # don't update too often
438 my $useddiff = $res->{used
} - $last_proc_stat->{used
};
439 $useddiff = $diff if $useddiff > $diff;
440 $res->{cpu
} = $useddiff/$diff;
441 my $waitdiff = $res->{iowait
} - $last_proc_stat->{iowait
};
442 $waitdiff = $diff if $waitdiff > $diff;
443 $res->{wait} = $waitdiff/$diff;
444 $last_proc_stat = $res;
446 $res->{cpu
} = $last_proc_stat->{cpu
};
447 $res->{wait} = $last_proc_stat->{wait};
455 my $res = { uptime
=> 0, idle
=> 0, avg1
=> 0, avg5
=> 0, avg15
=> 0 };
457 my $fh = IO
::File-
>new ('/proc/loadavg', "r");
461 if ($line =~ m
|^(\d
+\
.\d
+)\s
+(\d
+\
.\d
+)\s
+(\d
+\
.\d
+)\s
+\d
+/\d
+\s
+\d
+\s
*$|) {
467 ($res->{uptime
}, $res->{idle
}) = read_proc_uptime
();
469 my $ut = $res->{uptime
};
470 my $days = int ($ut / 86400);
472 my $hours = int ($ut / 3600);
476 my $utstr = strftime
("%H:%M:%S up ", localtime);
478 my $ds = $days > 1 ?
'days' : 'day';
479 $res->{uptimestrshort
} = sprintf "%d $ds %02d:%02d", $days, $hours, $mins;
481 $res->{uptimestrshort
} = sprintf "%02d:%02d", $hours, $mins;
484 $utstr .= "$res->{uptimestrshort}, ";
485 $utstr .= "load average: $res->{avg1}, $res->{avg5}, $res->{avg15}";
486 $res->{uptimestr
} = $utstr;
492 # memory usage of current process
495 my $res = { size
=> 0, resident
=> 0, shared
=> 0 };
499 open (MEMINFO
, "</proc/$$/statm");
500 my $line = <MEMINFO
>;
503 if ($line =~ m/^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+/) {
504 $res->{size
} = $1*$ps;
505 $res->{resident
} = $2*$ps;
506 $res->{shared
} = $3*$ps;
512 sub get_memory_info
{
523 open (MEMINFO
, "/proc/meminfo");
525 while (my $line = <MEMINFO
>) {
526 if ($line =~ m/^(\S+):\s+(\d+)\s*kB/i) {
527 $res->{lc ($1)} = $2;
533 $res->{memused
} = $res->{memtotal
} - $res->{memfree
};
534 $res->{swapused
} = $res->{swaptotal
} - $res->{swapfree
};
536 $res->{mbmemtotal
} = int ($res->{memtotal
}/1024);
537 $res->{mbmemfree
} = int (($res->{memfree
} + $res->{buffers
} + $res->{cached
})/1024);
538 $res->{mbmemused
} = $res->{mbmemtotal
} - $res->{mbmemfree
};
540 $res->{mbswaptotal
} = int ($res->{swaptotal
}/1024);
541 $res->{mbswapfree
} = int ($res->{swapfree
}/1024);
542 $res->{mbswapused
} = $res->{mbswaptotal
} - $res->{mbswapfree
};
552 my $hd = `df -P '$dir'`;
557 my ($rootfs, $hdo_total, $hdo_used, $hdo_avail) = $hd =~
558 m/^(simfs|vzfs|\/dev\
/\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+%\s.*$/mg;
560 my $real_hd_used = int ($hdo_used/1024);
561 my $real_hd_total = int ($hdo_total/1024);
563 # available memory = total memory - reserved memory
564 my $real_hd_avail = int (($hdo_used+$hdo_avail)/1024);
566 return { total
=> $real_hd_total,
567 avail
=> $real_hd_avail,
568 used
=> $real_hd_used,
569 free
=> $real_hd_avail - $real_hd_used
575 # cycles_per_jiffy = frequency_of_your_cpu/jiffies_per_second
576 # jiffies_per_second = 1000
578 # frequency_of_your_cpu can be read from /proc/cpuinfo, as:
579 # cpu MHz : <frequency_of_your_cpu>
582 my $fn = '/proc/cpuinfo';
584 return $cpuinfo if $cpuinfo;
586 open (CPUINFO
, "<$fn");
590 $res->{model
} = 'unknown';
593 $res->{cpu_cycles_per_jiffy
} = 0; # just to be not 0
598 while (my $line = <CPUINFO
>) {
599 if ($line =~ m/^processor\s*:\s*\d+\s*$/i) {
601 } elsif ($line =~ m/^model\s+name\s*:\s*(.*)\s*$/i) {
602 $res->{model
} = $1 if $res->{model
} eq 'unknown';
603 } elsif ($line =~ m/^cpu\s+MHz\s*:\s*(\d+\.\d+)\s*$/i) {
605 $res->{mhz
} = $1 if !$res->{mhz
};
606 $res->{cpu_cycles_per_jiffy
} += $1 * 1000;
607 } elsif ($line =~ m/^flags\s*:.*(vmx|svm)/) {
608 $res->{hvm
} = 1; # Hardware Virtual Machine (Intel VT / AMD-V)
612 $res->{cpus
} = $count;
616 $res->{kversion
} = `uname -srv`;
618 $res->{proxversion
} = PVE
::pvecfg
::package() . "/" .
619 PVE
::pvecfg
::version
() . "/" .
620 PVE
::pvecfg
::repoid
();
634 if ($fd2 = IO
::File-
>new ("/proc/net/dev", "r")) {
635 while (defined ($line = <$fd2>)) {
637 if ($line =~ m/^\s*(vmbr([0-9]{1,3})):.*/) {
638 my ($name, $num) = ($1, $2);
639 push @$res, $name if int($num) eq $num; # no leading zero
649 my ($cmd, $input, $timeout) = @_;
651 my $reader = IO
::File-
>new();
652 my $writer = IO
::File-
>new();
653 my $error = IO
::File-
>new();
655 my $cmdstr = join (' ', @$cmd);
661 $pid = open3
($writer, $reader, $error, @$cmd) || die $!;
667 if ($orig_pid != $$) {
668 syslog
('err', "ERROR: $err");
675 print $writer $input if defined $input;
678 my $select = new IO
::Select
;
679 $select->add ($reader);
680 $select->add ($error);
682 my ($ostream, $estream) = ('', '');
684 while ($select->count) {
685 my @handles = $select->can_read ($timeout);
687 if (defined ($timeout) && (scalar (@handles) == 0)) {
690 die "command '$cmdstr' failed: timeout";
693 foreach my $h (@handles) {
695 my $count = sysread ($h, $buf, 4096);
696 if (!defined ($count)) {
700 die "command '$cmdstr' failed: $err";
702 $select->remove ($h) if !$count;
705 } elsif ($h eq $error) {
712 my $rv = waitpid ($pid, 0);
717 die "command '$cmdstr' failed with exit code $ec:\n$estream";
719 die "command '$cmdstr' failed with exit code $ec";
728 my $time = substr (Digest
::SHA1
::sha1_base64
(time), 0, 8);
729 return crypt (encode
("utf8", $pw), "\$1\$$time\$");
733 my ($username, $group, $pw, $comment, $rawpw) = @_;
735 my $cmd = ['/usr/sbin/usermod'];
737 push @$cmd, '-c', $comment if defined ($comment);
740 my $epw = $rawpw ?
$pw :_encrypt_pw
($pw);
741 push @$cmd, '-p', $epw;
744 push @$cmd, '-g', $group if $group && $username ne 'root';
746 return if scalar (@$cmd) == 1 ; # no flags given
748 push @$cmd, $username;
755 'dk' => ['Danish', 'da', 'qwerty/dk-latin1.kmap.gz', 'dk', 'nodeadkeys'],
756 'de' => ['German', 'de', 'qwertz/de-latin1-nodeadkeys.kmap.gz', 'de', 'nodeadkeys' ],
757 'de-ch' => ['Swiss-German', 'de-ch', 'qwertz/sg-latin1.kmap.gz', 'ch', 'de_nodeadkeys' ],
758 'en-gb' => ['United Kingdom', 'en-gb', 'qwerty/uk.kmap.gz' , 'gb', 'intl' ],
759 'en-us' => ['U.S. English', 'en-us', 'qwerty/us-latin1.kmap.gz', 'us', 'intl' ],
760 'es' => ['Spanish', 'es', 'qwerty/es.kmap.gz', 'es', 'nodeadkeys'],
761 #'et' => [], # Ethopia or Estonia ??
762 'fi' => ['Finnish', 'fi', 'qwerty/fi-latin1.kmap.gz', 'fi', 'nodeadkeys'],
763 #'fo' => ['Faroe Islands', 'fo', ???, 'fo', 'nodeadkeys'],
764 'fr' => ['French', 'fr', 'azerty/fr-latin1.kmap.gz', 'fr', 'nodeadkeys'],
765 'fr-be' => ['Belgium-French', 'fr-be', 'azerty/be2-latin1.kmap.gz', 'be', 'nodeadkeys'],
766 'fr-ca' => ['Canada-French', 'fr-ca', 'qwerty/cf.kmap.gz', 'ca', 'fr-legacy'],
767 'fr-ch' => ['Swiss-French', 'fr-ch', 'qwertz/fr_CH-latin1.kmap.gz', 'ch', 'fr_nodeadkeys'],
768 #'hr' => ['Croatia', 'hr', 'qwertz/croat.kmap.gz', 'hr', ??], # latin2?
769 'hu' => ['Hungarian', 'hu', 'qwertz/hu.kmap.gz', 'hu', undef],
770 'is' => ['Icelandic', 'is', 'qwerty/is-latin1.kmap.gz', 'is', 'nodeadkeys'],
771 'it' => ['Italian', 'it', 'qwerty/it2.kmap.gz', 'it', 'nodeadkeys'],
772 'jp' => ['Japanese', 'ja', 'qwerty/jp106.kmap.gz', 'jp', undef],
773 'lt' => ['Lithuanian', 'lt', 'qwerty/lt.kmap.gz', 'lt', 'std'],
774 #'lv' => ['Latvian', 'lv', 'qwerty/lv-latin4.kmap.gz', 'lv', ??], # latin4 or latin7?
775 'mk' => ['Macedonian', 'mk', 'qwerty/mk.kmap.gz', 'mk', 'nodeadkeys'],
776 'nl' => ['Dutch', 'nl', 'qwerty/nl.kmap.gz', 'nl', undef],
777 #'nl-be' => ['Belgium-Dutch', 'nl-be', ?, ?, ?],
778 'no' => ['Norwegian', 'no', 'qwerty/no-latin1.kmap.gz', 'no', 'nodeadkeys'],
779 'pl' => ['Polish', 'pl', 'qwerty/pl.kmap.gz', 'pl', undef],
780 'pt' => ['Portuguese', 'pt', 'qwerty/pt-latin1.kmap.gz', 'pt', 'nodeadkeys'],
781 'pt-br' => ['Brazil-Portuguese', 'pt-br', 'qwerty/br-latin1.kmap.gz', 'br', 'nodeadkeys'],
782 #'ru' => ['Russian', 'ru', 'qwerty/ru.kmap.gz', 'ru', undef], # dont know?
783 'si' => ['Slovenian', 'sl', 'qwertz/slovene.kmap.gz', 'si', undef],
784 #'sv' => [], Swedish ?
793 'at' => 'ftp.at.debian.org',
794 'au' => 'ftp.au.debian.org',
795 'be' => 'ftp.be.debian.org',
796 'bg' => 'ftp.bg.debian.org',
797 'br' => 'ftp.br.debian.org',
798 'ca' => 'ftp.ca.debian.org',
799 'ch' => 'ftp.ch.debian.org',
800 'cl' => 'ftp.cl.debian.org',
801 'cz' => 'ftp.cz.debian.org',
802 'de' => 'ftp.de.debian.org',
803 'dk' => 'ftp.dk.debian.org',
804 'ee' => 'ftp.ee.debian.org',
805 'es' => 'ftp.es.debian.org',
806 'fi' => 'ftp.fi.debian.org',
807 'fr' => 'ftp.fr.debian.org',
808 'gr' => 'ftp.gr.debian.org',
809 'hk' => 'ftp.hk.debian.org',
810 'hr' => 'ftp.hr.debian.org',
811 'hu' => 'ftp.hu.debian.org',
812 'ie' => 'ftp.ie.debian.org',
813 'is' => 'ftp.is.debian.org',
814 'it' => 'ftp.it.debian.org',
815 'jp' => 'ftp.jp.debian.org',
816 'kr' => 'ftp.kr.debian.org',
817 'mx' => 'ftp.mx.debian.org',
818 'nl' => 'ftp.nl.debian.org',
819 'no' => 'ftp.no.debian.org',
820 'nz' => 'ftp.nz.debian.org',
821 'pl' => 'ftp.pl.debian.org',
822 'pt' => 'ftp.pt.debian.org',
823 'ro' => 'ftp.ro.debian.org',
824 'ru' => 'ftp.ru.debian.org',
825 'se' => 'ftp.se.debian.org',
826 'si' => 'ftp.si.debian.org',
827 'sk' => 'ftp.sk.debian.org',
828 'tr' => 'ftp.tr.debian.org',
829 'tw' => 'ftp.tw.debian.org',
830 'gb' => 'ftp.uk.debian.org',
831 'us' => 'ftp.us.debian.org',
838 return "''" if !defined ($str) || ($str eq '');
840 die "unable to quote string containing null (\\000) bytes"
843 # from String::ShellQuote
844 if ($str =~ m
|[^\w
!%+,\-./:@^]|) {
858 my ($service, $cmd) = @_;
862 ($cmd eq 'start' || $cmd eq 'stop' || $cmd eq 'restart'
863 || $cmd eq 'reload' || $cmd eq 'awaken') ||
864 die "unknown service command '$cmd': ERROR";
866 if ($service eq 'postfix') {
867 $initd_cmd = '/etc/init.d/postfix';
868 } elsif ($service eq 'pvemirror') {
869 $initd_cmd = '/etc/init.d/pvemirror';
870 } elsif ($service eq 'pvetunnel') {
871 $initd_cmd = '/etc/init.d/pvetunnel';
872 } elsif ($service eq 'pvedaemon') {
873 $initd_cmd = '/etc/init.d/pvedaemon';
874 } elsif ($service eq 'apache') {
875 if ($cmd eq 'restart') {
876 $initd_cmd = '/usr/sbin/apache2ctl';
879 die "invalid service cmd 'apache $cmd': ERROR";
881 } elsif ($service eq 'network') {
882 if ($cmd eq 'restart') {
883 return system ('(sleep 1; /etc/init.d/networking restart; /etc/init.d/postfix restart; /usr/sbin/apache2ctl graceful)&');
885 die "invalid service cmd 'network $cmd': ERROR";
886 } elsif ($service eq 'ntpd') {
887 # debian start/stop scripts does not work for us
888 if ($cmd eq 'stop') {
889 system ('/etc/init.d/ntp stop');
890 #system ('/usr/bin/killall /usr/sbin/ntpd');
891 } elsif ($cmd eq 'start') {
892 system ('/etc/init.d/ntp start');
893 system ('/sbin/hwclock --systohc');
894 } elsif ($cmd eq 'restart') {
895 system ('/etc/init.d/ntp restart');
896 system ('/sbin/hwclock --systohc');
897 # restart cron/syslog to get right schedules and log time/dates
898 system ('/etc/init.d/sysklogd restart');
899 system ('/etc/init.d/cron restart');
902 } elsif ($service eq 'syslog') {
903 $initd_cmd = '/etc/init.d/sysklogd';
904 } elsif ($service eq 'cron') {
905 $initd_cmd = '/etc/init.d/cron';
906 } elsif ($service eq 'sshd') {
907 $initd_cmd = '/etc/init.d/ssh';
909 die "unknown service '$service': ERROR";
912 my $servicecmd = "$initd_cmd $cmd";
914 my $res = run_command
([$initd_cmd, $cmd]);
924 if ($service eq 'postfix') {
925 $pid_file = '/var/spool/postfix/pid/master.pid';
926 } elsif ($service eq 'apache') {
927 $pid_file = '/var/run/apache2.pid';
928 } elsif ($service eq 'bind') {
929 $pid_file = '/var/run/bind/run/named.pid';
930 } elsif ($service eq 'pvemirror') {
931 $pid_file = '/var/run/pvemirror.pid';
932 } elsif ($service eq 'pvetunnel') {
933 $pid_file = '/var/run/pvetunnel.pid';
934 } elsif ($service eq 'pvedaemon') {
935 $pid_file = '/var/run/pvedaemon.pid';
936 } elsif ($service eq 'ntpd') {
937 $pid_file = '/var/run/ntpd.pid';
938 } elsif ($service eq 'sshd') {
939 $pid_file = '/var/run/sshd.pid';
941 die "unknown service '$service': ERROR";
945 if (my $fh = IO
::File-
>new ($pid_file, "r")) {
949 if ($line && ($line =~ m/^\s*(\d+)\s*$/)) {
954 return 'running' if ($pid && kill (0, $pid));
959 sub service_wait_stopped
{
960 my ($timeout, @services) = @_;
962 my $starttime = time();
967 foreach my $s (@services) {
968 if (service_state
($s) eq 'running') {
970 if ((time() - $starttime) > $timeout) {
971 die "unable to stop services (got timeout)\n";
974 service_cmd
($s, 'stop');
987 sub check_vm_settings
{
990 if (defined ($settings->{mem
})) {
995 if ($settings->{mem
} < $min) {
996 die __
("Memory needs to be at least $min MB") . "\n";
998 if ($settings->{mem
} > $max) {
999 die __
("Memory needs to be less than $max MB") . "\n";
1003 if (defined ($settings->{swap
})) {
1007 if ($settings->{swap
} > $max) {
1008 die __
("Swap needs to be less than $max MB") . "\n";
1012 if (defined ($settings->{cpuunits
}) &&
1013 ($settings->{cpuunits
} < 8 || $settings->{cpuunits
} > 500000)) {
1014 die "parameter cpuunits out of range\n";
1017 if (defined ($settings->{cpus
}) &&
1018 ($settings->{cpus
} < 1 || $settings->{cpus
} > 16)) {
1019 die "parameter cpus out of range\n";