int libvirt_init(void) { if(virInitialize() != 0) { return -1; } else { return 0; } }
static int mymain(void) { int ret = 0; int i; const char *nodeData[] = { "test1", # if !(defined(__powerpc__) || \ defined(__powerpc64__)) "test2", "test3", "test4", "test5", "test6", # endif }; if (virInitialize() < 0) return EXIT_FAILURE; for (i = 0 ; i < ARRAY_CARDINALITY(nodeData); i++) if (virtTestRun(nodeData[i], 1, linuxTestNodeInfo, nodeData[i]) != 0) ret = -1; return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; }
static int lv_init (void) { if (virInitialize () != 0) return -1; else return 0; }
int main(int argc, char **argv) { if(argc < 4) { exit(1); //error } user_id=atoi(argv[1]); clust_id=atoi(argv[2]); node_id=atoi(argv[3]); clusterCfgRead(); //virSetErrorFunc(NULL, customGlobalErrorFunc); virConnectPtr conn; if (virInitialize() < 0) { fprintf(stderr, "Failed to initialize libvirt"); return 12; } //virEventRegisterDefaultImpl(); conn = virConnectOpen("qemu:///system"); //xen+unix:/// if (!conn) { printf("error opening\n"); return 13; } /* coming here we have to restore the snapshot of the vm */ // Build the path to restore the saved snapshot snap$.img [$=node_id] char path[512]; memset(path,0,512); sprintf(path,"%s/%d/%d/snap%d.img",clusterHomeDir,user_id,clust_id,node_id); if( virDomainRestore(conn,path)!=0) { exit(21); } /*---------------------------------------------------------- */ if (conn && virConnectClose(conn) < 0){ printf("error closing\n"); return 16; } return 0; }
static void init_libguestfs (void) { gl_lock_lock (init_lock); #ifdef HAVE_LIBVIRT virInitialize (); #endif xmlInitParser (); LIBXML_TEST_VERSION; gl_lock_unlock (init_lock); }
static void init_libguestfs (void) { #if defined(HAVE_LIBVIRT) || defined(HAVE_LIBXML2) gl_lock_lock (init_lock); #endif #ifdef HAVE_LIBVIRT virInitialize (); #endif #ifdef HAVE_LIBXML2 xmlInitParser (); LIBXML_TEST_VERSION; #endif #if defined(HAVE_LIBVIRT) || defined(HAVE_LIBXML2) gl_lock_unlock (init_lock); #endif }
static int mymain(void) { int ret = 0; size_t i; const struct linuxTestNodeInfoData nodeData[] = { {"test1", VIR_ARCH_X86_64}, {"test1", VIR_ARCH_PPC}, {"test2", VIR_ARCH_X86_64}, {"test3", VIR_ARCH_X86_64}, {"test4", VIR_ARCH_X86_64}, {"test5", VIR_ARCH_X86_64}, {"test6", VIR_ARCH_X86_64}, {"test7", VIR_ARCH_X86_64}, {"test8", VIR_ARCH_X86_64}, {"raspberrypi", VIR_ARCH_ARMV6L}, {"f21-mustang", VIR_ARCH_AARCH64}, {"rhelsa-3.19.0-mustang", VIR_ARCH_AARCH64}, {"deconfigured-cpus", VIR_ARCH_PPC64}, }; if (virInitialize() < 0) return EXIT_FAILURE; for (i = 0; i < ARRAY_CARDINALITY(nodeData); i++) if (virtTestRun(nodeData[i].testName, linuxTestNodeInfo, &nodeData[i]) != 0) ret = -1; # define DO_TEST_CPU_STATS(name, ncpus) \ do { \ static struct nodeCPUStatsData data = { name, ncpus }; \ if (virtTestRun("CPU stats " name, linuxTestNodeCPUStats, &data) < 0) \ ret = -1; \ } while (0) DO_TEST_CPU_STATS("24cpu", 24); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }
static int lv_config (const char *key, const char *value) { if (virInitialize () != 0) return 1; if (il_domains == NULL) il_domains = ignorelist_create (1); if (il_block_devices == NULL) il_block_devices = ignorelist_create (1); if (il_interface_devices == NULL) il_interface_devices = ignorelist_create (1); if (strcasecmp (key, "Connection") == 0) { char *tmp = strdup (value); if (tmp == NULL) { ERROR (PLUGIN_NAME " plugin: Connection strdup failed."); return 1; } sfree (conn_string); conn_string = tmp; return 0; } if (strcasecmp (key, "RefreshInterval") == 0) { char *eptr = NULL; interval = strtol (value, &eptr, 10); if (eptr == NULL || *eptr != '\0') return 1; return 0; } if (strcasecmp (key, "Domain") == 0) { if (ignorelist_add (il_domains, value)) return 1; return 0; } if (strcasecmp (key, "BlockDevice") == 0) { if (ignorelist_add (il_block_devices, value)) return 1; return 0; } if (strcasecmp (key, "InterfaceDevice") == 0) { if (ignorelist_add (il_interface_devices, value)) return 1; return 0; } if (strcasecmp (key, "IgnoreSelected") == 0) { if (IS_TRUE (value)) { ignorelist_set_invert (il_domains, 0); ignorelist_set_invert (il_block_devices, 0); ignorelist_set_invert (il_interface_devices, 0); } else { ignorelist_set_invert (il_domains, 1); ignorelist_set_invert (il_block_devices, 1); ignorelist_set_invert (il_interface_devices, 1); } return 0; } if (strcasecmp (key, "HostnameFormat") == 0) { char *value_copy; char *fields[HF_MAX_FIELDS]; int i, n; value_copy = strdup (value); if (value_copy == NULL) { ERROR (PLUGIN_NAME " plugin: strdup failed."); return -1; } n = strsplit (value_copy, fields, HF_MAX_FIELDS); if (n < 1) { sfree (value_copy); ERROR (PLUGIN_NAME " plugin: HostnameFormat: no fields"); return -1; } for (i = 0; i < n; ++i) { if (strcasecmp (fields[i], "hostname") == 0) hostname_format[i] = hf_hostname; else if (strcasecmp (fields[i], "name") == 0) hostname_format[i] = hf_name; else if (strcasecmp (fields[i], "uuid") == 0) hostname_format[i] = hf_uuid; else { ERROR (PLUGIN_NAME " plugin: unknown HostnameFormat field: %s", fields[i]); sfree (value_copy); return -1; } } sfree (value_copy); for (i = n; i < HF_MAX_FIELDS; ++i) hostname_format[i] = hf_none; return 0; } if (strcasecmp (key, "PluginInstanceFormat") == 0) { char *value_copy; char *fields[PLGINST_MAX_FIELDS]; int i, n; value_copy = strdup (value); if (value_copy == NULL) { ERROR (PLUGIN_NAME " plugin: strdup failed."); return -1; } n = strsplit (value_copy, fields, PLGINST_MAX_FIELDS); if (n < 1) { sfree (value_copy); ERROR (PLUGIN_NAME " plugin: PluginInstanceFormat: no fields"); return -1; } for (i = 0; i < n; ++i) { if (strcasecmp (fields[i], "none") == 0) { plugin_instance_format[i] = plginst_none; break; } else if (strcasecmp (fields[i], "name") == 0) plugin_instance_format[i] = plginst_name; else if (strcasecmp (fields[i], "uuid") == 0) plugin_instance_format[i] = plginst_uuid; else { ERROR (PLUGIN_NAME " plugin: unknown PluginInstanceFormat field: %s", fields[i]); sfree (value_copy); return -1; } } sfree (value_copy); for (i = n; i < PLGINST_MAX_FIELDS; ++i) plugin_instance_format[i] = plginst_none; return 0; } if (strcasecmp (key, "InterfaceFormat") == 0) { if (strcasecmp (value, "name") == 0) interface_format = if_name; else if (strcasecmp (value, "address") == 0) interface_format = if_address; else if (strcasecmp (value, "number") == 0) interface_format = if_number; else { ERROR (PLUGIN_NAME " plugin: unknown InterfaceFormat: %s", value); return -1; } return 0; } /* Unrecognised option. */ return -1; }
static PromiseResult VerifyEnvironments(EvalContext *ctx, Attributes a, const Promise *pp) { char hyper_uri[CF_MAXVARSIZE]; enum cfhypervisors envtype = cfv_none; switch (Str2Hypervisors(a.env.type)) { case cfv_virt_xen: case cfv_virt_xen_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "xen:///"); envtype = cfv_virt_xen; break; case cfv_virt_kvm: case cfv_virt_kvm_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "qemu:///session"); envtype = cfv_virt_kvm; break; case cfv_virt_esx: case cfv_virt_esx_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "esx://127.0.0.1"); envtype = cfv_virt_esx; break; case cfv_virt_test: case cfv_virt_test_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "test:///default"); envtype = cfv_virt_test; break; case cfv_virt_vbox: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "vbox:///session"); envtype = cfv_virt_vbox; break; case cfv_zone: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "solaris_zone"); envtype = cfv_zone; break; default: Log(LOG_LEVEL_ERR, "Environment type '%s' not currently supported", a.env.type); return PROMISE_RESULT_NOOP; break; } Log(LOG_LEVEL_VERBOSE, "Selecting environment type '%s' '%s'", a.env.type, hyper_uri); ClassRef environment_host_ref = ClassRefParse(a.env.host); if (!EvalContextClassGet(ctx, environment_host_ref.ns, environment_host_ref.name)) { switch (a.env.state) { case ENVIRONMENT_STATE_CREATE: case ENVIRONMENT_STATE_RUNNING: Log(LOG_LEVEL_VERBOSE, "This host ''%s' is not the promised host for the environment '%s', so setting its intended state to 'down'", VFQNAME, a.env.host); a.env.state = ENVIRONMENT_STATE_DOWN; break; default: Log(LOG_LEVEL_VERBOSE, "This is not the promised host for the environment, but it does not promise a run state, so take promise as valid"); } } ClassRefDestroy(environment_host_ref); virInitialize(); PromiseResult result = PROMISE_RESULT_NOOP; #if defined(__linux__) switch (Str2Hypervisors(a.env.type)) { case cfv_virt_xen: case cfv_virt_kvm: case cfv_virt_esx: case cfv_virt_vbox: case cfv_virt_test: result = PromiseResultUpdate(result, VerifyVirtDomain(ctx, hyper_uri, envtype, a, pp)); break; case cfv_virt_xen_net: case cfv_virt_kvm_net: case cfv_virt_esx_net: case cfv_virt_test_net: result = PromiseResultUpdate(result, VerifyVirtNetwork(ctx, hyper_uri, envtype, a, pp)); break; case cfv_ec2: break; case cfv_eucalyptus: break; default: break; } #elif defined(__APPLE__) switch (Str2Hypervisors(a.env.type)) { case cfv_virt_vbox: case cfv_virt_test: result = PromiseResultUpdate(result, VerifyVirtDomain(ctx, hyper_uri, envtype, a, pp)); break; case cfv_virt_xen_net: case cfv_virt_kvm_net: case cfv_virt_esx_net: case cfv_virt_test_net: result = PromiseResultUpdate(result, VerifyVirtNetwork(ctx, hyper_uri, envtype, a, pp)); break; default: break; } #elif defined(__sun) switch (Str2Hypervisors(a.env.type)) { case cfv_zone: result = PromiseResultUpdate(result, VerifyZone(a, pp)); break; default: break; } #else Log(LOG_LEVEL_VERBOSE, "Unable to resolve an environment supervisor/monitor for this platform, aborting"); #endif return result; }
static void * event_thread(void *arg) { struct event_args *args = (struct event_args *)arg; virConnectPtr dconn = NULL; int callback1ret = -1; int sts; dbg_printf(3, "Libvirt event listener starting\n"); if (args->uri) dbg_printf(3," * URI: %s\n", args->uri); if (args->path) dbg_printf(3," * Socket path: %s\n", args->path); dbg_printf(3," * Mode: %s\n", args->mode ? "VMChannel" : "Serial"); top: virEventRegisterImpl(myEventAddHandleFunc, myEventUpdateHandleFunc, myEventRemoveHandleFunc, myEventAddTimeoutFunc, myEventUpdateTimeoutFunc, myEventRemoveTimeoutFunc); dconn = virConnectOpen(args->uri); if (!dconn) { dbg_printf(1, "Error connecting to libvirt\n"); goto out; } DEBUG0("Registering domain event cbs"); registerExisting(dconn, args->path, args->mode); callback1ret = virConnectDomainEventRegister(dconn, myDomainEventCallback1, arg, NULL); if (callback1ret == 0) { while (run) { struct pollfd pfd = { .fd = h_fd, .events = h_event, .revents = 0 }; sts = poll(&pfd, 1, TIMEOUT_MS); /* We are assuming timeout of 0 here - so execute every time */ if (t_cb && t_active) { t_cb(t_timeout, t_opaque); } if (sts == 0) { /* DEBUG0("Poll timeout"); */ continue; } if (sts < 0) { DEBUG0("Poll failed"); continue; } if (pfd.revents & POLLHUP) { DEBUG0("Reset by peer"); virConnectDomainEventDeregister(dconn, myDomainEventCallback1); if (dconn && virConnectClose(dconn) < 0) dbg_printf(1, "error closing libvirt connection\n"); DEBUG0("Attempting to reinitialize libvirt connection"); goto top; } if (h_cb) { h_cb(0, h_fd, myPollEventToEventHandleType(pfd.revents & h_event), h_opaque); } } DEBUG0("Deregistering event handlers"); virConnectDomainEventDeregister(dconn, myDomainEventCallback1); } DEBUG0("Closing connection"); if (dconn && virConnectClose(dconn) < 0) { dbg_printf(1, "error closing libvirt connection\n"); } out: free(args->uri); free(args->path); free(args); return NULL; } int start_event_listener(const char *uri, const char *path, int mode, int *wake_fd) { struct event_args *args = NULL; int wake_pipe[2]; virInitialize(); args = malloc(sizeof(*args)); if (!args) return -1; memset(args, 0, sizeof(*args)); if (pipe2(wake_pipe, O_CLOEXEC) < 0) { goto out_fail; } if (uri) { args->uri = strdup(uri); if (args->uri == NULL) goto out_fail; } if (path) { args->path = strdup(path); if (args->path == NULL) goto out_fail; } args->mode = mode; //args->p_tid = pthread_self(); *wake_fd = wake_pipe[0]; args->wake_fd = wake_pipe[1]; run = 1; return pthread_create(&event_tid, NULL, event_thread, args); out_fail: free(args->uri); free(args->path); free(args); return -1; } int stop_event_listener(void) { run = 0; //pthread_cancel(event_tid); pthread_join(event_tid, NULL); event_tid = 0; return 0; }
static void VerifyEnvironments(Attributes a, Promise *pp) { char hyper_uri[CF_MAXVARSIZE]; enum cfhypervisors envtype = cfv_none; switch (Str2Hypervisors(a.env.type)) { case cfv_virt_xen: case cfv_virt_xen_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "xen:///"); envtype = cfv_virt_xen; break; case cfv_virt_kvm: case cfv_virt_kvm_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "qemu:///session"); envtype = cfv_virt_kvm; break; case cfv_virt_esx: case cfv_virt_esx_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "esx://127.0.0.1"); envtype = cfv_virt_esx; break; case cfv_virt_test: case cfv_virt_test_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "test:///default"); envtype = cfv_virt_test; break; case cfv_virt_vbox: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "vbox:///session"); envtype = cfv_virt_vbox; break; case cfv_zone: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "solaris_zone"); envtype = cfv_zone; break; default: CfOut(cf_error, "", " !! Environment type \"%s\" not currently supported", a.env.type); return; break; } CfOut(cf_verbose, "", " -> Selecting environment type \"%s\" -> \"%s\"", a.env.type, hyper_uri); if (!IsDefinedClass(a.env.host, NULL)) { switch (a.env.state) { case cfvs_create: case cfvs_running: CfOut(cf_verbose, "", " -> This host (\"%s\") is not the promised host for the environment (\"%s\"), so setting its intended state to \"down\"", VFQNAME, a.env.host); a.env.state = cfvs_down; break; default: CfOut(cf_verbose, "", " -> This is not the promised host for the environment, but it does not promise a run state, so take promise as valid"); } } virInitialize(); switch (VSYSTEMHARDCLASS) { case linuxx: switch (Str2Hypervisors(a.env.type)) { case cfv_virt_xen: case cfv_virt_kvm: case cfv_virt_esx: case cfv_virt_vbox: case cfv_virt_test: VerifyVirtDomain(hyper_uri, envtype, a, pp); break; case cfv_virt_xen_net: case cfv_virt_kvm_net: case cfv_virt_esx_net: case cfv_virt_test_net: VerifyVirtNetwork(hyper_uri, envtype, a, pp); break; case cfv_ec2: break; case cfv_eucalyptus: break; default: break; } break; case darwin: switch (Str2Hypervisors(a.env.type)) { case cfv_virt_vbox: case cfv_virt_test: VerifyVirtDomain(hyper_uri, envtype, a, pp); break; case cfv_virt_xen_net: case cfv_virt_kvm_net: case cfv_virt_esx_net: case cfv_virt_test_net: VerifyVirtNetwork(hyper_uri, envtype, a, pp); break; default: break; } break; case solaris: switch (Str2Hypervisors(a.env.type)) { case cfv_zone: VerifyZone(a, pp); break; default: break; } break; default: CfOut(cf_verbose, "", " -> Unable to resolve an environment supervisor/monitor for this platform, aborting"); break; } }
static int lv_config (const char *key, const char *value) { if (virInitialize () != 0) return 1; if (il_domains == NULL) il_domains = ignorelist_create (1); if (il_block_devices == NULL) il_block_devices = ignorelist_create (1); if (il_interface_devices == NULL) il_interface_devices = ignorelist_create (1); if (strcasecmp (key, "Connection") == 0) { if (conn != 0) { ERROR ("Connection may only be given once in config file"); return 1; } conn = virConnectOpenReadOnly (value); if (!conn) { VIRT_ERROR (NULL, "connection failed"); return 1; } return 0; } if (strcasecmp (key, "RefreshInterval") == 0) { char *eptr = NULL; interval = strtol (value, &eptr, 10); if (eptr == NULL || *eptr != '\0') return 1; return 0; } if (strcasecmp (key, "Domain") == 0) { if (ignorelist_add (il_domains, value)) return 1; return 0; } if (strcasecmp (key, "BlockDevice") == 0) { if (ignorelist_add (il_block_devices, value)) return 1; return 0; } if (strcasecmp (key, "InterfaceDevice") == 0) { if (ignorelist_add (il_interface_devices, value)) return 1; return 0; } if (strcasecmp (key, "IgnoreSelected") == 0) { if (strcasecmp (value, "True") == 0 || strcasecmp (value, "Yes") == 0 || strcasecmp (value, "On") == 0) { ignorelist_set_invert (il_domains, 0); ignorelist_set_invert (il_block_devices, 0); ignorelist_set_invert (il_interface_devices, 0); } else { ignorelist_set_invert (il_domains, 1); ignorelist_set_invert (il_block_devices, 1); ignorelist_set_invert (il_interface_devices, 1); } return 0; } if (strcasecmp (key, "HostnameFormat") == 0) { char *value_copy; char *fields[HF_MAX_FIELDS]; int i, n; value_copy = strdup (value); if (value_copy == NULL) { ERROR ("libvirt plugin: strdup failed."); return -1; } n = strsplit (value_copy, fields, HF_MAX_FIELDS); if (n < 1) { free (value_copy); ERROR ("HostnameFormat: no fields"); return -1; } for (i = 0; i < n; ++i) { if (strcasecmp (fields[i], "hostname") == 0) hostname_format[i] = hf_hostname; else if (strcasecmp (fields[i], "name") == 0) hostname_format[i] = hf_name; else if (strcasecmp (fields[i], "uuid") == 0) hostname_format[i] = hf_uuid; else { free (value_copy); ERROR ("unknown HostnameFormat field: %s", fields[i]); return -1; } } free (value_copy); for (i = n; i < HF_MAX_FIELDS; ++i) hostname_format[i] = hf_none; return 0; } /* Unrecognised option. */ return -1; }
static void VerifyEnvironments(EvalContext *ctx, Attributes a, Promise *pp) { char hyper_uri[CF_MAXVARSIZE]; enum cfhypervisors envtype = cfv_none; switch (Str2Hypervisors(a.env.type)) { case cfv_virt_xen: case cfv_virt_xen_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "xen:///"); envtype = cfv_virt_xen; break; case cfv_virt_kvm: case cfv_virt_kvm_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "qemu:///session"); envtype = cfv_virt_kvm; break; case cfv_virt_esx: case cfv_virt_esx_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "esx://127.0.0.1"); envtype = cfv_virt_esx; break; case cfv_virt_test: case cfv_virt_test_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "test:///default"); envtype = cfv_virt_test; break; case cfv_virt_vbox: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "vbox:///session"); envtype = cfv_virt_vbox; break; case cfv_zone: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "solaris_zone"); envtype = cfv_zone; break; default: CfOut(OUTPUT_LEVEL_ERROR, "", " !! Environment type \"%s\" not currently supported", a.env.type); return; break; } CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Selecting environment type \"%s\" -> \"%s\"", a.env.type, hyper_uri); if (!IsDefinedClass(ctx, a.env.host, NULL)) { switch (a.env.state) { case ENVIRONMENT_STATE_CREATE: case ENVIRONMENT_STATE_RUNNING: CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> This host (\"%s\") is not the promised host for the environment (\"%s\"), so setting its intended state to \"down\"", VFQNAME, a.env.host); a.env.state = ENVIRONMENT_STATE_DOWN; break; default: CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> This is not the promised host for the environment, but it does not promise a run state, so take promise as valid"); } } virInitialize(); #if defined(__linux__) switch (Str2Hypervisors(a.env.type)) { case cfv_virt_xen: case cfv_virt_kvm: case cfv_virt_esx: case cfv_virt_vbox: case cfv_virt_test: VerifyVirtDomain(ctx, hyper_uri, envtype, a, pp); break; case cfv_virt_xen_net: case cfv_virt_kvm_net: case cfv_virt_esx_net: case cfv_virt_test_net: VerifyVirtNetwork(ctx, hyper_uri, envtype, a, pp); break; case cfv_ec2: break; case cfv_eucalyptus: break; default: break; } #elif defined(__APPLE__) switch (Str2Hypervisors(a.env.type)) { case cfv_virt_vbox: case cfv_virt_test: VerifyVirtDomain(hyper_uri, envtype, a, pp); break; case cfv_virt_xen_net: case cfv_virt_kvm_net: case cfv_virt_esx_net: case cfv_virt_test_net: VerifyVirtNetwork(hyper_uri, envtype, a, pp); break; default: break; } #elif defined(__sun) switch (Str2Hypervisors(a.env.type)) { case cfv_zone: VerifyZone(a, pp); break; default: break; } #else CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Unable to resolve an environment supervisor/monitor for this platform, aborting"); #endif }
int main(int argc, char **argv) { virConfPtr conf = NULL; const char *login_shell_path = conf_file; pid_t cpid = -1; int ret = EXIT_CANCELED; int status; uid_t uid = getuid(); gid_t gid = getgid(); char *name = NULL; char **shargv = NULL; virSecurityModelPtr secmodel = NULL; virSecurityLabelPtr seclabel = NULL; virDomainPtr dom = NULL; virConnectPtr conn = NULL; char *homedir = NULL; int arg; int longindex = -1; int ngroups; gid_t *groups = NULL; ssize_t nfdlist = 0; int *fdlist = NULL; int openmax; size_t i; struct option opt[] = { {"help", no_argument, NULL, 'h'}, {"version", optional_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; if (virInitialize() < 0) { fprintf(stderr, _("Failed to initialize libvirt error handling")); return EXIT_CANCELED; } setenv("PATH", "/bin:/usr/bin", 1); virSetErrorFunc(NULL, NULL); virSetErrorLogPriorityFunc(NULL); progname = argv[0]; if (!setlocale(LC_ALL, "")) { perror("setlocale"); /* failure to setup locale is not fatal */ } if (!bindtextdomain(PACKAGE, LOCALEDIR)) { perror("bindtextdomain"); return ret; } if (!textdomain(PACKAGE)) { perror("textdomain"); return ret; } while ((arg = getopt_long(argc, argv, "hV", opt, &longindex)) != -1) { switch (arg) { case 'h': usage(); exit(EXIT_SUCCESS); case 'V': show_version(); exit(EXIT_SUCCESS); case '?': default: usage(); exit(EXIT_CANCELED); } } if (argc > optind) { virReportSystemError(EINVAL, _("%s takes no options"), progname); goto cleanup; } if (uid == 0) { virReportSystemError(EPERM, _("%s must be run by non root users"), progname); goto cleanup; } name = virGetUserName(uid); if (!name) goto cleanup; homedir = virGetUserDirectoryByUID(uid); if (!homedir) goto cleanup; if (!(conf = virConfReadFile(login_shell_path, 0))) goto cleanup; if ((ngroups = virGetGroupList(uid, gid, &groups)) < 0) goto cleanup; if (virLoginShellAllowedUser(conf, name, groups) < 0) goto cleanup; if (!(shargv = virLoginShellGetShellArgv(conf))) goto cleanup; conn = virConnectOpen("lxc:///"); if (!conn) goto cleanup; dom = virDomainLookupByName(conn, name); if (!dom) goto cleanup; if (!virDomainIsActive(dom) && virDomainCreate(dom)) { virErrorPtr last_error; last_error = virGetLastError(); if (last_error->code != VIR_ERR_OPERATION_INVALID) { virReportSystemError(last_error->code, _("Can't create %s container: %s"), name, last_error->message); goto cleanup; } } openmax = sysconf(_SC_OPEN_MAX); if (openmax < 0) { virReportSystemError(errno, "%s", _("sysconf(_SC_OPEN_MAX) failed")); goto cleanup; } if ((nfdlist = virDomainLxcOpenNamespace(dom, &fdlist, 0)) < 0) goto cleanup; if (VIR_ALLOC(secmodel) < 0) goto cleanup; if (VIR_ALLOC(seclabel) < 0) goto cleanup; if (virNodeGetSecurityModel(conn, secmodel) < 0) goto cleanup; if (virDomainGetSecurityLabel(dom, seclabel) < 0) goto cleanup; if (virSetUIDGID(0, 0, NULL, 0) < 0) goto cleanup; if (virDomainLxcEnterSecurityLabel(secmodel, seclabel, NULL, 0) < 0) goto cleanup; if (nfdlist > 0 && virDomainLxcEnterNamespace(dom, nfdlist, fdlist, NULL, NULL, 0) < 0) goto cleanup; if (virSetUIDGID(uid, gid, groups, ngroups) < 0) goto cleanup; if (chdir(homedir) < 0) { virReportSystemError(errno, _("Unable to chdir(%s)"), homedir); goto cleanup; } /* A fork is required to create new process in correct pid namespace. */ if ((cpid = virFork()) < 0) goto cleanup; if (cpid == 0) { int tmpfd; for (i = 3; i < openmax; i++) { tmpfd = i; VIR_MASS_CLOSE(tmpfd); } if (execv(shargv[0], (char *const*) shargv) < 0) { virReportSystemError(errno, _("Unable to exec shell %s"), shargv[0]); virDispatchError(NULL); return errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE; } } /* At this point, the parent is now waiting for the child to exit, * but as that may take a long time, we release resources now. */ cleanup: if (nfdlist > 0) for (i = 0; i < nfdlist; i++) VIR_FORCE_CLOSE(fdlist[i]); VIR_FREE(fdlist); virConfFree(conf); if (dom) virDomainFree(dom); if (conn) virConnectClose(conn); virStringFreeList(shargv); VIR_FREE(name); VIR_FREE(homedir); VIR_FREE(seclabel); VIR_FREE(secmodel); VIR_FREE(groups); if (virProcessWait(cpid, &status, true) == 0) virProcessExitWithStatus(status); if (virGetLastError()) virDispatchError(NULL); return ret; }