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) 도움말 페이지에서 이에 대해 자세히 설명합니다.