line |
stmt |
code |
1
|
|
# Copyright 2018-2021 SUSE LLC |
2
|
|
# SPDX-License-Identifier: GPL-2.0-or-later |
3
|
|
|
4
|
|
=head2 OpenQA::Qemu::BlockDevConf |
5
|
|
|
6
|
|
Configure block devices and drives. |
7
|
|
|
8
|
|
=cut |
9
|
|
|
10
|
|
use Mojo::Base 'OpenQA::Qemu::MutParams', -signatures; |
11
|
16
|
|
|
16
|
|
|
16
|
|
12
|
|
use OpenQA::Qemu::BlockDev; |
13
|
16
|
use OpenQA::Qemu::DriveDevice; |
|
16
|
|
|
16
|
|
14
|
16
|
use OpenQA::Qemu::PFlashDevice; |
|
16
|
|
|
16
|
|
15
|
16
|
use Storable 'freeze'; |
|
16
|
|
|
16
|
|
16
|
16
|
|
|
16
|
|
|
16
|
|
17
|
|
use constant OVERLAY_POSTFIX => '-overlay'; |
18
|
16
|
|
|
16
|
|
|
16
|
|
19
|
|
has basedir => 'raid'; |
20
|
|
|
21
|
|
has _drives => sub ($self) { [] }; |
22
|
|
|
23
|
|
=head3 add_existing_base |
24
|
|
|
25
|
|
Add an existing image file at the bottom/start of a block device chain. |
26
|
|
|
27
|
|
=cut |
28
|
|
$file_name //= $id; |
29
|
74
|
|
|
74
|
|
|
74
|
|
|
74
|
|
|
74
|
|
|
74
|
|
30
|
74
|
return OpenQA::Qemu::BlockDev->new() |
31
|
|
->node_name($id) |
32
|
74
|
->file($file_name) |
33
|
|
->size($size); |
34
|
|
} |
35
|
|
|
36
|
|
=head3 add_new_base |
37
|
|
|
38
|
|
Add a new image file at the bottom of a block device chain. The file is not |
39
|
|
created by this function, this just updates the object model. |
40
|
|
|
41
|
|
=cut |
42
|
|
$file_name //= $id; |
43
|
|
|
44
|
36
|
return $self->add_existing_base($id, $self->basedir . '/' . $file_name, $size) |
|
36
|
|
|
36
|
|
|
36
|
|
|
36
|
|
|
36
|
|
45
|
36
|
->needs_creating(1); |
46
|
|
} |
47
|
36
|
|
48
|
|
=head3 add_existing_overlay |
49
|
|
|
50
|
|
Add an existing image file as the overlay of $backing_file. |
51
|
|
|
52
|
|
=cut |
53
|
|
my $ol = OpenQA::Qemu::BlockDev->new() |
54
|
|
->node_name($id) |
55
|
|
->backing_file($backing_file) |
56
|
170
|
->file($self->basedir . '/' . $id) |
|
170
|
|
|
170
|
|
|
170
|
|
|
170
|
|
57
|
170
|
->size($backing_file->size); |
58
|
|
$backing_file->overlay($ol); |
59
|
|
|
60
|
|
return $ol; |
61
|
|
} |
62
|
170
|
|
63
|
|
=head3 add_new_overlay |
64
|
170
|
|
65
|
|
Add an overlay on top of $backing_file, this is equivalent to creating a new |
66
|
|
snapshot. This function does not create the file, it just updates the object |
67
|
|
model. |
68
|
|
|
69
|
|
=cut |
70
|
|
|
71
|
|
die 'PFlash drives are not supported by DriveDevice, use PFlashDevice' |
72
|
|
if $model eq 'pflash'; |
73
|
|
|
74
|
38
|
my $dd = OpenQA::Qemu::DriveDevice->new() |
|
38
|
|
|
38
|
|
|
38
|
|
|
38
|
|
75
|
|
->id($id) |
76
|
62
|
->drive($drive) |
|
62
|
|
|
62
|
|
|
62
|
|
|
62
|
|
|
62
|
|
|
62
|
|
77
|
62
|
->model($model) |
78
|
|
->num_queues($num_queues); |
79
|
|
push(@{$self->_drives}, $dd); |
80
|
62
|
|
81
|
|
return $dd; |
82
|
|
} |
83
|
|
|
84
|
|
=head3 add_new_drive |
85
|
62
|
|
|
62
|
|
86
|
|
Create a new drive device and qcow2 image. |
87
|
62
|
|
88
|
|
=cut |
89
|
|
my $base_drive = $self->add_new_base($id, $id, $size); |
90
|
|
return $self->_push_new_drive_dev($id, $base_drive, $model, $num_queues); |
91
|
|
} |
92
|
|
|
93
|
|
=head3 add_existing_drive |
94
|
|
|
95
|
36
|
Create a new drive device with an existing qcow2 image as the backing store. A |
|
36
|
|
|
36
|
|
|
36
|
|
|
36
|
|
|
36
|
|
|
36
|
|
96
|
36
|
new overlay is created so that the existing qcow2 image is not modified. |
97
|
36
|
|
98
|
|
=cut |
99
|
|
my $base_drive = $self->add_existing_base($id, $file_name, $size)->implicit(1)->deduce_driver; |
100
|
|
my $overlay = $self->add_new_overlay($id . OVERLAY_POSTFIX . '0', $base_drive); |
101
|
|
|
102
|
|
return $self->_push_new_drive_dev($id, $overlay, $model, $num_queues); |
103
|
|
} |
104
|
|
|
105
|
|
|
106
|
10
|
=head3 add_iso_drive |
|
10
|
|
|
10
|
|
|
10
|
|
|
10
|
|
|
10
|
|
|
10
|
|
|
10
|
|
107
|
10
|
|
108
|
10
|
Add a cdrom or USB drive with a raw ISO image as the backing store. An overlay |
109
|
|
is created, so the test can write to this drive and it won't modify the |
110
|
10
|
underlying image. |
111
|
|
|
112
|
|
=cut |
113
|
|
my $base_drive = $self->add_existing_base($id, $file_name, $size) |
114
|
|
->implicit(1) |
115
|
|
->driver('raw'); |
116
|
|
my $overlay = $self->add_new_overlay($id . OVERLAY_POSTFIX . '0', $base_drive); |
117
|
|
|
118
|
|
return $self->_push_new_drive_dev($id, $overlay, $model); |
119
|
|
} |
120
|
|
|
121
|
16
|
=head3 add_pflash_drive |
|
16
|
|
|
16
|
|
|
16
|
|
|
16
|
|
|
16
|
|
|
16
|
|
122
|
16
|
|
123
|
|
Add a pflash drive which is generally used for UEFI firmware code and |
124
|
|
variables. See the OpenQA::Qemu::PFlashDevice class. |
125
|
16
|
|
126
|
|
=cut |
127
|
16
|
my $base_drive = $self->add_existing_base($id, $file_name, $size)->implicit(1)->deduce_driver; |
128
|
|
my $overlay = $self->add_new_overlay($id . OVERLAY_POSTFIX . '0', $base_drive); |
129
|
|
my $pflash = OpenQA::Qemu::PFlashDevice->new() |
130
|
|
->id($id) |
131
|
|
->drive($overlay); |
132
|
|
|
133
|
|
push(@{$self->_drives}, $pflash); |
134
|
|
return $pflash; |
135
|
|
} |
136
|
12
|
|
|
12
|
|
|
12
|
|
|
12
|
|
|
12
|
|
|
12
|
|
137
|
12
|
=head3 add_path_to_drive |
138
|
12
|
|
139
|
12
|
Add a connection between a drive device and a controller device. You can add |
140
|
|
multiple connections to simulate multipath. |
141
|
|
|
142
|
|
=cut |
143
|
12
|
my $dp = OpenQA::Qemu::DrivePath->new() |
|
12
|
|
144
|
12
|
->controller($controller) |
145
|
|
->id($id); |
146
|
|
push(@{$drive->paths}, $dp); |
147
|
|
|
148
|
|
return $dp; |
149
|
|
} |
150
|
|
|
151
|
|
=head3 add_snapshot_to_drive |
152
|
|
|
153
|
8
|
Add an overlay to the block device chain for a given drive. Snapshots are |
|
8
|
|
|
8
|
|
|
8
|
|
|
8
|
|
|
8
|
|
154
|
8
|
added at runtime by a QEMU QMP command which creates the overlay, so this |
155
|
|
function will not mark the overlay for creation by qemu-img. |
156
|
|
|
157
|
8
|
=cut |
|
8
|
|
158
|
|
my $id = $drive->id . OVERLAY_POSTFIX . $drive->new_overlay_id; |
159
|
8
|
|
160
|
|
my $snap = $self->add_existing_overlay($id, $drive->drive) |
161
|
|
->snapshot($snapshot); |
162
|
|
$drive->drive($snap); |
163
|
|
|
164
|
|
return $snap; |
165
|
|
} |
166
|
|
|
167
|
|
=head3 revert_to_snapshot |
168
|
|
|
169
|
132
|
Revert to a snapshot/overlay in the blockdev chain which is specified by the |
|
132
|
|
|
132
|
|
|
132
|
|
|
132
|
|
170
|
132
|
snapshot object. This returns a list of the overlay files which were created |
171
|
|
after the snapshot. These should be deleted to prevent QEMU from doing |
172
|
132
|
something unexpected. Also init_blockdev_images needs to be run after this. |
173
|
|
|
174
|
132
|
=cut |
175
|
|
my @del_files = (); |
176
|
132
|
|
177
|
|
my $snap = $drive->drive; |
178
|
|
while (defined $snap && !$snap->snapshot->equals($snapshot)) { |
179
|
|
push(@del_files, $snap->file); |
180
|
|
$snap = $snap->backing_file; |
181
|
|
$drive->drive($snap); |
182
|
|
} |
183
|
|
|
184
|
|
die 'Block dev chain for ' . $drive->id . ' does not contain snapshot ' . $snap->name |
185
|
|
unless defined $snap; |
186
|
|
die 'The last block device in ' . $drive->id . "'s block device chain is a snapshot" |
187
|
16
|
unless defined $snap->backing_file; |
|
16
|
|
|
16
|
|
|
16
|
|
|
16
|
|
188
|
16
|
|
189
|
|
# Will cause the snapshot overlay to be recreated when init_blockdev_images is run |
190
|
16
|
$snap->needs_creating(1); |
191
|
16
|
|
192
|
116
|
return \@del_files; |
193
|
116
|
} |
194
|
116
|
|
195
|
|
$sub->($_) for @{$self->_drives}; |
196
|
|
return $self; |
197
|
16
|
} |
198
|
|
|
199
|
16
|
$self->for_each_drive(sub { |
200
|
|
shift->for_each_overlay(sub { |
201
|
|
shift->needs_creating(0); |
202
|
|
}); |
203
|
16
|
}); |
204
|
|
} |
205
|
16
|
|
206
|
|
# See MutParams.pm |
207
|
|
|
208
|
66
|
=head3 gen_qemu_img_cmdlines |
|
66
|
|
|
66
|
|
|
66
|
|
209
|
66
|
|
|
66
|
|
210
|
66
|
Create qemu-img command lines for all drives that need creating. |
211
|
|
|
212
|
|
=cut |
213
|
16
|
|
|
16
|
|
|
16
|
|
214
|
|
|
215
|
|
map { $_->gen_qemu_img_convert($img_dir, $name, $qemu_compress_qcow) } |
216
|
170
|
grep { $_->id =~ $filter } @{$self->_drives}; |
217
|
30
|
} |
218
|
16
|
|
219
|
|
=head3 gen_unlink_list |
220
|
|
|
221
|
|
Generate a list of all files which are marked for creation. So that they can |
222
|
43
|
be safely deleted if they already exist. |
|
43
|
|
|
43
|
|
|
43
|
|
|
75
|
|
|
43
|
|
223
|
|
|
224
|
|
=cut |
225
|
|
|
226
|
|
# See MutParams.pm |
227
|
|
my @drives = map { $_->_to_map() } @{$self->_drives}; |
228
|
|
return {basedir => $self->basedir, drives => \@drives}; |
229
|
26
|
} |
|
26
|
|
|
26
|
|
|
26
|
|
|
44
|
|
|
26
|
|
230
|
|
|
231
|
0
|
# See MutParams.pm |
|
0
|
|
|
0
|
|
|
0
|
|
|
0
|
|
|
0
|
|
|
0
|
|
232
|
|
my @drives = map { |
233
|
10
|
$_->{model} eq 'pflash' ? |
|
10
|
|
|
10
|
|
|
10
|
|
|
10
|
|
|
10
|
|
|
10
|
|
234
|
10
|
OpenQA::Qemu::PFlashDevice->new()->_from_map($_, $cont_conf, $snap_conf) : |
235
|
10
|
OpenQA::Qemu::DriveDevice->new()->_from_map($_, $cont_conf, $snap_conf) |
|
12
|
|
|
10
|
|
236
|
|
} @{$map->{drives}}; |
237
|
|
|
238
|
|
return $self->basedir($map->{basedir})->_drives(\@drives); |
239
|
|
} |
240
|
|
|
241
|
|
# See MutParams.pm |
242
|
|
|
243
|
|
1; |