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;
{ name => 'ubcfailcnt' },
{ name => 'network' },
{ name => 'network_changes' },
+ { name => 'aplinfo' },
];
return $result;
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;
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 {
}
}
+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) = @_;
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})/;
$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 = $@;
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;
REST.pm \
OpenVZ.pm \
OpenVZMigrate.pm \
+ APLInfo.pm \
VZDump.pm
all: pvecfg.pm ${SUBDIRS}
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
--- /dev/null
+-----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-----
#!/usr/bin/perl -w
use strict;
-#use PVE::APLInfo;
+use PVE::Cluster;
+use PVE::APLInfo;
use PVE::SafeSyslog;
use IO::File;
use File::Find;
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 {
use strict;
use PVE::Cluster;
-#use PVE::APLInfo;
+use PVE::APLInfo;
if (scalar (@ARGV) != 1) {
print STDERR "usage: $0 CMD\n";
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";
+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
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
VERSION=2.0
PACKAGE=pve-manager
-PACKAGERELEASE=30
+PACKAGERELEASE=31
BINDIR=${DESTDIR}/usr/bin
PERLLIBDIR=${DESTDIR}/usr/share/perl5
srvstop: ['SRV', gettext('Stop') ],
srvrestart: ['SRV', gettext('Restart') ],
srvreload: ['SRV', gettext('Reload') ],
+ imgcopy: ['', gettext('Copy data') ],
+ download: ['', gettext('Download') ],
vzdump: ['', gettext('Backup') ]
},
+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'],
});
}
},
+ {
+ 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() {