support more than 'local' storage for openvz.
It is now possible to use NFS or other directory type storages.
This commit is contained in:
parent
6ea2c67cb3
commit
bec1da7adb
PVE
www/manager
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user