File Coverage

OpenQA/Qemu/BlockDevConf.pm
Criterion Covered Total %
statement 199 206 96.6
total 199 206 96.6


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;