19dba6721SSasha Levin #include <kvm/util.h> 29dba6721SSasha Levin #include <kvm/kvm-cmd.h> 32a24f96dSSasha Levin #include <kvm/builtin-list.h> 49dba6721SSasha Levin #include <kvm/kvm.h> 50725673aSSasha Levin #include <kvm/parse-options.h> 64b1addaeSSasha Levin #include <kvm/kvm-ipc.h> 79dba6721SSasha Levin 8076e946eSSasha Levin #include <dirent.h> 99dba6721SSasha Levin #include <stdio.h> 109dba6721SSasha Levin #include <string.h> 119dba6721SSasha Levin #include <signal.h> 121b1577dcSSasha Levin #include <fcntl.h> 131b1577dcSSasha Levin 14076e946eSSasha Levin static bool run; 15076e946eSSasha Levin static bool rootfs; 16076e946eSSasha Levin 170725673aSSasha Levin static const char * const list_usage[] = { 188d2ff5daSWanlong Gao "lkvm list", 190725673aSSasha Levin NULL 200725673aSSasha Levin }; 210725673aSSasha Levin 220725673aSSasha Levin static const struct option list_options[] = { 23076e946eSSasha Levin OPT_GROUP("General options:"), 24076e946eSSasha Levin OPT_BOOLEAN('i', "run", &run, "List running instances"), 25076e946eSSasha Levin OPT_BOOLEAN('r', "rootfs", &rootfs, "List rootfs instances"), 260725673aSSasha Levin OPT_END() 270725673aSSasha Levin }; 280725673aSSasha Levin 2978c684b1SOsier Yang #define KVM_INSTANCE_RUNNING "running" 305bf27f05SAsias He #define KVM_INSTANCE_PAUSED "paused" 3178c684b1SOsier Yang #define KVM_INSTANCE_SHUTOFF "shut off" 3278c684b1SOsier Yang 330725673aSSasha Levin void kvm_list_help(void) 340725673aSSasha Levin { 350725673aSSasha Levin usage_with_options(list_usage, list_options); 360725673aSSasha Levin } 370725673aSSasha Levin 384b1addaeSSasha Levin static pid_t get_pid(int sock) 394b1addaeSSasha Levin { 404b1addaeSSasha Levin pid_t pid; 410579e1d7SAsias He int r; 424b1addaeSSasha Levin 430579e1d7SAsias He r = kvm_ipc__send(sock, KVM_IPC_PID); 444b1addaeSSasha Levin if (r < 0) 454b1addaeSSasha Levin return r; 464b1addaeSSasha Levin 474b1addaeSSasha Levin r = read(sock, &pid, sizeof(pid)); 484b1addaeSSasha Levin if (r < 0) 494b1addaeSSasha Levin return r; 504b1addaeSSasha Levin 514b1addaeSSasha Levin return pid; 524b1addaeSSasha Levin } 534b1addaeSSasha Levin 54*08ffc82aSLai Jiangshan int get_vmstate(int sock) 555bf27f05SAsias He { 565bf27f05SAsias He int vmstate; 570579e1d7SAsias He int r; 585bf27f05SAsias He 590579e1d7SAsias He r = kvm_ipc__send(sock, KVM_IPC_VMSTATE); 605bf27f05SAsias He if (r < 0) 615bf27f05SAsias He return r; 625bf27f05SAsias He 635bf27f05SAsias He r = read(sock, &vmstate, sizeof(vmstate)); 645bf27f05SAsias He if (r < 0) 655bf27f05SAsias He return r; 665bf27f05SAsias He 675bf27f05SAsias He return vmstate; 685bf27f05SAsias He 695bf27f05SAsias He } 705bf27f05SAsias He 714b1addaeSSasha Levin static int print_guest(const char *name, int sock) 729dba6721SSasha Levin { 735bf27f05SAsias He pid_t pid; 745bf27f05SAsias He int vmstate; 755bf27f05SAsias He 765bf27f05SAsias He pid = get_pid(sock); 775bf27f05SAsias He vmstate = get_vmstate(sock); 781b1577dcSSasha Levin 790a56c424SLai Jiangshan if ((int)pid < 0 || vmstate < 0) 801b1577dcSSasha Levin goto cleanup; 811b1577dcSSasha Levin 825bf27f05SAsias He if (vmstate == KVM_VMSTATE_PAUSED) 835bf27f05SAsias He printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_PAUSED); 845bf27f05SAsias He else 8578c684b1SOsier Yang printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_RUNNING); 861b1577dcSSasha Levin 87886af5f2SLiming Wang return 0; 881b1577dcSSasha Levin 891b1577dcSSasha Levin cleanup: 904b1addaeSSasha Levin kvm__remove_socket(name); 910a56c424SLai Jiangshan return -1; 929dba6721SSasha Levin } 939dba6721SSasha Levin 94076e946eSSasha Levin static int kvm_list_running_instances(void) 959dba6721SSasha Levin { 96886af5f2SLiming Wang return kvm__enumerate_instances(print_guest); 979dba6721SSasha Levin } 98076e946eSSasha Levin 99076e946eSSasha Levin static int kvm_list_rootfs(void) 100076e946eSSasha Levin { 101076e946eSSasha Levin DIR *dir; 102076e946eSSasha Levin struct dirent *dirent; 103076e946eSSasha Levin 104da08dcdbSLai Jiangshan dir = opendir(kvm__get_dir()); 105076e946eSSasha Levin if (dir == NULL) 106076e946eSSasha Levin return -1; 107076e946eSSasha Levin 108076e946eSSasha Levin while ((dirent = readdir(dir))) { 109076e946eSSasha Levin if (dirent->d_type == DT_DIR && 110076e946eSSasha Levin strcmp(dirent->d_name, ".") && 111076e946eSSasha Levin strcmp(dirent->d_name, "..")) 11278c684b1SOsier Yang printf("%5s %-20s %s\n", "", dirent->d_name, KVM_INSTANCE_SHUTOFF); 113076e946eSSasha Levin } 114076e946eSSasha Levin 115076e946eSSasha Levin return 0; 116076e946eSSasha Levin } 117076e946eSSasha Levin 118076e946eSSasha Levin static void parse_setup_options(int argc, const char **argv) 119076e946eSSasha Levin { 120076e946eSSasha Levin while (argc != 0) { 121076e946eSSasha Levin argc = parse_options(argc, argv, list_options, list_usage, 122076e946eSSasha Levin PARSE_OPT_STOP_AT_NON_OPTION); 123076e946eSSasha Levin if (argc != 0) 124076e946eSSasha Levin kvm_list_help(); 125076e946eSSasha Levin } 126076e946eSSasha Levin } 127076e946eSSasha Levin 128076e946eSSasha Levin int kvm_cmd_list(int argc, const char **argv, const char *prefix) 129076e946eSSasha Levin { 130076e946eSSasha Levin int r; 131076e946eSSasha Levin 132076e946eSSasha Levin parse_setup_options(argc, argv); 133076e946eSSasha Levin 134076e946eSSasha Levin if (!run && !rootfs) 13584e10404SPekka Enberg run = rootfs = true; 13684e10404SPekka Enberg 13778c684b1SOsier Yang printf("%6s %-20s %s\n", "PID", "NAME", "STATE"); 13878c684b1SOsier Yang printf("------------------------------------\n"); 139076e946eSSasha Levin 140076e946eSSasha Levin if (run) { 141076e946eSSasha Levin r = kvm_list_running_instances(); 142076e946eSSasha Levin if (r < 0) 143076e946eSSasha Levin perror("Error listing instances"); 144076e946eSSasha Levin } 145076e946eSSasha Levin 146076e946eSSasha Levin if (rootfs) { 147076e946eSSasha Levin r = kvm_list_rootfs(); 148076e946eSSasha Levin if (r < 0) 149076e946eSSasha Levin perror("Error listing rootfs"); 150076e946eSSasha Levin } 151076e946eSSasha Levin 152076e946eSSasha Levin return 0; 153076e946eSSasha Levin } 154