support more than 'local' storage for openvz.

It is now possible to use NFS or other directory type storages.
This commit is contained in:
Dietmar Maurer 2011-11-07 12:35:38 +01:00
parent 6ea2c67cb3
commit bec1da7adb
7 changed files with 106 additions and 48 deletions

@ -87,16 +87,16 @@ __PACKAGE__->register_method({
}});
my $restore_openvz = sub {
my ($archive, $vmid, $force) = @_;
my ($private, $archive, $vmid, $force) = @_;
my $vzconf = PVE::OpenVZ::read_global_vz_config ();
my $conffile = PVE::OpenVZ::config_file($vmid);
my $cfgdir = dirname($conffile);
my $private = $vzconf->{privatedir};
$private =~ s/\$VEID/$vmid/;
my $root = $vzconf->{rootdir};
$root =~ s/\$VEID/$vmid/;
my $default_private = $vzconf->{privatedir};
$default_private =~ s/\$VEID/$vmid/;
print "you choose to force overwriting VPS config file, private and root directories.\n" if $force;
@ -112,8 +112,15 @@ my $restore_openvz = sub {
my $conf;
eval {
rmtree $private if -d $private;
rmtree $root if -d $root;
if ($force && -f $conffile) {
my $conf = PVE::OpenVZ::load_config($vmid);
my $oldprivate = $conf->{ve_private} ? $conf->{ve_private}->{value} : $default_private;
rmtree $oldprivate if -d $oldprivate;
my $oldroot = $conf->{ve_root} ? $conf->{ve_root}->{value} : $root;
rmtree $oldroot if -d $oldroot;
};
mkpath $private || die "unable to create private dir '$private'";
mkpath $root || die "unable to create private dir '$private'";
@ -191,6 +198,11 @@ __PACKAGE__->register_method({
type => 'string',
description => "Sets root password inside container.",
},
storage => get_standard_option('pve-storage-id', {
description => "Target storage.",
default => 'local',
optional => 1,
}),
force => {
optional => 1,
type => 'boolean',
@ -219,7 +231,18 @@ __PACKAGE__->register_method({
my $password = extract_param($param, 'password');
my $stcfg = cfs_read_file("storage.cfg");
my $storage = extract_param($param, 'storage') || 'local';
my $storage_cfg = cfs_read_file("storage.cfg");
my $scfg = PVE::Storage::storage_check_node($storage_cfg, $storage, $node);
raise_param_exc({ storage => "storage '$storage' does not support openvz root directories"})
if !$scfg->{content}->{rootdir};
my $private = PVE::Storage::get_private_dir($storage_cfg, $storage, $vmid);
PVE::Storage::activate_storage($storage_cfg, $storage);
my $conf = PVE::OpenVZ::parse_ovz_config("/tmp/openvz/$vmid.conf", $pve_base_ovz_config);
@ -245,7 +268,7 @@ __PACKAGE__->register_method({
$archive = '-';
} else {
if (PVE::Storage::parse_volume_id($ostemplate, 1)) {
$archive = PVE::Storage::path($stcfg, $ostemplate);
$archive = PVE::Storage::path($storage_cfg, $ostemplate);
} else {
raise_param_exc({ archive => "Only root can pass arbitrary paths." })
if $user ne 'root@pam';
@ -275,6 +298,7 @@ __PACKAGE__->register_method({
$conf->{ostemplate}->{value} = $archive;
$conf->{ostemplate}->{value} =~ s|^.*/||;
$conf->{ostemplate}->{value} =~ s/\.tar\.(gz|bz2)$//;
$conf->{ve_private}->{value} = $private;
}
my $rawconf = PVE::OpenVZ::generate_raw_config($pve_base_ovz_config, $conf);
@ -282,14 +306,14 @@ __PACKAGE__->register_method({
PVE::Cluster::check_cfs_quorum();
my $realcmd = sub {
&$restore_openvz($archive, $vmid, $param->{force});
&$restore_openvz($private, $archive, $vmid, $param->{force});
PVE::Tools::file_set_contents($basecfg_fn, $rawconf)
if !$param->{restore};
# hack: vzctl '--userpasswd' starts the CT, but we want
# to avoid that for create
PVE::OpenVZ::set_rootpasswd($vmid, $password) if defined($password);
PVE::OpenVZ::set_rootpasswd($private, $password) if defined($password);
};
return $rpcenv->fork_worker($param->{restore} ? 'vzrestore' : 'vzcreate',

@ -197,7 +197,7 @@ sub vmstatus {
if (my $fh = IO::File->new ("/proc/mounts", "r")) {
while (defined (my $line = <$fh>)) {
if ($line =~ m|^/var/lib/vz/private/(\d+)\s+/var/lib/vz/root/|) {
if ($line =~ m|/private/(\d+)\s+/var/lib/vz/root/\d+\s|) {
$list->{$1}->{status} = 'mounted' if defined($list->{$1});
}
}
@ -219,7 +219,7 @@ sub vmstatus {
if (my $fh = IO::File->new ("/proc/vz/vzquota", "r")) {
while (defined (my $line = <$fh>)) {
if ($line =~ m|^(\d+):\s+/var/lib/vz/private/\d+$|) {
if ($line =~ m|^(\d+):\s+\S+/private/\d+$|) {
my $vmid = $1;
my $d = $list->{$vmid};
if ($d && defined($d->{status})) {
@ -1173,16 +1173,13 @@ sub replacepw {
}
sub set_rootpasswd {
my ($vmid, $opt_rootpasswd) = @_;
my ($privatedir, $opt_rootpasswd) = @_;
my $vmdir = $global_vzconf->{privatedir};
$vmdir =~ s/\$VEID/$vmid/;
my $pwfile = "$vmdir/etc/passwd";
my $pwfile = "$privatedir/etc/passwd";
return if ! -f $pwfile;
my $shadow = "$vmdir/etc/shadow";
my $shadow = "$privatedir/etc/shadow";
if ($opt_rootpasswd !~ m/^\$/) {
my $time = substr (Digest::SHA1::sha1_base64 (time), 0, 8);

@ -564,6 +564,8 @@ Ext.define('PVE.Utils', { statics: {
cta.push('Templates');
} else if (ct === 'iso') {
cta.push('ISO');
} else if (ct === 'rootdir') {
cta.push('Containers');
}
});

@ -5,12 +5,12 @@ Ext.define('PVE.form.ContentTypeSelector', {
initComponent: function() {
var me = this;
me.data = [
['images', 'Images'],
['iso', 'ISO'],
['vztmpl', 'Templates'],
['backup', 'Backups']
];
me.data = [];
var cts = ['images', 'iso', 'vztmpl', 'backup', 'rootdir'];
Ext.Array.each(cts, function(ct) {
me.data.push([ct, PVE.Utils.format_content_types(ct)]);
});
me.callParent();
}

@ -80,16 +80,23 @@ Ext.define('PVE.grid.BackupView', {
text: 'Restore',
disabled: true,
selModel: sm,
confirmMsg: function(rec) {
return 'Are you sure you want to restore from "' + rec.data.volid + '"? ' +
'This will permanently erase current VM data.';
},
enableFn: function(rec) {
return !!rec;
},
handler: function(b, e, rec) {
var volid = rec.data.volid;
var win = Ext.create('PVE.window.Restore', {
nodename: nodename,
vmid: vmid,
volid: rec.data.volid,
volidText: PVE.Utils.render_storage_content(rec.data.volid, {}, rec),
vmtype: vmtype
});
win.show();
win.on('destroy', reload);
return;
var url;
var params = {
vmid: vmid,

@ -20,6 +20,14 @@ Ext.define('PVE.openvz.CreateWizard', {
]
});
var storagesel = Ext.create('PVE.form.StorageSelector', {
name: 'storage',
fieldLabel: 'Storage',
storageContent: 'rootdir',
autoSelect: true,
allowBlank: false
});
var tmplsel = Ext.create('PVE.form.FileSelector', {
name: 'ostemplate',
storageContent: 'vztmpl',
@ -53,6 +61,7 @@ Ext.define('PVE.openvz.CreateWizard', {
change: function(f, value) {
tmplsel.setStorage('local', value);
bridgesel.setNodename(value);
storagesel.setNodename(value);
}
}
},
@ -72,6 +81,7 @@ Ext.define('PVE.openvz.CreateWizard', {
}
],
column2: [
storagesel,
{
xtype: 'textfield',
inputType: 'password',

@ -42,9 +42,10 @@ Ext.define('PVE.window.Restore', {
},
storagesel,
{
xtype: 'pveVMIDSelector',
xtype: me.vmid ? 'displayfield' : 'pveVMIDSelector',
name: 'vmid',
value: PVE.data.ResourceStore.findNextVMID(),
fieldLabel: 'VM ID',
value: me.vmid || PVE.data.ResourceStore.findNextVMID(),
validateExists: false
}
]
@ -56,6 +57,26 @@ Ext.define('PVE.window.Restore', {
submitBtn.setDisabled(!valid);
});
var doRestore = function(url, params) {
PVE.Utils.API2Request({
url: url,
params: params,
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();
}
});
};
var submitBtn = Ext.create('Ext.Button', {
text: 'Restore',
handler: function(){
@ -64,36 +85,33 @@ Ext.define('PVE.window.Restore', {
var params = {
storage: storage,
vmid: values.vmid
vmid: me.vmid ? me.vmid : values.vmid,
force: me.vmid ? 1 : 0
};
if (me.vmtype === 'openvz') {
url = '/nodes/' + me.nodename + '/openvz';
params.ostemplate = me.volid;
params.restore = 1;
} else if (me.vmtype === 'qemu') {
url = '/nodes/' + me.nodename + '/qemu';
params.archive = me.volid;
} else {
throw 'unknown VM type';
}
PVE.Utils.API2Request({
url: url,
params: params,
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();
}
});
if (me.vmid) {
var msg = 'Are you sure you want to restore this VM"? ' +
'This will permanently erase current VM data.';
Ext.Msg.confirm('Confirmation', msg, function(btn) {
if (btn !== 'yes') {
return;
}
doRestore(url, params);
});
} else {
doRestore(url, params);
}
}
});