mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2613e5301b | ||
|
|
7a16a0b358 | ||
|
|
f8e4c310bb | ||
|
|
d1808ea5eb | ||
|
|
42afed95dc | ||
|
|
7bbadaec5a | ||
|
|
b43ca06ea6 |
@@ -116,6 +116,9 @@ $UDEVD --daemon #--debug
|
||||
udevadm trigger
|
||||
udevadm settle --timeout=600
|
||||
|
||||
# Recreate module dependencies (RHEL only)
|
||||
depmod -a
|
||||
|
||||
# Disk optimizations.
|
||||
# Increase the SCSI timeout so we can read remote images.
|
||||
shopt -s nullglob
|
||||
|
||||
@@ -248,12 +248,17 @@ device_name_translation (const char *device)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *reverse_btrfsvol (const char *device);
|
||||
|
||||
char *
|
||||
reverse_device_name_translation (const char *device)
|
||||
{
|
||||
char *ret = NULL;
|
||||
size_t i;
|
||||
|
||||
if (STRPREFIX (device, "btrfsvol:"))
|
||||
return reverse_btrfsvol (device);
|
||||
|
||||
/* Look it up in the cache, and if found return the canonical name.
|
||||
* If not found return a copy of the original string.
|
||||
*/
|
||||
@@ -287,3 +292,34 @@ reverse_device_name_translation (const char *device)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* btrfsvol:/dev/sdX also needs reversing. */
|
||||
static char *
|
||||
reverse_btrfsvol (const char *device)
|
||||
{
|
||||
const char prefix[] = "btrfsvol:";
|
||||
const char *device_start, *device_end;
|
||||
CLEANUP_FREE char *device_name = NULL;
|
||||
CLEANUP_FREE char *reversed_device = NULL;
|
||||
char *ret;
|
||||
|
||||
device_start = device + strlen (prefix);
|
||||
device_end = strchr (device_start + strlen ("/dev/"), '/');
|
||||
device_name = strndup (device_start, device_end - device_start);
|
||||
if (device_name == NULL) {
|
||||
reply_with_perror ("strndup");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
reversed_device = reverse_device_name_translation (device_name);
|
||||
if (reversed_device == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Construct the final btrfsvol: and return it, caller frees. */
|
||||
if (asprintf (&ret, "%s%s%s", prefix, reversed_device, device_end) == -1) {
|
||||
reply_with_perror ("asprintf");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -207,6 +207,12 @@ and check_windows_registry systemroot data =
|
||||
if Is.is_file system_hive then Some system_hive else None in
|
||||
data.windows_system_hive <- system_hive;
|
||||
|
||||
if verbose () then
|
||||
eprintf "check_windows_registry: software hive: %s\n\
|
||||
check_windows_registry: system hive: %s\n%!"
|
||||
(Option.value ~default:"None" software_hive)
|
||||
(Option.value ~default:"None" system_hive);
|
||||
|
||||
match software_hive, system_hive with
|
||||
| None, _ | Some _, None -> ()
|
||||
| Some software_hive, Some system_hive ->
|
||||
@@ -376,11 +382,25 @@ and map_registry_disk_blob_mbr devices blob =
|
||||
* disk with this disk ID.
|
||||
*)
|
||||
let diskid = String.sub blob 0 4 in
|
||||
if verbose () then
|
||||
eprintf "map_registry_disk_blob_mbr: searching for MBR disk ID %s\n%!"
|
||||
(hex_of_string diskid);
|
||||
|
||||
let device =
|
||||
List.find (
|
||||
fun dev ->
|
||||
Parted.part_get_parttype dev = "msdos" &&
|
||||
try
|
||||
Parted.part_get_parttype dev = "msdos" &&
|
||||
pread dev 4 0x01b8 = diskid
|
||||
with Unix.Unix_error (EINVAL, "parted", msg) ->
|
||||
(* Errors can happen here if the disk is empty. Just ignore
|
||||
* them. It means the drive mapping might have missing
|
||||
* entries but that's not important. (RHEL-108803)
|
||||
*)
|
||||
if verbose () then
|
||||
eprintf "map_registry_disk_blob_mbr: parted returned: \
|
||||
%s (ignored)\n" msg;
|
||||
false
|
||||
) devices in
|
||||
|
||||
(* Next 8 bytes are the offset of the partition in bytes(!) given as
|
||||
@@ -388,6 +408,10 @@ and map_registry_disk_blob_mbr devices blob =
|
||||
* partition byte offset from Parted.part_list.
|
||||
*)
|
||||
let offset = String.sub blob 4 8 in
|
||||
if verbose () then
|
||||
eprintf "map_registry_disk_blob_mbr: searching for MBR partition offset \
|
||||
%s\n%!"
|
||||
(hex_of_string offset);
|
||||
let offset = int_of_le64 offset in
|
||||
let partitions = Parted.part_list device in
|
||||
let partition =
|
||||
@@ -414,14 +438,21 @@ and map_registry_disk_blob_gpt partitions blob =
|
||||
let partition =
|
||||
List.find (
|
||||
fun part ->
|
||||
let partnum = Devsparts.part_to_partnum part in
|
||||
let device = Devsparts.part_to_dev part in
|
||||
let typ = Parted.part_get_parttype device in
|
||||
if typ <> "gpt" then false
|
||||
else (
|
||||
let guid = Sfdisk.part_get_gpt_guid device partnum in
|
||||
String.lowercase_ascii guid = blob_guid
|
||||
)
|
||||
try
|
||||
let partnum = Devsparts.part_to_partnum part in
|
||||
let device = Devsparts.part_to_dev part in
|
||||
let typ = Parted.part_get_parttype device in
|
||||
if typ <> "gpt" then false
|
||||
else (
|
||||
let guid = Sfdisk.part_get_gpt_guid device partnum in
|
||||
String.lowercase_ascii guid = blob_guid
|
||||
)
|
||||
with Unix.Unix_error (EINVAL, "parted", msg) ->
|
||||
(* See comment in MBR code above (RHEL-108803) *)
|
||||
if verbose () then
|
||||
eprintf "map_registry_disk_blob_gpt: parted returned: \
|
||||
%s (ignored)\n" msg;
|
||||
false
|
||||
) partitions in
|
||||
Some partition
|
||||
with
|
||||
|
||||
@@ -291,3 +291,7 @@ let parse_key_value_strings ?unquote lines =
|
||||
match unquote with
|
||||
| None -> lines
|
||||
| Some f -> List.map (fun (k, v) -> (k, f v)) lines
|
||||
|
||||
let hex_of_string s =
|
||||
let bytes = String.map_chars (fun c -> sprintf "%02x" (Char.code c)) s in
|
||||
String.concat " " bytes
|
||||
|
||||
@@ -121,5 +121,9 @@ val parse_key_value_strings : ?unquote:(string -> string) -> string list -> (str
|
||||
it is applied on the values as unquote function. Empty lines,
|
||||
or that start with a comment character [#], are ignored. *)
|
||||
|
||||
val hex_of_string : string -> string
|
||||
(** Return a string as a list of hex bytes.
|
||||
Use this for debugging msgs only. *)
|
||||
|
||||
(**/**)
|
||||
val get_verbose_flag : unit -> bool
|
||||
|
||||
@@ -109,26 +109,6 @@ image. To exit, type C<exit>.
|
||||
If you get an error, try enabling debugging (add C<-v> to the command
|
||||
line). Also make sure that L<libguestfs-test-tool(1)> succeeds.
|
||||
|
||||
=head2 Try to open a remote guest image with guestfish.
|
||||
|
||||
You may also have to disable libvirt by setting this:
|
||||
|
||||
export LIBGUESTFS_BACKEND=direct
|
||||
|
||||
If you have a disk image available over HTTP/FTP, try to open it.
|
||||
|
||||
guestfish --ro -i --format=raw -a http://www.example.com/disk.img
|
||||
|
||||
For SSH you will need to make sure that ssh-agent is set up so you
|
||||
don't need a password to log in to the remote machine. Then a command
|
||||
similar to this should work:
|
||||
|
||||
guestfish --ro -i --format=raw \
|
||||
-a ssh://remote.example.com/path/to/disk.img
|
||||
|
||||
If you get an error, try enabling debugging (add C<-v> to the command
|
||||
line). Also make sure that L<libguestfs-test-tool(1)> succeeds.
|
||||
|
||||
=head2 Run virt-alignment-scan on all your guests.
|
||||
|
||||
Run L<virt-alignment-scan(1)> on guests or disk images:
|
||||
|
||||
@@ -131,9 +131,9 @@ To list what is available do:
|
||||
|
||||
=head2 Remote drives
|
||||
|
||||
Access a remote disk using ssh:
|
||||
Access a remote disk using NBD:
|
||||
|
||||
guestfish -a ssh://example.com/path/to/disk.img
|
||||
guestfish -a nbd://example.com
|
||||
|
||||
=head2 Remote control
|
||||
|
||||
@@ -1129,12 +1129,12 @@ L<guestfs(3)/REMOTE STORAGE>>.
|
||||
On the command line, you can use the I<-a> option to add network
|
||||
block devices using a URI-style format, for example:
|
||||
|
||||
guestfish -a ssh://root@example.com/disk.img
|
||||
guestfish -a nbd://example.com
|
||||
|
||||
URIs I<cannot> be used with the L</add> command. The equivalent
|
||||
command using the API directly is:
|
||||
|
||||
><fs> add /disk.img protocol:ssh server:tcp:example.com username:root
|
||||
><fs> add /disk.img protocol:nbd server:tcp:example.com
|
||||
|
||||
The possible I<-a URI> formats are described below.
|
||||
|
||||
@@ -1144,28 +1144,6 @@ The possible I<-a URI> formats are described below.
|
||||
|
||||
Add the local disk image (or device) called F<disk.img>.
|
||||
|
||||
=head2 B<-a ftp://[user@]example.com[:port]/disk.img>
|
||||
|
||||
=head2 B<-a ftps://[user@]example.com[:port]/disk.img>
|
||||
|
||||
=head2 B<-a http://[user@]example.com[:port]/disk.img>
|
||||
|
||||
=head2 B<-a https://[user@]example.com[:port]/disk.img>
|
||||
|
||||
Add a disk located on a remote FTP or HTTP server.
|
||||
|
||||
The equivalent API command would be:
|
||||
|
||||
><fs> add /disk.img protocol:(ftp|...) server:tcp:example.com
|
||||
|
||||
=head2 B<-a iscsi://example.com[:port]/target-iqn-name[/lun]>
|
||||
|
||||
Add a disk located on an iSCSI server.
|
||||
|
||||
The equivalent API command would be:
|
||||
|
||||
><fs> add target-iqn-name/lun protocol:iscsi server:tcp:example.com
|
||||
|
||||
=head2 B<-a nbd://example.com[:port]>
|
||||
|
||||
=head2 B<-a nbd://example.com[:port]/exportname>
|
||||
@@ -1200,23 +1178,13 @@ The equivalent API command would be:
|
||||
|
||||
><fs> add pool/disk protocol:rbd server:tcp:example.com:port
|
||||
|
||||
=head2 B<-a ssh://[user@]example.com[:port]/disk.img>
|
||||
|
||||
Add a disk image located on a remote server, accessed using the Secure
|
||||
Shell (ssh) SFTP protocol. SFTP is supported out of the box by all
|
||||
major SSH servers.
|
||||
|
||||
The equivalent API command would be:
|
||||
|
||||
><fs> add /disk protocol:ssh server:tcp:example.com [username:user]
|
||||
|
||||
Note that the URIs follow the syntax of
|
||||
L<RFC 3986|https://tools.ietf.org/html/rfc3986>: in particular, there
|
||||
are restrictions on the allowed characters for the various components
|
||||
of the URI. Characters such as C<:>, C<@>, and C</> B<must> be
|
||||
percent-encoded:
|
||||
|
||||
$ guestfish -a ssh://user:pass%40word@example.com/disk.img
|
||||
$ guestfish -a rbd://user:pass%40word@example.com[:port]/pool/disk
|
||||
|
||||
In this case, the password is C<pass@word>.
|
||||
|
||||
|
||||
@@ -40,10 +40,6 @@ function fail ()
|
||||
$VG guestfish -x -a file://$abs_builddir/test-add-uri.img </dev/null >test-add-uri.out 2>&1
|
||||
grep -sq 'add_drive ".*/test-add-uri.img"' test-add-uri.out || fail
|
||||
|
||||
# curl
|
||||
$VG guestfish -x -a ftp://user@example.com/disk.img </dev/null >test-add-uri.out 2>&1
|
||||
grep -sq 'add_drive "/disk.img" "protocol:ftp" "server:tcp:example.com" "username:user"' test-add-uri.out || fail
|
||||
|
||||
# NBD
|
||||
$VG guestfish -x -a nbd://example.com </dev/null >test-add-uri.out 2>&1
|
||||
grep -sq 'add_drive "" "protocol:nbd" "server:tcp:example.com"' test-add-uri.out || fail
|
||||
@@ -63,22 +59,5 @@ grep -sq 'add_drive "pool/disk" "protocol:rbd" "server:tcp:example.com:6789"' te
|
||||
$VG guestfish -x -a rbd:///pool/disk </dev/null >test-add-uri.out 2>&1
|
||||
grep -sq 'add_drive "pool/disk" "protocol:rbd"' test-add-uri.out || fail
|
||||
|
||||
# ssh
|
||||
$VG guestfish -x -a ssh://example.com/disk.img </dev/null >test-add-uri.out 2>&1
|
||||
grep -sq 'add_drive "/disk.img" "protocol:ssh" "server:tcp:example.com"' test-add-uri.out || fail
|
||||
|
||||
$VG guestfish -x -a ssh://user@example.com/disk.img </dev/null >test-add-uri.out 2>&1
|
||||
grep -sq 'add_drive "/disk.img" "protocol:ssh" "server:tcp:example.com" "username:user"' test-add-uri.out || fail
|
||||
|
||||
$VG guestfish -x -a ssh://user@example.com:2000/disk.img </dev/null >test-add-uri.out 2>&1
|
||||
grep -sq 'add_drive "/disk.img" "protocol:ssh" "server:tcp:example.com:2000" "username:user"' test-add-uri.out || fail
|
||||
|
||||
# iSCSI
|
||||
$VG guestfish -x -a iscsi://example.com/iqn.2015-12.com.libguestfs:test1/0 </dev/null >test-add-uri.out 2>&1
|
||||
grep -sq 'add_drive "iqn.2015-12.com.libguestfs:test1/0" "protocol:iscsi" "server:tcp:example.com"' test-add-uri.out || fail
|
||||
|
||||
$VG guestfish -x -a iscsi://user:password@example.com/iqn.2015-12.com.libguestfs:test2/0 </dev/null >test-add-uri.out 2>&1
|
||||
grep -sq 'add_drive "iqn.2015-12.com.libguestfs:test2/0" "protocol:iscsi" "server:tcp:example.com" "username:user" "secret:password"' test-add-uri.out || fail
|
||||
|
||||
rm test-add-uri.out
|
||||
rm test-add-uri.img
|
||||
|
||||
@@ -350,22 +350,6 @@ F<filename> is interpreted as a local file or device.
|
||||
This is the default if the optional protocol parameter
|
||||
is omitted.
|
||||
|
||||
=item C<protocol = \"ftp\"|\"ftps\"|\"http\"|\"https\">
|
||||
|
||||
Connect to a remote FTP or HTTP server.
|
||||
The C<server> parameter must also be supplied - see below.
|
||||
|
||||
See also: L<guestfs(3)/FTP AND HTTP>
|
||||
|
||||
=item C<protocol = \"iscsi\">
|
||||
|
||||
Connect to the iSCSI server.
|
||||
The C<server> parameter must also be supplied - see below.
|
||||
The C<username> parameter may be supplied. See below.
|
||||
The C<secret> parameter may be supplied. See below.
|
||||
|
||||
See also: L<guestfs(3)/ISCSI>.
|
||||
|
||||
=item C<protocol = \"nbd\">
|
||||
|
||||
Connect to the Network Block Device server.
|
||||
@@ -382,15 +366,6 @@ The C<secret> parameter may be supplied. See below.
|
||||
|
||||
See also: L<guestfs(3)/CEPH>.
|
||||
|
||||
=item C<protocol = \"ssh\">
|
||||
|
||||
Connect to the Secure Shell (ssh) server.
|
||||
|
||||
The C<server> parameter must be supplied.
|
||||
The C<username> parameter may be supplied. See below.
|
||||
|
||||
See also: L<guestfs(3)/SSH>.
|
||||
|
||||
=back
|
||||
|
||||
=item C<server>
|
||||
@@ -401,11 +376,8 @@ is a list of server(s).
|
||||
Protocol Number of servers required
|
||||
-------- --------------------------
|
||||
file List must be empty or param not used at all
|
||||
ftp|ftps|http|https Exactly one
|
||||
iscsi Exactly one
|
||||
nbd Exactly one
|
||||
rbd Zero or more
|
||||
ssh Exactly one
|
||||
|
||||
Each list element is a string specifying a server. The string must be
|
||||
in one of the following formats:
|
||||
@@ -421,10 +393,10 @@ for the protocol is used (see F</etc/services>).
|
||||
|
||||
=item C<username>
|
||||
|
||||
For the C<ftp>, C<ftps>, C<http>, C<https>, C<iscsi>, C<rbd> and C<ssh>
|
||||
protocols, this specifies the remote username.
|
||||
For the C<rbd>
|
||||
protocol, this specifies the remote username.
|
||||
|
||||
If not given, then the local username is used for C<ssh>, and no authentication
|
||||
If not given, then no authentication
|
||||
is attempted for ceph. But note this sometimes may give unexpected results, for
|
||||
example if using the libvirt backend and if the libvirt backend is configured to
|
||||
start the qemu appliance as a special user such as C<qemu.qemu>. If in doubt,
|
||||
|
||||
@@ -1834,6 +1834,22 @@ and generate_client_actions actions () =
|
||||
check_args_validity c_name style;
|
||||
trace_call name c_name style;
|
||||
|
||||
(* RHEL *)
|
||||
if name = "mount" || name = "mount_ro" || name = "mount_options" ||
|
||||
name = "mount_vfs" then (
|
||||
pr " if (g->program && !STRPREFIX (g->program, \"virt-\")) {\n";
|
||||
pr " CLEANUP_FREE char *vfs_type = guestfs_vfs_type (g, mountable);\n";
|
||||
pr " if (vfs_type && STREQ (vfs_type, \"ntfs\")) {\n";
|
||||
pr " error (g, \"mount: unsupported filesystem type\");\n";
|
||||
pr " if (trace_flag)\n";
|
||||
pr " guestfs_int_trace (g, \"%%s = %%s (error)\",\n";
|
||||
pr " \"%s\", \"-1\");\n" name;
|
||||
pr " return %s;\n" (string_of_errcode errcode);
|
||||
pr " }\n";
|
||||
pr " }\n";
|
||||
pr "\n";
|
||||
);
|
||||
|
||||
(* Calculate the total size of all FileIn arguments to pass
|
||||
* as a progress bar hint.
|
||||
*)
|
||||
|
||||
113
lib/drives.c
113
lib/drives.c
@@ -166,34 +166,6 @@ create_drive_non_file (guestfs_h *g,
|
||||
return drv;
|
||||
}
|
||||
|
||||
static struct drive *
|
||||
create_drive_curl (guestfs_h *g,
|
||||
const struct drive_create_data *data)
|
||||
{
|
||||
if (data->nr_servers != 1) {
|
||||
error (g, _("curl: you must specify exactly one server"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data->servers[0].transport != drive_transport_none &&
|
||||
data->servers[0].transport != drive_transport_tcp) {
|
||||
error (g, _("curl: only tcp transport is supported"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (STREQ (data->exportname, "")) {
|
||||
error (g, _("curl: pathname should not be an empty string"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data->exportname[0] != '/') {
|
||||
error (g, _("curl: pathname must begin with a '/'"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return create_drive_non_file (g, data);
|
||||
}
|
||||
|
||||
static int
|
||||
nbd_port (void)
|
||||
{
|
||||
@@ -261,67 +233,6 @@ create_drive_rbd (guestfs_h *g,
|
||||
return create_drive_non_file (g, data);
|
||||
}
|
||||
|
||||
static struct drive *
|
||||
create_drive_ssh (guestfs_h *g,
|
||||
const struct drive_create_data *data)
|
||||
{
|
||||
if (data->nr_servers != 1) {
|
||||
error (g, _("ssh: you must specify exactly one server"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data->servers[0].transport != drive_transport_none &&
|
||||
data->servers[0].transport != drive_transport_tcp) {
|
||||
error (g, _("ssh: only tcp transport is supported"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (STREQ (data->exportname, "")) {
|
||||
error (g, _("ssh: pathname should not be an empty string"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data->exportname[0] != '/') {
|
||||
error (g, _("ssh: pathname must begin with a '/'"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data->username && STREQ (data->username, "")) {
|
||||
error (g, _("ssh: username should not be an empty string"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return create_drive_non_file (g, data);
|
||||
}
|
||||
|
||||
static struct drive *
|
||||
create_drive_iscsi (guestfs_h *g,
|
||||
const struct drive_create_data *data)
|
||||
{
|
||||
if (data->nr_servers != 1) {
|
||||
error (g, _("iscsi: you must specify exactly one server"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data->servers[0].transport != drive_transport_none &&
|
||||
data->servers[0].transport != drive_transport_tcp) {
|
||||
error (g, _("iscsi: only tcp transport is supported"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (STREQ (data->exportname, "")) {
|
||||
error (g, _("iscsi: target name should not be an empty string"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data->exportname[0] == '/') {
|
||||
error (g, _("iscsi: target string must not begin with a '/'"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return create_drive_non_file (g, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the special F</dev/null> drive.
|
||||
*
|
||||
@@ -768,26 +679,6 @@ guestfs_impl_add_drive_opts (guestfs_h *g, const char *filename,
|
||||
drv = create_drive_file (g, &data);
|
||||
}
|
||||
}
|
||||
else if (STREQ (protocol, "ftp")) {
|
||||
data.protocol = drive_protocol_ftp;
|
||||
drv = create_drive_curl (g, &data);
|
||||
}
|
||||
else if (STREQ (protocol, "ftps")) {
|
||||
data.protocol = drive_protocol_ftps;
|
||||
drv = create_drive_curl (g, &data);
|
||||
}
|
||||
else if (STREQ (protocol, "http")) {
|
||||
data.protocol = drive_protocol_http;
|
||||
drv = create_drive_curl (g, &data);
|
||||
}
|
||||
else if (STREQ (protocol, "https")) {
|
||||
data.protocol = drive_protocol_https;
|
||||
drv = create_drive_curl (g, &data);
|
||||
}
|
||||
else if (STREQ (protocol, "iscsi")) {
|
||||
data.protocol = drive_protocol_iscsi;
|
||||
drv = create_drive_iscsi (g, &data);
|
||||
}
|
||||
else if (STREQ (protocol, "nbd")) {
|
||||
data.protocol = drive_protocol_nbd;
|
||||
drv = create_drive_nbd (g, &data);
|
||||
@@ -796,10 +687,6 @@ guestfs_impl_add_drive_opts (guestfs_h *g, const char *filename,
|
||||
data.protocol = drive_protocol_rbd;
|
||||
drv = create_drive_rbd (g, &data);
|
||||
}
|
||||
else if (STREQ (protocol, "ssh")) {
|
||||
data.protocol = drive_protocol_ssh;
|
||||
drv = create_drive_ssh (g, &data);
|
||||
}
|
||||
else {
|
||||
error (g, _("unknown protocol ‘%s’"), protocol);
|
||||
drv = NULL; /*FALLTHROUGH*/
|
||||
|
||||
@@ -723,51 +723,6 @@ a qcow2 backing file specification, libvirt does not construct an
|
||||
ephemeral secret object from those, for Ceph authentication. Refer to
|
||||
L<https://bugzilla.redhat.com/2033247>.
|
||||
|
||||
=head3 FTP AND HTTP
|
||||
|
||||
Libguestfs can access remote disks over FTP, FTPS, HTTP or HTTPS
|
||||
protocols.
|
||||
|
||||
To do this, set the optional C<protocol> and C<server> parameters of
|
||||
L</guestfs_add_drive_opts> like this:
|
||||
|
||||
char **servers = { "www.example.org", NULL };
|
||||
guestfs_add_drive_opts (g, "/disk.img",
|
||||
GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
|
||||
GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "http",
|
||||
GUESTFS_ADD_DRIVE_OPTS_SERVER, servers,
|
||||
-1);
|
||||
|
||||
The C<protocol> can be one of C<"ftp">, C<"ftps">, C<"http">,
|
||||
or C<"https">.
|
||||
|
||||
C<servers> (the C<server> parameter) is a list which must have a
|
||||
single element. The single element is a string defining the web
|
||||
or FTP server. The format of this string is documented in
|
||||
L</guestfs_add_drive_opts>.
|
||||
|
||||
=head3 GLUSTER
|
||||
|
||||
Glusterfs support was removed in libguestfs 1.54 (2024).
|
||||
|
||||
=head3 ISCSI
|
||||
|
||||
Libguestfs can access iSCSI disks remotely.
|
||||
|
||||
To do this, set the optional C<protocol> and C<server> parameters like
|
||||
this:
|
||||
|
||||
char **server = { "iscsi.example.org:3000", NULL };
|
||||
guestfs_add_drive_opts (g, "target-iqn-name/lun",
|
||||
GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
|
||||
GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "iscsi",
|
||||
GUESTFS_ADD_DRIVE_OPTS_SERVER, server,
|
||||
-1);
|
||||
|
||||
The C<server> parameter is a list which must have a single element.
|
||||
The single element is a string defining the iSCSI server. The format
|
||||
of this string is documented in L</guestfs_add_drive_opts>.
|
||||
|
||||
=head3 NETWORK BLOCK DEVICE
|
||||
|
||||
Libguestfs can access Network Block Device (NBD) disks remotely.
|
||||
@@ -830,28 +785,6 @@ L<https://bugs.launchpad.net/qemu/+bug/1155677>
|
||||
|
||||
=back
|
||||
|
||||
=head3 SHEEPDOG
|
||||
|
||||
Sheepdog support was removed in libguestfs 1.54 (2024).
|
||||
|
||||
=head3 SSH
|
||||
|
||||
Libguestfs can access disks over a Secure Shell (SSH) connection.
|
||||
|
||||
To do this, set the C<protocol> and C<server> and (optionally)
|
||||
C<username> parameters of L</guestfs_add_drive_opts> like this:
|
||||
|
||||
char **server = { "remote.example.com", NULL };
|
||||
guestfs_add_drive_opts (g, "/path/to/disk.img",
|
||||
GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
|
||||
GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "ssh",
|
||||
GUESTFS_ADD_DRIVE_OPTS_SERVER, server,
|
||||
GUESTFS_ADD_DRIVE_OPTS_USERNAME, "remoteuser",
|
||||
-1);
|
||||
|
||||
The format of the server string is documented in
|
||||
L</guestfs_add_drive_opts>.
|
||||
|
||||
=head2 INSPECTION
|
||||
|
||||
Libguestfs has APIs for inspecting an unknown disk image to find out
|
||||
|
||||
@@ -37,6 +37,7 @@ fi
|
||||
|
||||
# Create a disk image.
|
||||
guestfish <<EOF
|
||||
set-program virt-testing
|
||||
sparse windows.img-t 512M
|
||||
run
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@ main (int argc, char *argv[])
|
||||
if (g == NULL)
|
||||
error (EXIT_FAILURE, 0, "failed to create handle");
|
||||
|
||||
guestfs_set_program (g, "virt-testing");
|
||||
|
||||
if (guestfs_add_drive_scratch (g, 1024*1024*1024, -1) == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
|
||||
@@ -65,13 +65,6 @@ check_output
|
||||
grep -sq -- '-drive file=rbd:abc-def/ghi-jkl:auth_supported=none,' "$DEBUG_QEMU_FILE" || fail ceph2
|
||||
rm "$DEBUG_QEMU_FILE"
|
||||
|
||||
# iSCSI.
|
||||
|
||||
$guestfish -d iscsi run ||:
|
||||
check_output
|
||||
grep -sq -- '-drive file=iscsi://1.2.3.4:1234/iqn.2003-01.org.linux-iscsi.fedora' "$DEBUG_QEMU_FILE" || fail iscsi
|
||||
rm "$DEBUG_QEMU_FILE"
|
||||
|
||||
# NBD.
|
||||
|
||||
$guestfish -d nbd run ||:
|
||||
|
||||
@@ -63,35 +63,6 @@ check_output
|
||||
grep -sq -- '-drive file=rbd:abc-def/ghi-jkl:auth_supported=none,' "$DEBUG_QEMU_FILE" || fail
|
||||
rm "$DEBUG_QEMU_FILE"
|
||||
|
||||
# HTTP.
|
||||
|
||||
guestfish <<EOF ||:
|
||||
add "/disk.img" "format:raw" "protocol:http" "server:www.example.com"
|
||||
run
|
||||
EOF
|
||||
check_output
|
||||
grep -sq -- '-drive file=http://www.example.com/disk.img,' "$DEBUG_QEMU_FILE" || fail
|
||||
rm "$DEBUG_QEMU_FILE"
|
||||
|
||||
# iSCSI.
|
||||
|
||||
guestfish <<EOF ||:
|
||||
add "target-iqn-name/lun" "format:raw" "protocol:iscsi" "server:www.example.com:3000"
|
||||
run
|
||||
EOF
|
||||
check_output
|
||||
grep -sq -- '-drive file=iscsi://www.example.com:3000/target-iqn-name/lun,' "$DEBUG_QEMU_FILE" || fail
|
||||
rm "$DEBUG_QEMU_FILE"
|
||||
|
||||
guestfish <<EOF ||:
|
||||
add "target-iqn-name/lun" "format:raw" "protocol:iscsi" "server:www.example.com:3000" \
|
||||
"username:user" "secret:pass"
|
||||
run
|
||||
EOF
|
||||
check_output
|
||||
grep -sq -- '-drive file=iscsi://user%pass@www.example.com:3000/target-iqn-name/lun,' "$DEBUG_QEMU_FILE" || fail
|
||||
rm "$DEBUG_QEMU_FILE"
|
||||
|
||||
# NBD.
|
||||
|
||||
guestfish <<EOF ||:
|
||||
@@ -109,14 +80,3 @@ EOF
|
||||
check_output
|
||||
grep -sq -- '-drive file=nbd:unix:/socket,' "$DEBUG_QEMU_FILE" || fail
|
||||
rm "$DEBUG_QEMU_FILE"
|
||||
|
||||
# SSH.
|
||||
|
||||
guestfish <<EOF ||:
|
||||
add "/disk.img" "format:raw" "protocol:ssh" "server:example.com" \
|
||||
"username:rich"
|
||||
run
|
||||
EOF
|
||||
check_output
|
||||
grep -sq -- '-drive file=ssh://rich@example.com/disk.img,' "$DEBUG_QEMU_FILE" || fail
|
||||
rm "$DEBUG_QEMU_FILE"
|
||||
|
||||
Reference in New Issue
Block a user