]> git.proxmox.com Git - pve-manager.git/blobdiff - PVE/APLInfo.pm
read_aplinfo_from_fh: use architecture to generate default file names
[pve-manager.git] / PVE / APLInfo.pm
index 26fd791ec834487b8164926b1f047d0ce2c3d970..5f0737b3e938becfd77723bb29486c0107a51412 100644 (file)
@@ -3,30 +3,37 @@ package PVE::APLInfo;
 use strict;
 use IO::File;
 use PVE::SafeSyslog;
-use PVE::I18N;
 use LWP::UserAgent;
-use PVE::Config;
 use POSIX qw(strftime);
 
 my $logfile = "/var/log/pveam.log";
+my $aplinfodir = "/var/lib/pve-manager/apl-info";
 
 # Default list of GPG keys allowed to sign aplinfo
 #
 #pub   1024D/5CAC72FE 2004-06-24
 #      Key fingerprint = 9ABD 7E02 AD24 3AD3 C2FB  BCCC B0C1 CC22 5CAC 72FE
 #uid                  Proxmox Support Team <support@proxmox.com>
+#pub   2048R/A16EB94D 2008-08-15 [expires: 2023-08-12]
+#      Key fingerprint = 694C FF26 795A 29BA E07B  4EB5 85C2 5E95 A16E B94D
+#uid                  Turnkey Linux Release Key <release@turnkeylinux.com>
 
 my $valid_keys = {
     '9ABD7E02AD243AD3C2FBBCCCB0C1CC225CAC72FE' => 1, # fingerprint support@proxmox.com
     '25CAC72FE' => 1,                                # keyid support@proxmox.com
+    '694CFF26795A29BAE07B4EB585C25E95A16EB94D' => 1, # fingerprint release@turnkeylinux.com
+    'A16EB94D' => 1,                                 # keyid release@turnkeylinux.com
 };
 
 sub import_gpg_keys {
 
-    my $keyfile = '/usr/share/doc/pve-manager/support@proxmox.com.pubkey';
+    my @keyfiles = ('support@proxmox.com.pubkey', 'release@turnkeylinux.com.pubkey');
 
-    return system ("/usr/bin/gpg --batch --no-tty --status-fd=1 -q " .
-                  "--logger-fd=1 --import $keyfile >>$logfile");
+    foreach my $key (@keyfiles) {
+       my $fn = "/usr/share/doc/pve-manager/$key";
+       system ("/usr/bin/gpg --batch --no-tty --status-fd=1 -q " .
+               "--logger-fd=1 --import $fn >>$logfile");
+    }
 }
 
 sub logmsg {
@@ -41,6 +48,96 @@ sub logmsg {
     }
 }
 
