Commit 82f9a5d7 authored by Dietmar Maurer's avatar Dietmar Maurer

implement template download

Also added turnkeylinux.com
parent af79261b
......@@ -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;
......
This diff is collapsed.
......@@ -10,6 +10,7 @@ PERLSOURCE = \
REST.pm \
OpenVZ.pm \
OpenVZMigrate.pm \
APLInfo.pm \
VZDump.pm
all: pvecfg.pm ${SUBDIRS}
......
......@@ -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
......
-----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;
......@@ -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 {
......
......@@ -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";
......
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
......
......@@ -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
......
......@@ -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
......
......@@ -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') ]
},
......
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() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment