File: pvm.pm

package info (click to toggle)
os-autoinst 4.3%2Bgit20160919-3
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 10,860 kB
  • ctags: 665
  • sloc: perl: 7,624; cpp: 1,584; python: 216; makefile: 188; sh: 63
file content (230 lines) | stat: -rw-r--r-- 7,552 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
package backend::pvm;
use strict;
use base ('backend::baseclass');
use bmwqemu qw(fileContent diag save_vars);
use File::Path qw/mkpath/;
require IPC::System::Simple;
use autodie qw(:all);
use File::Basename;
use Digest::MD5 qw(md5_hex);

sub new {
    my $class      = shift;
    my $self       = $class->SUPER::new;
    my $masterlpar = qx{cat /proc/device-tree/ibm,partition-name};
    $self->{pid}         = undef;
    $self->{children}    = [];
    $self->{pidfilename} = 'pvm.pid';
    $self->{pvmctl}      = '/usr/bin/pvmctl';
    $self->{masterlpar}  = substr($masterlpar, 0, -1);
    die "pvmctl not found" unless -x $self->{pvmctl};

    return $self;
}

sub do_start_vm {
    my $self = shift;
    $self->unlink_crash_file;
    $self->start_lpar();
    return {};
}

sub runcmd {
    diag "running " . join(' ', @_);
    return system(@_);
}

sub do_extract_assets {
    my ($self, $args) = @_;
    my $vars    = \%bmwqemu::vars;
    my $hdd_num = $args->{hdd_num};
    my $name    = $args->{name};
    my $img_dir = $args->{dir};
    my $format  = $args->{format};
    my $disk    = $vars->{"HDD_$hdd_num"};
    my $lpar    = $self->{masterlpar};
    my $cmd     = "pvmctl scsi list -w";
    $cmd = $cmd . " VirtualDisk.name=$disk";
    $cmd = $cmd . " -d VirtualDisk.udid --hide-label";
    #attach disk
    diag "Attaching $disk to $lpar";
    $self->pvmctl("scsi", "create", "lv", $disk, $lpar);

    my $prefix = "/dev/disk/by-id/scsi-SAIX_VDASD_";
    my $id     = qx{$cmd};
    chomp($id);
    my $device = $prefix . substr($id, 2);

    if (!$format || $format !~ /^raw$/) {
        diag "do_extract_assets: Image will be saved as raw eitherway";
    }

    #rescan scsi for newly attached disk
    qx{sudo rescan-scsi-bus.sh -a};
    #wait until udev creates a link
    until (-l $device) {
        sleep 1;
    }
    mkpath($img_dir);
    runcmd("sudo", "dd", "if=$device", "of=$img_dir/$name.$format", "bs=8096", "conv=sparse");

    #detach disk
    $self->pvmctl("scsi", "delete", "lv", $disk, $lpar);
    qx/sudo rescan-scsi-bus.sh -r/;
}

sub pvmctl {
    my $self = shift @_;
    my $vars = \%bmwqemu::vars;
    my ($type, $action) = @_;
    push(my @cmd, $self->{pvmctl}, $type, $action);
    my $lpar = $vars->{LPAR};

    if ($type =~ /lpar/) {
        push(@cmd, "-i", "name=" . $lpar) if ($action =~ /power|restart|delete/);
        if ($action =~ /create/) {
            my ($type, $action, $cpu, $memory) = @_;
            push(@cmd, qw{--proc-type shared --sharing-mode uncapped --type AIX/Linux});
            push(@cmd, "--proc", $cpu, "--mem", $memory, "--name", $lpar);
            push(@cmd, "--proc-unit", $cpu * 0.05);
        }
    }
    elsif ($type =~ /scsi/) {
        my ($type, $action, $kind, $file, $target) = @_;
        #so far only disks are reatachable to the master LPAR
        #set it back to default if argument is omited
        $lpar = $target if $target;
        push(@cmd, "--type", $kind, "--stor-id", $file);
        push(@cmd, "--lpar", "name=" . $lpar);
        push(@cmd, "--vg", "name=rootvg") if ($type =~ /lv/);
    }
    elsif ($type =~ /lv/) {
        my ($type, $action, $name, $size) = @_;
        push(@cmd, "--name", $name, "--size", $size);
    }
    elsif ($type =~ /eth/) {
        my ($type, $action, $vlan, $vswitch) = @_;
        push(@cmd, "--pvid", $vlan, "--vswitch", $vswitch, "-p", "name=" . $lpar);
    }
    else {
        die "Unrecognized command $type";
    }
    runcmd(@cmd);
}
sub attach_console {
    my $vars    = \%bmwqemu::vars;
    my $vncport = qx{sudo /usr/sbin/mkvtermutil --id $vars->{LPARID} --vnc --local --log serial0 2>/dev/null};
    $vncport =~ /([0-9]+)/;
    chomp($vncport);
    $vars->{VNC} = $vncport;
    diag "VNC is $vars->{VNC}";
}

sub image_exists {
    my ($img, $size) = @_;
    #lv already exists?
    my @cmd;
    my $pvmctlcmd = "pvmctl lv list -w LogicalVolume.name=$img -d LogicalVolume.name LogicalVolume.capacity -f , --hide-label";
    my ($name, $capacity) = split(",", qx/$pvmctlcmd/);
    return if !($name =~ /$img/);
    if (($img =~ /$name/) && ($size =~ /$capacity/)) {
        push(@cmd, "sudo viosvrcmd --id 1 -r -c \"dd if=/dev/zero bs=1024 count=1 of=/dev/r$name\"");
    }
    else {
        push(@cmd, "sudo viosvrcmd --id 1 -c\"rmbdsp -sp rootvg -bd $name\"");
    }
    runcmd(@cmd);
}
sub start_lpar {
    my $self = shift;
    my $vars = \%bmwqemu::vars;
    #general settiings
    $vars->{LPAR} = "osauto" . $vars->{WORKER_ID};
    $vars->{CPUS} ||= 1;
    $vars->{MEM}  ||= "2048";
    #disk settings
    $vars->{NUMDISKS}  ||= 1;
    $vars->{HDDSIZEGB} ||= 15;
    #network settings
    $vars->{NIC}     ||= "sea";
    $vars->{NICVLAN} ||= 1;
    $vars->{VSWITCH} ||= "ETHERNET0";
    #unfortunately NovaLink can't take files longer than 38 chars. So we need to shorten ISO name here
    $vars->{VIOISO} = md5_hex(basename($vars->{ISO})) . ".iso";
    my $iso = $vars->{VIOISO};
    die "$iso exceeds 37 characters\n" if (length($iso) > 37);

    if (!($vars->{ARCH} =~ /ppc64/)) {
        die "arch $vars->{ARCH} is not allowed on pvm backend";
    }
    #create lpar
    $self->pvmctl("lpar", "create", $vars->{CPUS}, $vars->{MEM});

    my $id = substr(qx/pvmctl lpar list -d LogicalPartition.id --where LogicalPartition.name=$vars->{LPAR}/, 3);
    chomp($id);
    $vars->{LPARID} = $id;
    bmwqemu::save_vars();

    #we copy isos from nfs mount on VIO side to VMLibrary
    my $source_iso = '/iso/' . basename($vars->{ISO});
    diag "source_iso: $source_iso, vio iso: $iso";
    my $iso_present = qx/pvmctl media list -d VirtualOpticalMedia.media_name --where VirtualOpticalMedia.name=$iso/;
    if ($iso_present !~ /$iso/) {
        #copy over from nfs to VMLibrary
        my @viocmd = ("sudo viosvrcmd --id 1 -r -c\"cp $source_iso /var/vio/VMLibrary/$iso\"");
        push(@viocmd, "sudo viosvrcmd --id 1 -r -c\"chown padmin:staff /var/vio/VMLibrary/$iso\"");
        push(@viocmd, "sudo viosvrcmd --id 1 -c\"chvopt -name $iso -access ro\"");
        foreach my $viocmd (@viocmd) {
            runcmd($viocmd);
        }
    }
    $self->pvmctl('scsi', 'create', 'vopt', $iso);

    for my $i (1 .. $vars->{NUMDISKS}) {
        my $name = $vars->{LPAR} . "_" . $i;
        $vars->{"HDD_$i"} = $name;
        my $size = $vars->{HDDSIZEGB};
        $self->pvmctl("lv", "create", $name, $size) if !image_exists($name, $size);
        $self->pvmctl("scsi", "create", "lv", $name);
    }

    $self->pvmctl("eth", "create", $vars->{NICVLAN}, $vars->{VSWITCH});
    $self->pvmctl("lpar", "power-on");
    bmwqemu::save_vars();

    attach_console;
    bmwqemu::save_vars();

    my $vnc = $testapi::distri->add_console(
        'sut',
        'vnc-base',
        {
            hostname => 'localhost',
            port     => $vars->{VNC}});
    $vnc->backend($self);
    $self->select_console({testapi_console => 'sut'});
}

sub _status {
    my ($self) = @_;
    my $id = $bmwqemu::vars{LPARID};
    return qx{pvmctl lpar list -i id=$id -d LogicalPartition.state --hide-label};
}

sub is_shutdown {
    my ($self) = @_;
    return $self->_status =~ /running/;
}

sub do_stop_vm {
    my $self = shift;
    my $vars = \%bmwqemu::vars;
    $self->pvmctl("lpar", "power-off") if (!$self->is_shutdown);
    runcmd("rmvterm", "--id", $vars->{LPARID});
    for my $i (1 .. $vars->{NUMDISKS}) {
        my $disk = $vars->{LPAR} . "_" . $i;
        $self->pvmctl("scsi", "delete", "lv", $disk);
    }
    $self->pvmctl("scsi", "delete", "vopt", $vars->{VIOISO});
    $self->pvmctl("lpar", "delete");
}