From 2c27e4b7c76e0c591070ec5635aa016674d5380b Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Wed, 22 Apr 2015 10:49:30 +0200 Subject: [PATCH] lxc: implement startup and onboot option --- PVE/API2/Nodes.pm | 43 ++++++++++-- www/manager/Makefile | 1 + www/manager/lxc/Config.js | 5 ++ www/manager/lxc/Options.js | 139 +++++++++++++++++++++++++++++++++++++ 4 files changed, 181 insertions(+), 7 deletions(-) create mode 100644 www/manager/lxc/Options.js diff --git a/PVE/API2/Nodes.pm b/PVE/API2/Nodes.pm index f3289ba4..11919250 100644 --- a/PVE/API2/Nodes.pm +++ b/PVE/API2/Nodes.pm @@ -1199,12 +1199,22 @@ my $get_start_stop_list = sub { my $bootorder = LONG_MAX; - if ($d->{type} eq 'qemu') { + if ($d->{type} eq 'lxc') { + my $conf = PVE::LXC::load_config($vmid); + return if $autostart && !$conf->{'pve.onboot'}; + + if ($conf->{'pve.startup'}) { + $startup = PVE::JSONSchema::parse_startup($conf->{'pve.startup'}); + $startup->{order} = $bootorder if !defined($startup->{order}); + } else { + $startup = { order => $bootorder }; + } + } elsif ($d->{type} eq 'qemu') { my $conf = PVE::QemuServer::load_config($vmid); return if $autostart && !$conf->{onboot}; if ($conf->{startup}) { - $startup = PVE::QemuServer::parse_startup($conf->{startup}); + $startup = PVE::JSONSchema::parse_startup($conf->{startup}); $startup->{order} = $bootorder if !defined($startup->{order}); } else { $startup = { order => $bootorder }; @@ -1282,7 +1292,11 @@ __PACKAGE__->register_method ({ my $default_delay = 0; my $upid; - if ($d->{type} eq 'qemu') { + if ($d->{type} eq 'lxc') { + return if PVE::LXC::check_running($vmid); + print STDERR "Starting CT $vmid\n"; + $upid = PVE::API2::LXC->vm_start({node => $nodename, vmid => $vmid }); + } elsif ($d->{type} eq 'qemu') { $default_delay = 3; # to redruce load return if PVE::QemuServer::check_running($vmid, 1); print STDERR "Starting VM $vmid\n"; @@ -1307,7 +1321,11 @@ __PACKAGE__->register_method ({ } } } else { - print STDERR "Starting VM $vmid failed: status\n"; + if ($d->{type} eq 'lxc') { + print STDERR "Starting CT $vmid failed: $status\n"; + } elsif ($d->{type} eq 'qemu') { + print STDERR "Starting VM $vmid failed: status\n"; + } } }; warn $@ if $@; @@ -1323,7 +1341,13 @@ my $create_stop_worker = sub { my ($nodename, $type, $vmid, $down_timeout) = @_; my $upid; - if ($type eq 'qemu') { + if ($type eq 'lxc') { + return if !PVE::LXC::check_running($vmid); + my $timeout = defined($down_timeout) ? int($down_timeout) : 60; + print STDERR "Stopping CT $vmid (timeout = $timeout seconds)\n"; + $upid = PVE::API2::LXC->vm_shutdown({node => $nodename, vmid => $vmid, + timeout => $timeout, forceStop => 1 }); + } elsif ($type eq 'qemu') { return if !PVE::QemuServer::check_running($vmid, 1); my $timeout = defined($down_timeout) ? int($down_timeout) : 60*3; print STDERR "Stopping VM $vmid (timeout = $timeout seconds)\n"; @@ -1412,11 +1436,16 @@ my $create_migrate_worker = sub { my ($nodename, $type, $vmid, $target) = @_; my $upid; - if ($type eq 'qemu') { + if ($type eq 'lxc') { + my $online = PVE::LXC::check_running($vmid) ? 1 : 0; + print STDERR "Migrating CT $vmid\n"; + $upid = PVE::API2::LXC->migrate_vm({node => $nodename, vmid => $vmid, target => $target, + online => $online }); + } elsif ($type eq 'qemu') { my $online = PVE::QemuServer::check_running($vmid, 1) ? 1 : 0; print STDERR "Migrating VM $vmid\n"; $upid = PVE::API2::Qemu->migrate_vm({node => $nodename, vmid => $vmid, target => $target, - online => $online }); + online => $online }); } else { die "unknown VM type '$type'\n"; } diff --git a/www/manager/Makefile b/www/manager/Makefile index 6ad97bb2..6f3f95e1 100644 --- a/www/manager/Makefile +++ b/www/manager/Makefile @@ -143,6 +143,7 @@ JSSRC= \ lxc/Summary.js \ lxc/Network.js \ lxc/Resources.js \ + lxc/Options.js \ lxc/Config.js \ lxc/CreateWizard.js \ pool/StatusView.js \ diff --git a/www/manager/lxc/Config.js b/www/manager/lxc/Config.js index 977563cc..50699781 100644 --- a/www/manager/lxc/Config.js +++ b/www/manager/lxc/Config.js @@ -135,6 +135,11 @@ Ext.define('PVE.lxc.Config', { itemId: 'network', xtype: 'pveLxcNetworkView' }, + { + title: gettext('Options'), + itemId: 'options', + xtype: 'pveLxcOptions' + }, { title: gettext('Task History'), itemId: 'tasks', diff --git a/www/manager/lxc/Options.js b/www/manager/lxc/Options.js new file mode 100644 index 00000000..9ac81e6f --- /dev/null +++ b/www/manager/lxc/Options.js @@ -0,0 +1,139 @@ +/*jslint confusion: true */ +Ext.define('PVE.lxc.Options', { + extend: 'PVE.grid.ObjectGrid', + alias: ['widget.pveLxcOptions'], + + initComponent : function() { + var me = this; + var i; + + var nodename = me.pveSelNode.data.node; + if (!nodename) { + throw "no node name specified"; + } + + var vmid = me.pveSelNode.data.vmid; + if (!vmid) { + throw "no VM ID specified"; + } + + var caps = Ext.state.Manager.get('GuiCap'); + + var rows = { + onboot: { + header: gettext('Start at boot'), + defaultValue: '', + renderer: PVE.Utils.format_boolean, + editor: caps.vms['VM.Config.Options'] ? { + xtype: 'pveWindowEdit', + subject: gettext('Start at boot'), + items: { + xtype: 'pvecheckbox', + name: 'onboot', + uncheckedValue: 0, + defaultValue: 0, + fieldLabel: gettext('Start at boot') + } + } : undefined + }, + startup: { + header: gettext('Start/Shutdown order'), + defaultValue: '', + renderer: PVE.Utils.render_kvm_startup, + editor: caps.vms['VM.Config.Options'] && caps.nodes['Sys.Modify'] ? + 'PVE.qemu.StartupEdit' : undefined + }, + ostemplate: { + header: gettext('Template'), + defaultValue: 'no set' + }, + storage: { + header: gettext('Storage'), + defaultValue: 'no set' + }, + cpuunits: { + header: gettext('CPU units'), + defaultValue: '1024', + editor: caps.vms['VM.Config.CPU'] ? { + xtype: 'pveWindowEdit', + subject: gettext('CPU units'), + items: { + xtype: 'numberfield', + name: 'cpuunits', + fieldLabel: gettext('CPU units'), + minValue: 8, + maxValue: 500000, + allowBlank: false + } + } : undefined + } + }; + + var baseurl = 'nodes/' + nodename + '/lxc/' + vmid + '/config'; + + var reload = function() { + me.rstore.load(); + }; + + var sm = Ext.create('Ext.selection.RowModel', {}); + + var run_editor = function() { + var rec = sm.getSelection()[0]; + if (!rec) { + return; + } + + var rowdef = rows[rec.data.key]; + if (!rowdef.editor) { + return; + } + + var win; + if (Ext.isString(rowdef.editor)) { + win = Ext.create(rowdef.editor, { + pveSelNode: me.pveSelNode, + confid: rec.data.key, + url: '/api2/extjs/' + baseurl + }); + } else { + var config = Ext.apply({ + pveSelNode: me.pveSelNode, + confid: rec.data.key, + url: '/api2/extjs/' + baseurl + }, rowdef.editor); + win = Ext.createWidget(rowdef.editor.xtype, config); + win.load(); + } + + win.show(); + win.on('destroy', reload); + }; + + var edit_btn = new PVE.button.Button({ + text: gettext('Edit'), + disabled: true, + selModel: sm, + enableFn: function(rec) { + var rowdef = rows[rec.data.key]; + return !!rowdef.editor; + }, + handler: run_editor + }); + + Ext.applyIf(me, { + url: "/api2/json/nodes/" + nodename + "/lxc/" + vmid + "/config", + selModel: sm, + cwidth1: 150, + tbar: [ edit_btn ], + rows: rows, + listeners: { + itemdblclick: run_editor + } + }); + + me.callParent(); + + me.on('show', reload); + } +}); +