16.11. 프로그래밍 언어에서 API 사용
libguestfs API는 Red Hat Enterprise Linux 6.2의 다음 언어에서 직접 사용할 수 있습니다. C, C++, Perl, Python, Java, Ruby 및 OCaml.
- C 및 C++ 바인딩을 설치하려면 다음 명령을 입력합니다.
# yum install libguestfs-devel - Perl 바인딩을 설치하려면 다음을 수행합니다.
# yum install 'perl(Sys::Guestfs)' - Python 바인딩을 설치하려면 다음을 수행합니다.
# yum install python-libguestfs - Java 바인딩을 설치하려면 다음을 수행합니다.
# yum install libguestfs-java libguestfs-java-devel libguestfs-javadoc - Ruby 바인딩을 설치하려면 다음을 수행합니다.
# yum install ruby-libguestfs - OCaml 바인딩을 설치하려면 다음을 수행합니다.
# yum install ocaml-libguestfs ocaml-libguestfs-devel
각 언어의 바인딩은 기본적으로 동일하지만 약간의 구문 변경 사항이 있습니다. C 문의:
guestfs_launch (g);
Perl에서 다음과 같이 표시됩니다.
$g->launch ()
OCaml에서 다음과 같은 경우:
g#launch ()
이 섹션에서는 C API만 자세히 설명합니다.
C 및 C++ 바인딩에서 오류를 수동으로 확인해야 합니다. 다른 바인딩에서는 오류가 예외로 변환됩니다. 아래 예에 표시된 추가 오류 검사는 다른 언어에 필요하지 않지만 예외를 catch하는 코드를 추가하려는 경우도 있습니다. libguestfs API의 아키텍처에 대한 몇 가지 관심 사항은 다음 목록을 참조하십시오.
- libguestfs API가 동기화됩니다. 각 호출 블록은 완료될 때까지 차단됩니다. 비동기적으로 호출하려면 스레드를 만들어야 합니다.If you want to make calls asynchronously, you have to create a thread.
- libguestfs API는 스레드로부터 안전하지 않습니다. 각 핸들은 단일 스레드에서만 사용해야 합니다. 또는 두 스레드가 동시에 하나의 처리에서 명령을 실행할 수 없도록 자체 뮤텍스 간에 핸들을 공유해야 합니다.
- 동일한 디스크 이미지에서 여러 프로세스를 열 수 없습니다. 모든 핸들이 읽기 전용이지만 여전히 권장되지는 않는 경우 허용됩니다.
- 해당 디스크 이미지(예: 라이브 VM)를 사용할 수 있는 경우 쓰기용 디스크 이미지를 추가하지 않아야 합니다. 이렇게 하면 디스크 손상이 발생합니다.
- 현재 사용 중인 디스크 이미지에 읽기 전용 핸들을 열 수 있지만(예: 라이브 VM) 디스크 이미지를 읽는 시점에 디스크 이미지가 많이 기록되는 경우 결과를 예측할 수 없거나 특별히 일치하지 않을 수 있습니다.
16.11.1. C 프로그램을 통한 API와 상호 작용 링크 복사링크가 클립보드에 복사되었습니다!
링크 복사링크가 클립보드에 복사되었습니다!
C 프로그램은 헤더 파일을 {s.> 포함하여 시작하며, 핸들을 생성합니다.
#include <stdio.h>
#include <stdlib.h>
#include <guestfs.h>
int
main (int argc, char *argv[])
{
guestfs_h *g;
g = guestfs_create ();
if (g == NULL) {
perror ("failed to create libguestfs handle");
exit (EXIT_FAILURE);
}
/* ... */
guestfs_close (g);
exit (EXIT_SUCCESS);
}
이 프로그램을 파일에 저장합니다(
test.c). 이 프로그램을 컴파일하고 다음 두 명령을 사용하여 실행합니다.
gcc -Wall test.c -o test -lguestfs
./test
이 단계에서는 출력을 출력하지 않아야 합니다. 이 섹션의 나머지 부분에서는 이 프로그램을 확장하여 새 디스크 이미지를 생성하고 파티션을 지정하고, ext4 파일 시스템으로 포맷한 다음 파일 시스템에 일부 파일을 생성하는 방법을 보여주는 예제를 보여줍니다. 디스크 이미지는
disk.img 라고 하며 현재 디렉터리에 생성됩니다.
이 프로그램의 개요는 다음과 같습니다.
- 핸들을 만듭니다.
- 디스크에 디스크에 추가합니다.
- libguestfs 백엔드를 시작합니다.
- 파티션, 파일 시스템 및 파일을 만듭니다.
- 핸들을 닫고 종료합니다.
다음은 수정된 프로그램입니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <guestfs.h>
int
main (int argc, char *argv[])
{
guestfs_h *g;
size_t i;
g = guestfs_create ();
if (g == NULL) {
perror ("failed to create libguestfs handle");
exit (EXIT_FAILURE);
}
/* Create a raw-format sparse disk image, 512 MB in size. */
int fd = open ("disk.img", O_CREAT|O_WRONLY|O_TRUNC|O_NOCTTY, 0666);
if (fd == -1) {
perror ("disk.img");
exit (EXIT_FAILURE);
}
if (ftruncate (fd, 512 * 1024 * 1024) == -1) {
perror ("disk.img: truncate");
exit (EXIT_FAILURE);
}
if (close (fd) == -1) {
perror ("disk.img: close");
exit (EXIT_FAILURE);
}
/* Set the trace flag so that we can see each libguestfs call. */
guestfs_set_trace (g, 1);
/* Set the autosync flag so that the disk will be synchronized
* automatically when the libguestfs handle is closed.
*/
guestfs_set_autosync (g, 1);
/* Add the disk image to libguestfs. */
if (guestfs_add_drive_opts (g, "disk.img",
GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", /* raw format */
GUESTFS_ADD_DRIVE_OPTS_READONLY, 0, /* for write */
-1 /* this marks end of optional arguments */ )
== -1)
exit (EXIT_FAILURE);
/* Run the libguestfs back-end. */
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
/* Get the list of devices. Because we only added one drive
* above, we expect that this list should contain a single
* element.
*/
char **devices = guestfs_list_devices (g);
if (devices == NULL)
exit (EXIT_FAILURE);
if (devices[0] == NULL || devices[1] != NULL) {
fprintf (stderr,
"error: expected a single device from list-devices\n");
exit (EXIT_FAILURE);
}
/* Partition the disk as one single MBR partition. */
if (guestfs_part_disk (g, devices[0], "mbr") == -1)
exit (EXIT_FAILURE);
/* Get the list of partitions. We expect a single element, which
* is the partition we have just created.
*/
char **partitions = guestfs_list_partitions (g);
if (partitions == NULL)
exit (EXIT_FAILURE);
if (partitions[0] == NULL || partitions[1] != NULL) {
fprintf (stderr,
"error: expected a single partition from list-partitions\n");
exit (EXIT_FAILURE);
}
/* Create an ext4 filesystem on the partition. */
if (guestfs_mkfs (g, "ext4", partitions[0]) == -1)
exit (EXIT_FAILURE);
/* Now mount the filesystem so that we can add files. */
if (guestfs_mount_options (g, "", partitions[0], "/") == -1)
exit (EXIT_FAILURE);
/* Create some files and directories. */
if (guestfs_touch (g, "/empty") == -1)
exit (EXIT_FAILURE);
const char *message = "Hello, world\n";
if (guestfs_write (g, "/hello", message, strlen (message)) == -1)
exit (EXIT_FAILURE);
if (guestfs_mkdir (g, "/foo") == -1)
exit (EXIT_FAILURE);
/* This uploads the local file /etc/resolv.conf into the disk image. */
if (guestfs_upload (g, "/etc/resolv.conf", "/foo/resolv.conf") == -1)
exit (EXIT_FAILURE);
/* Because 'autosync' was set (above) we can just close the handle
* and the disk contents will be synchronized. You can also do
* this manually by calling guestfs_umount_all and guestfs_sync.
*/
guestfs_close (g);
/* Free up the lists. */
for (i = 0; devices[i] != NULL; ++i)
free (devices[i]);
free (devices);
for (i = 0; partitions[i] != NULL; ++i)
free (partitions[i]);
free (partitions);
exit (EXIT_SUCCESS);
}
다음 두 명령을 사용하여 이 프로그램을 컴파일하고 실행합니다.
gcc -Wall test.c -o test -lguestfs
./test
프로그램이 성공적으로 완료되는 경우
disk.img 라는 디스크 이미지로 남아 있어야 합니다. 이 이미지는fish로 검사할 수 있습니다.
guestfish --ro -a disk.img -m /dev/sda1
><fs> ll /
><fs> cat /foo/resolv.conf
기본적으로 (C 및 C++ 바인딩의 경우에만) libguestfs는 stderr에 오류를 출력합니다. 오류 처리기를 설정하여 이 동작을 변경할 수 있습니다. guestfs(3) 도움말 페이지에서 이에 대해 자세히 설명합니다.