App-FuguVM

 view release on metacpan or  search on metacpan

lib/App/FuguVM/DiskCache.pod  view on Meta::CPAN

file. No script installed an imported image, so the record holds no
script digest, and an imported entry survives a change to a shipped
expect script. An overlay inherits the virtual size of its base, so
the record holds no disk size either, and each host of a fleet
derives one key.

=back

The generation file is a counter. Increase the number in this file
when the install driver changes in a way that the script hash cannot
see. One example is a change in how L<App::FuguVM::Guest> or
L<App::FuguVM::Console> drives the installer.

The counter is a data file, not a constant in this module. Thus a
continuous-integration cache key can hash the file too. Keep the file
content to the bare number: the hash covers the whole content, and an
edit to a comment changes the key.

The memory settings and the port settings do not shape the disk, and
the key intentionally excludes them. Thus a change to these settings
hits the same entry.

=head2 Snapshots

A snapshot is an immutable, named layer over the base image of an
entry. Its purpose is to cache states that fuguvm itself does not
know. One example is a provisioning script that caches its "guest
packages installed" state. The mechanism is in this module. The
policy stays in the callers: they select the states that get a cache.

The snapshots are inside C<< installed/<key>/ >>. Thus, when a base
becomes invalid - through a new key, or through C<cache clear> - the
snapshots of that base also become invalid automatically.

C<snapshot_store> B<flattens> the working disk onto C<base.qcow2>. It
does not copy the disk. Thus each snapshot is a direct child of the
base:

    base.qcow2  <-  <name>.qcow2  <-  disk.qcow2

A copy keeps the backing-file header of the working disk verbatim.
That header is correct only while the disk hangs directly off the
base. After a restore, the disk hangs off a snapshot. Thus a copy
stacks chains without a limit, or it publishes a qcow2 that names
itself as its own backing file. The second result occurs when a caller
saves the same name again. A normal second run does this.

Because C<snapshot_store> flattens the disk, no snapshot is the parent
of a different snapshot. Thus C<snapshot_remove> cannot make a
snapshot an orphan.

The working disk must come from a stopped VM. A live overlay is not
consistent.

=head1 METHODS

=over 4

=item new($cache_dir)

The constructor creates a cache over C<$cache_dir>. It expands a
C<~> at the start of the path.

=item installed_dir

=item entry_dir($key)

=item base_path($key)

These methods return locations. The paths do not have to exist.

=item key($vm_config)

The method derives the cache key for a VM configuration hash. It
returns C<undef> when it cannot read an input, and when the
configuration carries no architecture. The caller then has no key,
and thus no cache.

Two architectures give two key strings and two entry directories.
Thus one cache holds a base image for each architecture, and neither
entry can overwrite the other.

=item lookup($key)

The method returns C<< { key, dir, base, meta } >> for a complete
entry. In other cases, it returns C<undef>. A half-written entry is a
miss, not an error.

=item store($key, $disk_path, $meta)

The method compacts C<$disk_path> into the cache as the base image
for C<$key>, and writes C<$meta> adjacent to it. Put the guest
C<root_password> in C<$meta>. The method returns the path of the base
image. It returns C<undef> on a failure, and a try to overwrite a
populated key is one such failure. The caller then degrades to a
standalone disk.

=item lock_entry($key, $timeout)

The method returns an open handle with an exclusive C<flock(2)> on
the lock file of C<$key>:
C<< <cache_dir>/installed/.lock.<key> >>. The wait blocks, with a
deadline of C<$timeout> seconds (default 3600). The method returns
C<undef> on the deadline, and C<undef> when the file cannot open.

The lock releases when the handle closes, or when the process exits.
Thus a stale lock file blocks nothing.

The lock serializes the first population of one entry. The caller
takes the lock, looks the key up a second time, and installs only on
a second miss. Every project that shares the cache directory shares
the lock. The lock does not replace the write-once rule of C<store>:
a run that lost the lock to its deadline still cannot publish a
second entry.

The file name starts with a dot. Thus it cannot collide with an
entry: C<list> reads only a directory whose name has no leading dot,
and C<sweep_temp> removes only a C<.tmp.> directory.

=item list



( run in 1.196 second using v1.01-cache-2.11-cpan-a49fcb8fa48 )