[! use strict; use PVE::pvecfg; use PVE::I18N; use PVE::ConfigServer; use PVE::HTMLTable; use PVE::Config; use PVE::Cluster; use PVE::HTMLForm; use PVE::HTMLUtils; use PVE::QemuServer; !] [- use strict; sub html_table_line { my ($v1, $v2, $v3, $v4) = @_; $v1 = " " if !$v1; $v2 = " " if !$v2; $v3 = " " if !$v3; $v4 = " " if !$v4; my $html = ''; $html .= "$v1$v2"; $html .= "$v3$v4\n"; return $html; } my @disks = PVE::QemuServer::disknames(); sub device_list { my ($conf, $disktype) = @_; my $devsel; foreach my $ds (@disks) { next if $ds !~ m/^$disktype\d+$/; next if defined ($conf->{$ds}); my $devinfo = PVE::QemuServer::disk_devive_info ($ds); push @$devsel, [ $ds, $devinfo->{desc} ]; } $devsel = [[ '', sprintf (__("no %s devices available"), $disktype)]] if !$devsel; return $devsel; } my $form = PVE::HTMLForm->new (\%fdat); my $out = ''; my $cinfo = $fdat{__cinfo}; my $veid = $fdat{veid}; my $cid = $fdat{cid}; my $vminfo = PVE::Cluster::load_vmconfig ($cinfo, $cid, $veid, 'qemu'); my $status = $vminfo->{vzlist}->{"VEID_$veid"}->{status}; my $vmconf = $vminfo->{config}; my $ni = $vminfo->{ni}; my $medialist = PVE::Config::get_media_list(); $medialist = [ 'none', @$medialist ]; if ($udat{action}) { my $data = $fdat{aa}; if (($udat{action} eq 'deldisk') || ($udat{action} eq 'delcdrom')) { eval { my $settings = { $data => '' }; my $conn = PVE::ConfigClient::connect (); $conn->vmconfig_set ($udat{auth_username}, $cid, $veid, 'qemu', $settings)->result; }; if ($@) { $udat{popup_error} = $@; } } elsif (($udat{action} eq 'delunused')) { eval { my $conn = PVE::ConfigClient::connect (); $conn->qemu_unlink_disk ($udat{auth_username}, $cid, $veid, $data)->result; }; if ($@) { $udat{popup_error} = $@; } } elsif ($udat{action} eq 'delnic') { foreach my $i (0 .. 9, 'u') { my $vlan = "vlan$i"; my $cc = $vmconf->{$vlan}; next if !$cc; my $net = PVE::QemuServer::parse_vlan ($cc); next if !$net || !$net->{nics}; my $na = []; my $found = 0; foreach my $nic (@{$net->{nics}}) { if (!$nic->{macaddr} || ($nic->{macaddr} ne $data)) { push @$na, $nic; } else { $found = 1; } } if ($found) { $net->{nics} = $na; $cc = PVE::QemuServer::print_vlan ($net); my $settings = { $vlan => $cc }; eval { my $conn = PVE::ConfigClient::connect (); $conn->vmconfig_set ($udat{auth_username}, $cid, $veid, 'qemu', $settings)->result; }; $udat{popup_error} = $@ if $@; last; } } } print OUT $out; return; } if ($form->action =~ m/^setcdrom-(\S+)/) { my $dev = $1; my $value = $fdat{"cdrom-$dev"}; my $settings = { $dev => $value }; eval { my $conn = PVE::ConfigClient::connect (); $conn->vmconfig_setcdrom ($udat{auth_username}, $cid, $veid, $settings)->result; }; $udat{popup_error} = $@ if $@; } elsif ($form->action eq 'add') { if ($fdat{itype} eq 'disk') { if (!$fdat{unuseddevice}) { $udat{popup_error} = __("Please select a device"); } else { my $settings = { $fdat{unuseddevice} => $fdat{unused} }; eval { my $conn = PVE::ConfigClient::connect (); $conn->vmconfig_set ($udat{auth_username}, $cid, $veid, 'qemu', $settings)->result; }; if ($@) { $udat{popup_error} = $@; } else { $udat{redirect} = $fdat{__uri}; } } } elsif ($fdat{itype} eq 'cdrom') { if (!$fdat{device}) { $udat{popup_error} = __("Please select a device"); } else { my $settings = { $fdat{device} => "$fdat{cdrom},media=cdrom" }; eval { my $conn = PVE::ConfigClient::connect (); $conn->vmconfig_set ($udat{auth_username}, $cid, $veid, 'qemu', $settings)->result; }; if ($@) { $udat{popup_error} = $@; } else { $udat{redirect} = $fdat{__uri}; } } } else { delete ($fdat{edit}); } } elsif ($form->action eq 'create') { if ($fdat{itype} eq 'nic') { my $vlan = $fdat{bridge} || 'vlan0'; my $cc = $vmconf->{$vlan}; my $mac = PVE::QemuServer::random_ether_addr(); my $network = "$fdat{model}=$mac"; $cc = $cc ? "$cc,$network" : $network; my $settings = { $vlan => $cc }; eval { my $conn = PVE::ConfigClient::connect (); $conn->vmconfig_set ($udat{auth_username}, $cid, $veid, 'qemu', $settings)->result; }; if ($@) { $udat{popup_error} = $@; } else { $udat{redirect} = $fdat{__uri}; } } elsif ($fdat{itype} eq 'disk') { if (!$fdat{device}) { $udat{popup_error} = __("Please select a device"); } else { eval { # fixme: check size my $settings = { $fdat{device} => $fdat{hdsize} }; my $conn = PVE::ConfigClient::connect (); $conn->vmconfig_set ($udat{auth_username}, $cid, $veid, 'qemu', $settings)->result; }; if ($@) { $udat{popup_error} = $@; } else { $udat{redirect} = $fdat{__uri}; } } } else { delete ($fdat{edit}); } } if ($fdat{edit} == 2) { $out .= $form->create_header($fdat{__uri}); if ($fdat{itype} eq 'disk') { my $devsel1 = device_list ($vmconf, $fdat{disktype} || 'ide'); my $html = ''; my $dtypes = [['ide', 'IDE'], ['scsi', 'SCSI'], ['virtio', 'VIRTIO']]; $html .= html_table_line (__("Disk space") . ' (GB):', $form->create_element ('hdsize', 'text', $fdat{hdsize} || 32), __("Bus") . ':', $form->create_element ('disktype', 'dynamicdropdown', $fdat{disktype}, $dtypes)); $html .= html_table_line ('', '', __("Device") . ':', $form->create_element ('device', 'dropdown', $fdat{device}, $devsel1)); $html .= "

" . $form->create_cmdbutton ('create'); $out .= PVE::HTMLUtils::create_statusframe (undef, __("Create a new virtual disk"), undef, $html); my $di = $vmconf->{diskinfo} || {}; my $unused; my $ddown; foreach my $ds (keys %$di) { next if $ds !~ m/^unused\d+$/; push @$unused, $di->{$ds}; push @$ddown, [ $di->{$ds}->{file}, "$di->{$ds}->{file} ($di->{$ds}->{disksize}GB)" ]; } if ($unused) { $out .= "
\n"; my $devsel2 = device_list ($vmconf, $fdat{unuseddisktype} || 'ide'); my $html = ''; $html .= html_table_line (__("Existing Disks"), $form->create_element ('unused', 'dropdown', $fdat{unused}, $ddown), __("Bus") . ':', $form->create_element ('unuseddisktype', 'dynamicdropdown', $fdat{unuseddisktype}, $dtypes)); $html .= html_table_line ('', '', __("Device"), $form->create_element ('unuseddevice', 'dropdown', $fdat{unuseddevice}, $devsel2)); $html .= "

" . $form->create_cmdbutton ('add'); $out .= PVE::HTMLUtils::create_statusframe (undef, __("Use an existing virtual disk"), undef, $html); } } elsif ($fdat{itype} eq 'cdrom') { my $devsel1 = device_list ($vmconf, $fdat{disktype} || 'ide'); my $dtypes = [['ide', 'IDE'], ['scsi', 'SCSI']]; my $html = ''; $html .= html_table_line (__("CDROM") . ':', $form->create_element ('cdrom', 'dropdown', $fdat{cdrom} || 'none', $medialist), __("Bus") . ':', $form->create_element ('disktype', 'dynamicdropdown', $fdat{disktype}, $dtypes)); $html .= html_table_line ('', '', __("Device"), $form->create_element ('device', 'dropdown', $fdat{device}, $devsel1)); $html .= "

" . $form->create_cmdbutton ('add'); $out .= PVE::HTMLUtils::create_statusframe (undef, __("Add a CD-ROM drive"), undef, $html); } elsif ($fdat{itype} eq 'nic') { my $html = ""; my $nics = PVE::QemuServer::nic_models (); my $bridges = PVE::Utils::get_bridges (); my $brg; foreach my $bn (@$bridges) { if ($bn =~ m/^vmbr([0-9])$/) { push @$brg, [ "vlan$1", "vmbr$1" ]; } } push @$brg, [ "vlanu", "NAT (User Mode Network)" ]; $html .= html_table_line (__("Model"), $form->create_element ('model', 'dropdown', $fdat{model}, $nics), __("Bridge") . ':', $form->create_element ('bridge', 'dropdown', 'vmbr0', $brg)); $html .= "

" . $form->create_cmdbutton ('create'); $out .= PVE::HTMLUtils::create_statusframe (undef, __("Add a network card"), undef, $html); } $out .= $form->create_element("edit", "hidden", $fdat{edit}); $out .= $form->create_element("itype", "hidden", $fdat{itype}); $out .= $form->create_footer(); print OUT $out; return; } $out .= $form->create_header($fdat{__uri}); my $ddown = PVE::HTMLDropDown->new (); $ddown->add_item ("menu0", "?itype=disk&edit=2", __("Add a hard disk")); $ddown->add_item ("menu0", "?itype=nic&edit=2", __("Add an ethernet device")); $ddown->add_item ("menu0", "?itype=cdrom&edit=2", __("Add a CD-ROM drive")); $ddown->add_item ('menudisk', "?action=deldisk", __('Delete')); $ddown->add_item ('menuunused', "?action=delunused", __('Delete from disk')); $ddown->add_item ('menunic', "?action=delnic", __('Delete')); $ddown->add_item ('menucdrom', "?action=delcdrom", __('Delete')); $out .= $ddown->out_dropdown_menu ("menu0"); $out .= "

" . $ddown->out_symbol("menu0", "iarrdown") . " " . __("Hardware device list for VM $veid") . "


"; $out .= $ddown->out_dropdown_menu ("menudisk"); $out .= $ddown->out_dropdown_menu ("menuunused"); $out .= $ddown->out_dropdown_menu ("menunic"); $out .= $ddown->out_dropdown_menu ("menucdrom"); my $header_disk = ['1', '20px', ' ', '1', '10px', ' ', '1', '100px', __("Bus"), '1', '100px', __('Device'), '1', '100px', __('Size'), '1', '360px', __("File name")]; my $table = PVE::HTMLTable->new ([]); $table->add_headline ($header_disk); my $found = 0; foreach my $ds (@disks) { next if !defined ($vmconf->{$ds}); my $disk = PVE::QemuServer::parse_drive ($ds, $vmconf->{$ds}); next if !$disk || PVE::QemuServer::drive_is_cdrom ($disk); my $size = '-'; if ($vmconf->{diskinfo} && $vmconf->{diskinfo}->{$ds}) { $size = $vmconf->{diskinfo}->{$ds}->{disksize}; } my $devinfo = PVE::QemuServer::disk_devive_info ($ds); my $menu = $ddown->out_symbol ('menudisk', '', "&aa=$ds"); $table->add_row ('' ,$menu, '', uc($devinfo->{bus}), $devinfo->{desc}, "${size}GB", $disk->{file}); $found = 1; } my $html; if ($found) { $html = $table->out_table (); } my $header_unused = ['1', '20px', ' ', '1', '10px', ' ', '1', '100px', __('Size'), '1', '560px', __("Unused disk images"), ]; $table = PVE::HTMLTable->new ([]); $table->add_headline ($header_unused); my $ufound = 0; my $uhtml = "
"; my $di = $vmconf->{diskinfo} || {}; foreach my $ds (keys %$di) { next if $ds !~ m/^unused\d+$/; $ufound = 1; my $file = $di->{$ds}->{file}; my $menu = $ddown->out_symbol ('menuunused', '', "&aa=$file"); $table->add_row ('' ,$menu, '', "$di->{$ds}->{disksize}GB", $file); } $uhtml .= $table->out_table (); $html .= $uhtml if $ufound; if (!$found && !$ufound) { $html = "no devices"; } $out .= PVE::HTMLUtils::create_statusframe (undef, __("Hard disks"), undef, $html); my $header_cdrom = ['1', '20px', ' ', '1', '10px', ' ', '1', '100px', __("Bus"), '1', '100px', __('Device'), '1', '100px', ' ', '1', '300px', __("Media"), '1', '60px', ' ', ]; my $table = PVE::HTMLTable->new ([]); $table->add_headline ($header_cdrom); $found = 0; foreach my $ds (@disks) { next if !defined ($vmconf->{$ds}); my $disk = PVE::QemuServer::parse_drive ($ds, $vmconf->{$ds}); next if !PVE::QemuServer::drive_is_cdrom ($disk); my $menu = $ddown->out_symbol ('menucdrom', '', "&aa=$ds"); my $devinfo = PVE::QemuServer::disk_devive_info ($ds); my $key = "cdrom-$ds"; my $v = defined ($fdat{$key}) ? $fdat{$key} : $disk->{file} || 'none'; my $el = $form->create_element ($key, 'dropdown', $v, $medialist, 300); my $cmd = $form->create_cmdbutton ("setcdrom-$ds", __('apply')); $table->add_row ('' ,$menu, '', uc($devinfo->{bus}), $devinfo->{desc}, '', $el, $cmd); $found = 1; } if ($found) { $html = $table->out_table (); } else { $html = "no devices"; } $out .= '
'; $out .= PVE::HTMLUtils::create_statusframe (undef, __("CD-ROM drives"), undef, $html); my $header_nic = ['1', '20px', ' ', '1', '10px', ' ', '1', '100px', __("Model"), '1', '100px', __('Bridge'), '1', '100px', ' ', '1', '360px', __("MAC address")]; my $table = PVE::HTMLTable->new ([]); $table->add_headline ($header_nic); $found = 0; foreach my $id (0 .. 9, 'u') { next if !defined ($vmconf->{"vlan$id"}); my $net = PVE::QemuServer::parse_vlan ($vmconf->{"vlan$id"}); next if !$net || !$net->{nics}; my $brname = $id eq 'u' ? "NAT" : "vmbr$id"; foreach my $nic (sort { $a->{model} cmp $b->{model} } @{$net->{nics}}) { next if !$nic->{model} || !$nic->{macaddr}; my $menu = $ddown->out_symbol ('menunic', '', "&aa=$nic->{macaddr}"); $table->add_row ('' ,$menu, '', $nic->{model}, $brname, '', $nic->{macaddr}); $found = 1; } } if ($found) { $html = $table->out_table (); } else { $html = "no devices"; } $out .= '
'; $out .= PVE::HTMLUtils::create_statusframe (undef, __("Ethernet devices"), undef, $html); $out .= $form->create_footer(); print OUT $out; return; -]