#!/usr/bin/env perl # # Copyright (c) 2019-2021 Mischa Peters # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # # vmm(4)/vmd(8) VM remove script for OpenBSD Amsterdam # 2020/05/25 version 2 - Perl again! :) # use 5.024; use strict; use warnings; use autodie; use Cwd qw(cwd); use User::pwent; # Get vmXX.txt from arguments if (! $ARGV[0]) { print STDERR "usage: $0 vmXX.txt\n"; exit 1; } my $vmid = $ARGV[0]; # fuction to parse _deploy.conf and vm*.txt files # all variables are stripped and added to either %vms or %conf sub get_variables { my ($hash_name, @files) = @_; my %hash; my $filename; my $vm_name; my $vm_number; for my $file (@files) { # When hash is 'vms' use the vm_name as key # Otherwise use 'conf' as key if ($hash_name eq "vms") { ($filename = $file) =~ s/.*\///; ($vm_name = $filename) =~ s/\.txt//; ($vm_number = $vm_name) =~ s/^vm//; $hash{$vm_name}{'vm_number'} = $vm_number; } open my $fh, "<", "$file"; while (my $row = <$fh>) { next if ($row =~ /^\s*($|#)/); chomp($row); (my $key, my $val) = split(/=/, $row, 2); if ($hash_name eq "vms") { ($hash{$vm_name}{$key} .= $val) =~ s/^"+|"+$//g; } else { ($hash{$hash_name}{$key} .= $val) =~ s/^"+|"+$//g; } } close $fh; } return %hash; } # function to create accounts on the host for vmctl(8) access sub remove_accounts { my %conf = %{$_[0]}; my %vms = %{$_[1]}; printf "userdel(8) user:\n"; for my $vm_name (sort keys %vms) { my $_instance = $vms{$vm_name}{'instance'} || $vm_name; my $_owner = $vms{$vm_name}{'owner'} || $vms{$vm_name}{'username'}; my $_group = $conf{'conf'}{'VMDUSERS'}; my $id = getpwnam("$_owner"); if ($id) { qx(/usr/sbin/userdel -r $_owner); printf "%16s %s account removed\n", $_instance, $_owner; qx(/usr/sbin/groupdel $_owner); printf "%16s %s group removed\n", $_instance, $_owner; } } } # function to create the disk image files for vmm(4)/vmd(8) sub backup_img_files { my %conf = %{$_[0]}; my %vms = %{$_[1]}; printf "vmm(4)/vmd(8) files:\n"; for my $vm_name (sort keys %vms) { my $_instance = $vms{$vm_name}{'instance'} || $vm_name; my $_disk_format = $vms{$vm_name}{'format'} || $conf{'conf'}{'FORMAT'}; my $_disk = $conf{'conf'}{'IMAGES'} . "/" . $_instance . "." . $_disk_format; my $_disk2 = $conf{'conf'}{'IMAGES'} . "/" . $_instance . "_extra." . $_disk_format if $vms{$vm_name}{'disk2'}; if (-e $_disk) { qx(mv $_disk $_disk-backup); printf "%16s %s mv(1) %s-backup\n", $_instance, $_disk, $_disk; } if ($_disk2) { if (-e $_disk2) { qx(mv $_disk2 $_disk2-backup); printf "%16s %s mv(1) $_disk2-backup\n", $_instance, $_disk2; } } } } sub backup_vm_files { my %conf = %{$_[0]}; my %vms = %{$_[1]}; printf "vmXX.txt file:\n"; for my $vm_name (sort keys %vms) { my $_instance = $vms{$vm_name}{'instance'} || $vm_name; my $filename = $conf{'conf'}{'VMS'} . "/" . $vmid; qx(cp $filename $filename-backup); printf "%16s %s cp(1) %s-backup\n", $_instance, $filename, $filename; qx(mv $filename $filename.free); printf "%16s %s mv(1) %s.free\n", $_instance, $filename, $filename; qx(chown -R mischa:mischa $filename-backup $filename.free); } } # function to print all keys & values for debug purposes sub debug_parse { my %conf = %{$_[0]}; my %vms = %{$_[1]}; for my $vm_name (sort keys %vms) { for my $key (keys %{$vms{$vm_name}}) { printf "VMS: %s %s = %s\n", $vm_name, $key, $vms{$vm_name}{$key}; } } } # check if _deploy.conf exists in current working directory my %conf; my $dir = cwd; if (-e "$dir/_deploy.conf") { %conf = get_variables('conf', "$dir/_deploy.conf"); } else { printf "Unable to find config file in current directory (%s).\n", $dir; printf "Create the config file _deploy.conf in %s.\n", $dir; exit 1; } # parse all vm*.txt files in the VMS directory my %vms; my @files = glob "$conf{'conf'}{'VMS'}/$vmid"; %vms = get_variables('vms', @files); # run all functions #debug_parse(\%conf, \%vms); remove_accounts(\%conf, \%vms); backup_img_files(\%conf, \%vms); backup_vm_files(\%conf, \%vms);