]> git.proxmox.com Git - pve-manager.git/commitdiff
implement template download
authorDietmar Maurer <dietmar@proxmox.com>
Tue, 21 Feb 2012 10:42:32 +0000 (11:42 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Tue, 21 Feb 2012 10:45:30 +0000 (11:45 +0100)
Also added turnkeylinux.com

12 files changed:
PVE/API2/Nodes.pm
PVE/APLInfo.pm
PVE/Makefile
aplinfo/Makefile
aplinfo/release@turnkeylinux.com.pubkey [new file with mode: 0644]
bin/cron/daily/pve
bin/pveam
debian/changelog.Debian
debian/postinst
defines.mk
www/manager/Utils.js
www/manager/storage/ContentView.js

index d8605e10f75b51234780944c90c45ca71416704e..a819a815898c6049ec8c5d56804981f06f1cf878 100644 (file)
@@ -9,14 +9,16 @@ use PVE::pvecfg;
 use PVE::Tools;
 use PVE::ProcFSTools;
 use PVE::SafeSyslog;
-use PVE::Cluster;
+use PVE::Cluster qw(cfs_read_file);
 use PVE::INotify;
 use PVE::Exception qw(raise raise_perm_exc);
 use PVE::RESTHandler;
 use PVE::RPCEnvironment;
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::AccessControl;
+use PVE::Storage;
 use PVE::OpenVZ;
+use PVE::APLInfo;
 use PVE::API2::Services;
 use PVE::API2::Network;
 use PVE::API2::Tasks;
@@ -111,6 +113,7 @@ __PACKAGE__->register_method ({
            { name => 'ubcfailcnt' },
            { name => 'network' },
            { name => 'network_changes' },
+           { name => 'aplinfo' },
            ];
 
        return $result;
@@ -746,6 +749,148 @@ __PACKAGE__->register_method({
        return undef;
     }});
 
+__PACKAGE__->register_method({
+    name => 'aplinfo', 
+    path => 'aplinfo', 
+    method => 'GET',
+    permissions => {
+       user => 'all',
+    },
+    description => "Get list of appliances.",
+    proxyto => 'node',
+    parameters => {
+       additionalProperties => 0,
+       properties => {
+           node => get_standard_option('pve-node'),
+       },
+    },
+    returns => {
+       type => 'array',
+       items => {
+           type => "object",
+           properties => {},
+       },
+    },
+    code => sub {
+       my ($param) = @_;
+
+       my $res = [];
+
+       my $list = PVE::APLInfo::load_data();
+
+       foreach my $template (keys %{$list->{all}}) {
+           my $pd = $list->{all}->{$template};
+           next if $pd->{'package'} eq 'pve-web-news';
+           push @$res, $pd;
+       }
+
+       return $res;
+    }});
+
+__PACKAGE__->register_method({
+    name => 'apl_download', 
+    path => 'aplinfo', 
+    method => 'POST',
+    permissions => {
+       check => ['perm', '/storage/{storage}', ['Datastore.AllocateTemplate']],
+    },
+    description => "Download appliance templates.",
+    proxyto => 'node',
+    protected => 1,
+    parameters => {
+       additionalProperties => 0,
+       properties => {
+           node => get_standard_option('pve-node'),
+           storage => get_standard_option('pve-storage-id'),
+           template => { type => 'string', maxLength => 255 },
+       },
+    },
+    returns => { type => "string" },
+    code => sub {
+       my ($param) = @_;
+
+       my $rpcenv = PVE::RPCEnvironment::get();
+
+       my $user = $rpcenv->get_user();
+
+       my $node = $param->{node};
+
+       my $list = PVE::APLInfo::load_data();
+
+       my $template = $param->{template};
+       my $pd = $list->{all}->{$template};
+
+       raise_param_exc({ template => "no such template"}) if !$pd;
+
+       my $cfg = cfs_read_file("storage.cfg");
+       my $scfg = PVE::Storage::storage_check_enabled($cfg, $param->{storage}, $node);
+
+       die "cannot download to storage type '$scfg->{type}'" 
+           if !($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs');
+
+       die "unknown template type '$pd->{type}'\n" if $pd->{type} ne 'openvz';
+
+       die "storage '$param->{storage}' does not support templates\n" 
+           if !$scfg->{content}->{vztmpl};
+
+       my $src = $pd->{location};
+       my $tmpldir = PVE::Storage::get_vztmpl_dir($cfg, $param->{storage});
+       my $dest = "$tmpldir/$template";
+       my $tmpdest = "$tmpldir/${template}.tmp.$$";
+
+       my $worker = sub  {
+           my $upid = shift;
+           
+           print "starting template download from: $src\n";
+           print "target file: $dest\n";
+
+           eval {
+
+               if (-f $dest) {
+                   my $md5 = (split (/\s/, `md5sum '$dest'`))[0];
+
+                   if ($md5 && (lc($md5) eq lc($pd->{md5sum}))) {
+                       print "file already exists $md5 - no need to download\n";
+                       return;
+                   }
+               }
+
+               local %ENV;
+               my $dccfg = PVE::Cluster::cfs_read_file('datacenter.cfg');
+               if ($dccfg->{http_proxy}) {
+                   $ENV{http_proxy} = $dccfg->{http_proxy};
+               }
+
+               my @cmd = ('/usr/bin/wget', '--progress=dot:mega', '-O', $tmpdest, $src);
+               if (system (@cmd) != 0) {
+                   die "download failed - $!\n";
+               }
+
+               my $md5 = (split (/\s/, `md5sum '$tmpdest'`))[0];
+               
+               if (!$md5 || (lc($md5) ne lc($pd->{md5sum}))) {
+                   die "wrong checksum: $md5 != $pd->{md5sum}\n";
+               }
+
+               if (system ('mv', $tmpdest, $dest) != 0) {
+                   die "unable to save file - $!\n";
+               }
+           };
+           my $err = $@;
+
+           unlink $tmpdest;
+
+           if ($err) {
+               print "\n";
+               die $err if $err;
+           }
+
+           print "download finished\n";
+       };
+
+       return $rpcenv->fork_worker('download', undef, $user, $worker);
+    }});
+
 package PVE::API2::Nodes;
 
 use strict;
index 26fd791ec834487b8164926b1f047d0ce2c3d970..5d260a38d1a988736ef9d93887e00374a1d39f3d 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,91 @@ sub logmsg {
     }
 }
 
+sub read_aplinfo {
+    my ($filename, $list, $source, $update) = @_;
+
+    my $fh = IO::File->new("<$filename") ||
+       die "unable to open file '$filename' - $!\n";
+
+    local $/ = "";
+
+    eval { 
+       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)$/) {
+                       $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 {
+                   $template = "$res->{os}-$res->{package}_$res->{version}_i386.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;         
+           }
+       }
+    };
+    my $err = $@;
+
+    close($fh);
+
+    die $err if $err;
+    
+    return $list;
+}
+
 sub url_get {
     my ($ua, $url, $file, $logfh) = @_;
 
@@ -59,64 +151,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 +201,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 +229,90 @@ 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) = @_;
+sub load_data {
 
-    my $templates = load_data ();
+    my $filename = "$aplinfodir/download.proxmox.com";
+    if (! -f $filename) {
+       mkdir $aplinfodir;
+       system("cp /usr/share/doc/pve-manager/aplinfo.dat $filename");
+    }
 
-    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;
index 3a6608407ce8eba54cf76f57c856fd63c610d59f..bb3b3c726f4596fea51d8b14bc29ffacb3dc1044 100644 (file)
@@ -10,6 +10,7 @@ PERLSOURCE =                  \
        REST.pm                 \
        OpenVZ.pm               \
        OpenVZMigrate.pm        \
+       APLInfo.pm              \
        VZDump.pm
 
 all: pvecfg.pm ${SUBDIRS}
index 82049fbb4ac09fe592a1232f0d445b18d1db40f7..b416572c938f10f2628688a82dc3f41da37c6a58 100644 (file)
@@ -7,6 +7,7 @@ all:
 install: aplinfo.dat support@proxmox.com.pubkey
        install -D -m 0644 aplinfo.dat ${DESTDIR}${DOCDIR}/aplinfo.dat
        install -D -m 0644 support@proxmox.com.pubkey ${DESTDIR}${DOCDIR}/support@proxmox.com.pubkey
+       install -D -m 0644 release@turnkeylinux.com.pubkey ${DESTDIR}${DOCDIR}/release@turnkeylinux.com.pubkey
 
 .PHONY: distclean
 distclean: clean
diff --git a/aplinfo/release@turnkeylinux.com.pubkey b/aplinfo/release@turnkeylinux.com.pubkey
new file mode 100644 (file)
index 0000000..44f9ea3
--- /dev/null
@@ -0,0 +1,31 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+mQENBEilXh0BCADtICrXzrAP7Q5fFzAMrQYvpSrWn7+UUbmMn35fEpS9IzAbZSDX
+24nBG8LTuWDXqbmT0lqam/rkTrVQpZFeSimcZx1Y68iG+Iw6BJvK3XrfaCFUUeyy
++JTgHNr73N03jQ6LS/wkjCQQ3YLD4vrI+ti1bs24QOavnDad8oqYMbSDBhqeiOkE
+97THg0afEhxiq2C13SW5aHlSmGw0EulKGfa/0MmIFmmztE7Vz1qumbd75p6bheDK
+HhtdHz5L2zDOK0C98h6oYKBnEr+anfXRPgEQAs3qNm1zRcgjd9xyF3KKuRQZoTAK
+8kyYoFI09C+rPs7Cm438k7GSr4pHDWwb+GDBABEBAAG0NFR1cm5rZXkgTGludXgg
+UmVsZWFzZSBLZXkgPHJlbGVhc2VAdHVybmtleWxpbnV4LmNvbT6JARwEEAECAAYF
+AklrWbAACgkQbeyW07BngNkbzAf/XkA+TMcWQ4i0/Epi4zEp9Fb+gtPZnzvHFqcG
+lb/l79hcxiw/JfadOa+BqdKGmTyPreu/yLAPE2GIc9Z8cMsiTTWu1ILy1TmXYw2e
+Zx8AmpqeV4Jzn4ygLuimNpyguCIRhSnyjvtXOX2Jf2ZpwbNT6rD3gmAJca3onVLu
+cTGpJX1JWmmnc8aXmUzX7KjC/4EGg0ShxGC00WCaQnaHp1QDQ0rWMm3la/wyZj/1
+27n69PMjjfcpDow1jJ45QPykRxV/gRnS++ymPHkQFERACYtIS9MAbzOXwCoLprci
+J9lOEIU/fc0wzmnZaRenLzmh/hhLkCKw30ByRECD89n7kVE7uYkBHAQTAQIABgUC
+SKVgagAKCRDA8gC1FJezDGJAB/9DvOR3ZcW6vWoV9BwSOjgJTDKOePQ6C4wUOHF1
+sDu0EKQTzJhD4/ca0KN7NiAx9D4I+2FQS9ZnqyIATWGqNeMdSgnuo5iq79eQ4pZn
+Quor2hzrzeHdoPZHDRt7CzChMztXg8CwipPhzTrXBaWKQuomxpvt93RgQS+Ktt5S
+rojoEDj1/lCgfm4D/XnVns31h5RQ9q+YMpbGOOVTCW1oxo74X++n8R1C4DuX0sxv
+Vqyu28lwOrLcbV4Ur7xjAjSjXM4q1cX/Bxt1KeLtVR8FTK+6TNQoZNycx46Yw2G4
+38PPVrFmvunNBgB30iO08SUZ9mULU47BQcZ8WdqrewzaQkwEiQE8BBMBAgAmBQJI
+pV4dAhsDBQkcMgSABgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQhcJelaFuuU3N
++Qf/fhpcQROYB00dU7E0LJ3iP5cwUALJebbmKlNmoCNoqskZ4JS+hvy4AJmxsf2M
+UdlMUTL8TwOxyfNDj4kfXv4phNw4X47TwUU3OBXcQNpFf9em3zJG2WID8EesGX8Z
+nGsCpOWhwOiBo5LfrFqCaCet3gUXaRjmuVcUkEyHmFd0TyWljEhINCS9wqQk55TO
+juRigCGGEvxB8i6b4o64rVc6EVZizzLUzvXDgDOaqxSsYrKt34ezPgGpRQgy/HNF
+C6LTLFlxJvwG42YZETK3S1R1RAVZQ6II4pl8Et3iU8aFoot64zx+GnFI62/krcG6
+5ul/98lS4h1xGJfl6U0NIu8tjw==
+=DmER
+-----END PGP PUBLIC KEY BLOCK-----
index 69a188e979a3578f952380933db8347362305fbe..d083082a5498ee93bb04d366ece01750ed598005 100644 (file)
@@ -1,7 +1,8 @@
 #!/usr/bin/perl -w
 
 use strict;
-#use PVE::APLInfo;
+use PVE::Cluster;
+use PVE::APLInfo;
 use PVE::SafeSyslog;
 use IO::File;
 use File::Find;
@@ -9,14 +10,11 @@ use File::stat;
 
 initlog ('pvedailycron', 'daemon');
 
-# fixme: update APL info?
-#my $pvecfg = PVE::Config::read_file('pvecfg');
-#my $proxy = ($pvecfg && $pvecfg->{http_proxy}) ? $pvecfg->{http_proxy} : undef;
-
-## update appliance info
-#if (!PVE::APLInfo::update()) {
-#    syslog ('err', "update appliance info failed - see /var/log/pveam.log for details");
-#}
+my $dccfg = PVE::Cluster::cfs_read_file('datacenter.cfg');
+eval { PVE::APLInfo::update($dccfg->{http_proxy}); };
+if (my $err = $@) {
+   syslog ('err', "update appliance info failed - see /var/log/pveam.log for details");
+}
 
 sub cleanup_tasks {
 
index b85bb3a589b21dd48b502946829b9aa54810eb78..4f1309c3d0f83065bea5a9896491bf929595e691 100755 (executable)
--- a/bin/pveam
+++ b/bin/pveam
@@ -2,7 +2,7 @@
 
 use strict;
 use PVE::Cluster;
-#use PVE::APLInfo;
+use PVE::APLInfo;
 
 if (scalar (@ARGV) != 1) {
     print STDERR "usage: $0 CMD\n";
@@ -13,9 +13,8 @@ my $cmd = shift;
 
 if ($cmd eq 'update') {
     my $dccfg = PVE::Cluster::cfs_read_file('datacenter.cfg');
-    die "sorry, this is currently not implemented\n";
-    #exit (0) if PVE::APLInfo::update($dccfg->{http_proxy});
-    #print STDERR "update failed - see /var/log/pveam.log for details\n";
+    exit (0) if PVE::APLInfo::update($dccfg->{http_proxy});
+    print STDERR "update failed - see /var/log/pveam.log for details\n";
     exit (-1);
 } else {
     print STDERR "unknown CMD '$cmd'\n";
index 45f5f88edc26232cbc35083cc71c2e7c4edb3c55..a7dec2da31eebbac88d21f8ceb72d7beffe65439 100644 (file)
@@ -1,3 +1,11 @@
+pve-manager (2.0-31) unstable; urgency=low
+
+  * add template download GUI
+  
+  * include turnkey appliances in download list.
+
+ -- Proxmox Support Team <support@proxmox.com>  Tue, 21 Feb 2012 11:45:07 +0100
+
 pve-manager (2.0-30) unstable; urgency=low
 
   * add unmount button to openvz GUI
index d8b76bfe19cc21ec51363a0428e1fe4d0cc84922..0074ab766c28af17bb6db927b17502f9a0539e91 100755 (executable)
@@ -37,7 +37,8 @@ case "$1" in
 
     mkdir /etc/pve 2>/dev/null || true
 
-    test -e /var/lib/pve-manager/apl-available || cp /usr/share/doc/pve-manager/aplinfo.dat /var/lib/pve-manager/apl-available
+    # remove old APL dir
+    rm -rf /var/lib/pve-manager/apl-available
 
     if test -f /root/.forward; then
        if ! grep -q '|/usr/bin/pvemailforward' /root/.forward; then 
index 7036833a478d4ab04c13b5bccd650342bc13934f..6fbaa955543b6351737e16bd845560e15072854a 100644 (file)
@@ -2,7 +2,7 @@ RELEASE=2.0
 
 VERSION=2.0
 PACKAGE=pve-manager
-PACKAGERELEASE=30
+PACKAGERELEASE=31
 
 BINDIR=${DESTDIR}/usr/bin
 PERLLIBDIR=${DESTDIR}/usr/share/perl5
index c3a215dd7d9fc2bddd85a0fb9c26c840ae8fc35c..c063e9b52a20c429ba8bab0349b0cc2730a131f0 100644 (file)
@@ -396,6 +396,8 @@ Ext.define('PVE.Utils', { statics: {
        srvstop: ['SRV', gettext('Stop') ],
        srvrestart: ['SRV', gettext('Restart') ],
        srvreload: ['SRV', gettext('Reload') ],
+       imgcopy: ['', gettext('Copy data') ],
+       download: ['', gettext('Download') ],
        vzdump: ['', gettext('Backup') ]
     },
 
index 6e0ac65f2aa58e62025431a76c6cac31b9eb6bf5..515c2db1fda73e40bb08cb0adefc9b308a6435e8 100644 (file)
@@ -1,3 +1,146 @@
+Ext.define('PVE.grid.TemplateSelector', {
+    extend: 'Ext.grid.GridPanel',
+
+    alias: ['widget.pveTemplateSelector'],
+
+    initComponent : function() {
+       var me = this;
+
+       if (!me.nodename) {
+           throw "no node name specified";
+       }
+
+       var baseurl = "/nodes/" + me.nodename + "/aplinfo";
+       var store = new Ext.data.Store({
+           model: 'pve-aplinfo',
+           groupField: 'section',
+           proxy: {
+                type: 'pve',
+               url: '/api2/json' + baseurl
+           }
+       });
+
+       var sm = Ext.create('Ext.selection.RowModel', {});
+
+       var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
+            groupHeaderTpl: '{[ "Section: " + values.name ]} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
+       });
+
+       var reload = function() {
+           store.load();
+       };
+
+       PVE.Utils.monStoreErrors(me, store);
+
+       Ext.apply(me, {
+           store: store,
+           selModel: sm,
+           stateful: false,
+           viewConfig: {
+               trackOver: false
+           },
+           features: [ groupingFeature ],
+           columns: [
+               {
+                   header: gettext('Type'),
+                   width: 80,
+                   dataIndex: 'type'
+               },
+               {
+                   header: gettext('Package'),
+                   flex: 1,
+                   dataIndex: 'package'
+               },
+               {
+                   header: gettext('Version'),
+                   width: 80,
+                   dataIndex: 'version'
+               },
+               {
+                   header: gettext('Description'),
+                   flex: 1.5,
+                   dataIndex: 'headline'
+               }
+           ],
+           listeners: {
+               afterRender: reload
+           }
+       });
+
+       me.callParent();
+    }
+
+}, function() {
+
+    Ext.define('pve-aplinfo', {
+       extend: 'Ext.data.Model',
+       fields: [ 
+           'template', 'type', 'package', 'version', 'headline', 'infopage', 
+           'description', 'os', 'section'
+       ],
+       idProperty: 'template'
+    });
+
+});
+
+Ext.define('PVE.storage.TemplateDownload', {
+    extend: 'Ext.window.Window',
+    alias: ['widget.pveTemplateDownload'],
+
+    modal: true,
+
+    initComponent : function() {
+       /*jslint confusion: true */
+        var me = this;
+
+       var grid = Ext.create('PVE.grid.TemplateSelector', {
+           width: 600,
+           height: 400,
+           border: false,
+           autoScroll: true,
+           nodename: me.nodename
+       });
+
+       var sm = grid.getSelectionModel();
+
+       var submitBtn = Ext.create('PVE.button.Button', {
+           text: gettext('Download'),
+           disabled: true,
+           selModel: sm,
+           handler: function(button, event, rec) {
+               PVE.Utils.API2Request({
+                   url: '/nodes/' + me.nodename + '/aplinfo',
+                   params: { 
+                       storage: me.storage, 
+                       template: rec.data.template
+                   },
+                   method: 'POST',
+                   failure: function (response, opts) {
+                       Ext.Msg.alert('Error', response.htmlStatus);
+                   },
+                   success: function(response, options) {
+                       var upid = response.result.data;
+                       
+                       var win = Ext.create('PVE.window.TaskViewer', { 
+                           upid: upid
+                       });
+                       win.show();
+                       me.close();
+                   }
+               });
+           }
+       });
+
+        Ext.applyIf(me, {
+            title: gettext('Template download'),
+           items: grid,
+           buttons: [ submitBtn ]
+       });
+
+       me.callParent();
+    }
+});
+
 Ext.define('PVE.storage.Upload', {
     extend: 'Ext.window.Window',
     alias: ['widget.pveStorageUpload'],
@@ -279,6 +422,17 @@ Ext.define('PVE.storage.ContentView', {
                        });
                    }
                },
+               {
+                   text: gettext('Templates'),
+                   handler: function() {
+                       var win = Ext.create('PVE.storage.TemplateDownload', {
+                           nodename: nodename,
+                           storage: storage
+                       });
+                       win.show();
+                       win.on('destroy', reload);
+                   }
+               },
                {
                    text: gettext('Upload'),
                    handler: function() {