+sub read_aplinfo_from_fh {
+    my ($fh, $list, $source, $update) = @_;
+
+    local $/ = "";
+
+    while (my $rec = <$fh>) {
+       chomp $rec;
+       
+       my $res = {};
+
+       while ($rec) {
+
+           if ($rec =~ s/^Description:\s*([^\n]*)(\n\s+.*)*$//si) {
+               $res->{headline} = $1;
+               my $long = $2;
+               $long =~ s/\n\s+/ /g;
+               $long =~ s/^\s+//g;
+               $long =~ s/\s+$//g;
+               $res->{description} = $long;
+           } elsif ($rec =~ s/^Version:\s*(.*\S)\s*\n//i) {
+               my $version = $1;
+               if ($version =~ m/^(\d[a-zA-Z0-9\.\+\-\:\~]*)-(\d+)$/) {
+                   $res->{version} = $version;
+               } else {
+                   my $msg = "unable to parse appliance record: version = '$version'\n";
+                   $update ? die $msg : warn $msg;
+               }
+           } elsif ($rec =~ s/^Type:\s*(.*\S)\s*\n//i) {
+               my $type = $1;
+               if ($type =~ m/^(openvz|lxc)$/) {
+                   $res->{type} = $type;
+               } else {
+                   my $msg = "unable to parse appliance record: unknown type '$type'\n";
+                   $update ? die $msg : warn $msg;
+               }
+           } elsif ($rec =~ s/^([^:]+):\s*(.*\S)\s*\n//) {
+               $res->{lc $1} = $2;
+           } else {
+               my $msg = "unable to parse appliance record: $rec\n";
+               $update ? die $msg : warn $msg;         
+               $res = {};
+               last;
+           }
+       }
+       
+       if ($res->{'package'} eq 'pve-web-news' && $res->{description}) {
+           $list->{'all'}->{$res->{'package'}} = $res;     
+           next;
+       }
+
+       $res->{section} = 'unknown' if !$res->{section};
+       
+       if ($res->{'package'} && $res->{type} && $res->{os} && $res->{version} &&
+           $res->{infopage}) {
+           my $template;
+           if ($res->{location}) {
+               $template = $res->{location};
+               $template =~ s|.*/([^/]+.tar.gz)|$1|;
+           } else {
+               my $arch = $res->{architecture} || 'i386';
+               $template = "$res->{os}-$res->{package}_$res->{version}_$arch.tar.gz";
+               $template =~ s/$res->{os}-$res->{os}-/$res->{os}-/;
+           }
+           $res->{source} = $source;
+           $res->{template} = $template;
+           $list->{$res->{section}}->{$template} = $res;
+           $list->{'all'}->{$template} = $res;
+       } else {
+           my $msg = "found incomplete appliance records\n";
+           $update ? die $msg : warn $msg;             
+       }
+    }
+}
+
+sub read_aplinfo {
+    my ($filename, $list, $source, $update) = @_;
+
+    my $fh = IO::File->new("<$filename") ||
+       die "unable to open file '$filename' - $!\n";
+
+    eval { read_aplinfo_from_fh($fh, $list, $source, $update); };
+    my $err = $@;
+
+    close($fh);
+
+    die $err if $err;
+    
+    return $list;
+}
+
 sub url_get {
     my ($ua, $url, $file, $logfh) = @_;
 
@@ -59,64 +156,43 @@ sub url_get {
     return 1;
 }
 
-sub update {
-    my ($proxy) = @_;
+sub download_aplinfo {
+    my ($ua, $aplurl, $host, $logfd) = @_;
 
-    my $aplurl = "http://download.proxmox.com/appliances";
     my $aplsrcurl = "$aplurl/aplinfo.dat.gz";
     my $aplsigurl = "$aplurl/aplinfo.dat.asc";
 
-    my $size;
-    if (($size = (-s $logfile) || 0) > (1024*50)) {
-       system ("mv $logfile $logfile.0");
-    }
-    my $logfd = IO::File->new (">>$logfile");
-    logmsg ($logfd, "starting update");
-
-    import_gpg_keys();
-
-    my $tmp = "/tmp/pveam.tmp.$$";
+    my $tmp = "$aplinfodir/pveam-${host}.tmp.$$";
     my $tmpgz = "$tmp.gz";
     my $sigfn = "$tmp.asc";
 
-    # this code works for ftp and http
-    # always use passive ftp
-    local $ENV{FTP_PASSIVE} = 1;
-    my $ua = LWP::UserAgent->new;
-    $ua->agent("PVE/1.0");
-
-    if ($proxy) {
-       $ua->proxy(['http'], $proxy);
-    } else {
-       $ua->env_proxy;
-    }
-
     eval {
-       if (url_get ($ua, $aplsigurl, $sigfn, $logfd) != 0) {
-           die "update failed - no signature\n";
+
+       if (url_get($ua, $aplsigurl, $sigfn, $logfd) != 0) {
+           die "update failed - no signature file '$sigfn'\n";
        }
 
-       if (url_get ($ua, $aplsrcurl, $tmpgz, $logfd) != 0) {
-           die "update failed - no data\n";
+       if (url_get($ua, $aplsrcurl, $tmpgz, $logfd) != 0) {
+           die "update failed - no data file '$aplsrcurl'\n";
        }
  
-       if (system ("zcat -f $tmpgz >$tmp 2>/dev/null") != 0) {
+       if (system("zcat -f $tmpgz >$tmp 2>/dev/null") != 0) {
            die "update failed: unable to unpack '$tmpgz'\n";
        } 
 
        # verify signature
 
-       my $cmd = "/usr/bin/gpg --verify --batch --no-tty --status-fd=1 -q " .
+       my $cmd = "/usr/bin/gpg --verify --trust-model always --batch --no-tty --status-fd=1 -q " .
            "--logger-fd=1 $sigfn $tmp";
 
-       open (CMD, "$cmd|") ||
+       open(CMD, "$cmd|") ||
            die "unable to execute '$cmd': $!\n";
 
        my $line;
        my $signer = '';
-       while (defined ($line = <CMD>)) {
+       while (defined($line = <CMD>)) {
            chomp $line;
-           logmsg ($logfd, $line);
+           logmsg($logfd, $line);
 
            # code borrowed from SA
            next if $line !~ /^\Q[GNUPG:]\E (?:VALID|GOOD)SIG (\S{8,40})/;
@@ -130,26 +206,26 @@ sub update {
            $signer = $key if (length $key > length $signer) && $valid_keys->{$key};
        }
 
-       close (CMD);
+       close(CMD);
 
        die "unable to verify signature\n" if !$signer;
 
-       logmsg ($logfd, "signature valid: $signer");
+       logmsg($logfd, "signature valid: $signer");
 
        # test syntax
        eval { 
-           my $fh = IO::File->new ("<$tmp") ||
+           my $fh = IO::File->new("<$tmp") ||
                die "unable to open file '$tmp' - $!\n";
-           PVE::Config::read_aplinfo ($tmp, $fh, 1);
-           close ($fh);
+           read_aplinfo($tmp, {}, $aplurl, 1);
+           close($fh);
        };
        die "update failed: $@" if $@;
 
-       if (system ("mv $tmp /var/lib/pve-manager/apl-available 2>/dev/null") != 0) { 
+       if (system("mv $tmp $aplinfodir/$host 2>/dev/null") != 0) { 
            die "update failed: unable to store data\n";
        }
 
-       logmsg ($logfd, "update sucessful");
+       logmsg($logfd, "update sucessful");
     };
 
     my $err = $@;
@@ -158,78 +234,84 @@ sub update {
     unlink $tmpgz;
     unlink $sigfn;
 
-    if ($err) {
-       logmsg ($logfd, $err);
-       close ($logfd);
-
-       return 0;
-    } 
-
-    close ($logfd);
-
-    return 1;
+    die $err if $err;
 }
 
-sub load_data {
-
-    my $filename = "/var/lib/pve-manager/apl-available";
-
-    if (! -f $filename) {
-       system ("cp /usr/share/doc/pve-manager/aplinfo.dat /var/lib/pve-manager/apl-available");
-    }
+sub get_apl_sources {
+    my $urls = [];
+    push @$urls, "http://download.proxmox.com/appliances";
+    push @$urls, "http://releases.turnkeylinux.org/pve";
 
-    return PVE::Config::read_file ('aplinfo');
+    return $urls;
 }
 
-sub display_name {
-    my ($template) = @_;
-
-    my $templates = load_data ();
+sub update {
+    my ($proxy) = @_;
 
-    return $template if !$templates;
+    my $size;
+    if (($size = (-s $logfile) || 0) > (1024*50)) {
+       system ("mv $logfile $logfile.0");
+    }
+    my $logfd = IO::File->new (">>$logfile");
+    logmsg($logfd, "starting update");
 
-    my $d =  $templates->{'all'}->{$template};
+    import_gpg_keys();
 
-    $template =~ s/\.tar\.gz$//;
-    $template =~ s/_i386$//;
+    # this code works for ftp and http
+    # always use passive ftp
+    local $ENV{FTP_PASSIVE} = 1;
+    my $ua = LWP::UserAgent->new;
+    $ua->agent("PVE/1.0");
 
-    return $template if !$d;
+    if ($proxy) {
+       $ua->proxy(['http'], $proxy);
+    } else {
+       $ua->env_proxy;
+    }
 
-    return "$d->{package}_$d->{version}";
-}
+    my $urls = get_apl_sources();
 
-sub pkginfo {
-    my ($template) = @_;
+    mkdir $aplinfodir;
 
-    my $templates = load_data ();
+    my @dlerr = ();
+    foreach my $aplurl (@$urls) {
+       eval { 
+           my $uri = URI->new($aplurl);
+           my $host = $uri->host();
+           download_aplinfo($ua, $aplurl, $host, $logfd); 
+       };
+       if (my $err = $@) {
+           logmsg ($logfd, $err);
+           push @dlerr, $aplurl; 
+       }
+    } 
 
-    return undef if !$templates;
+    close($logfd);
 
-    my $d =  $templates->{'all'}->{$template};
+    return 0 if scalar(@dlerr);
 
-    return $d;
+    return 1;
 }
 
-sub webnews {
-    my ($lang) = @_;
-
-    my $templates = load_data ();
+sub load_data {
 
-    my $html = '';
+   my $urls = get_apl_sources();
 
-    $html .= __("<b>Welcome</b> to the Proxmox Virtual Environment!");
-    $html .= "<br><br>";
-    $html .= __("For more information please visit our homepage at");
-    $html .= " <a href='http://www.proxmox.com' target='_blank'>www.proxmox.com</a>.";
+    my $list = {};
 
-    return $html if !$templates;
+    foreach my $aplurl (@$urls) {
 
-    # my $d = $templates->{'all'}->{"pve-web-news-$lang"} ||
-    my $d = $templates->{all}->{'pve-web-news'};
+       eval { 
 
-    return $html if !$d;
+           my $uri = URI->new($aplurl);
+           my $host = $uri->host();
+           read_aplinfo("$aplinfodir/$host", $list, $aplurl);
+       };
+       warn $@ if $@;
+    }
 
-    return $d->{description};
+    return $list;
 }
 
 1;