int libvirt_connect(int driver) { if (g_conn != NULL) { logwarn(_("conneted already.\n")); return -1; } virSetErrorFunc(NULL, __customErrorFunc); const char * URI; if (driver == HYPERVISOR_IS_KVM) URI = HYPERVISOR_URI_KVM; else if (driver == HYPERVISOR_IS_XEN) URI = HYPERVISOR_URI_XEN; else { logerror(_("unrecognized hypervisor driver(%d).\n"), driver); return -1; } __this_lock(); g_conn = virConnectOpen(URI); __this_unlock(); if (g_conn == NULL) { logerror(_("Connet to %s error.\n"), URI); return -1; } else { loginfo(_("Connect to %s success!\n"), URI); } return 0; }
static int mymain(void) { int id = 0; int ro = 0; virConnectPtr conn; virDomainPtr dom; int status; virCommandPtr cmd; struct utsname ut; /* Skip test if xend is not running. Calling xend on a non-xen kernel causes some versions of xend to issue a crash report, so we first probe uname results. */ uname(&ut); if (strstr(ut.release, "xen") == NULL) return EXIT_AM_SKIP; cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL); if (virCommandRun(cmd, &status) != 0 || status != 0) { virCommandFree(cmd); return EXIT_AM_SKIP; } virCommandFree(cmd); virSetErrorFunc(NULL, errorHandler); conn = virConnectOpen(NULL); if (conn == NULL) { ro = 1; conn = virConnectOpenReadOnly(NULL); } if (conn == NULL) { fprintf(stderr, "First virConnectOpen() failed\n"); return EXIT_FAILURE; } dom = virDomainLookupByID(conn, id); if (dom == NULL) { fprintf(stderr, "First lookup for domain %d failed\n", id); return EXIT_FAILURE; } virDomainFree(dom); virConnectClose(conn); if (ro == 1) conn = virConnectOpenReadOnly(NULL); else conn = virConnectOpen(NULL); if (conn == NULL) { fprintf(stderr, "Second virConnectOpen() failed\n"); return EXIT_FAILURE; } dom = virDomainLookupByID(conn, id); if (dom == NULL) { fprintf(stderr, "Second lookup for domain %d failed\n", id); return EXIT_FAILURE; } virDomainFree(dom); virConnectClose(conn); return EXIT_SUCCESS; }
int libvirt_check(int driver) { virSetErrorFunc(NULL, __customErrorFunc); const char * URI; if (driver == HYPERVISOR_IS_KVM) URI = HYPERVISOR_URI_KVM; else if (driver == HYPERVISOR_IS_XEN) URI = HYPERVISOR_URI_XEN; else { logerror(_("unrecognized hypervisor driver(%d).\n"), driver); return -1; } virConnectPtr conn = virConnectOpen(URI); if (conn == NULL) { logerror(_("Connect to %s error.\n"), URI); return -1; } int numDomains = virConnectNumOfDomains(conn); if (numDomains < 0) { logerror(_("Connect to %s error.\n"), URI); return -1; } virConnectClose(conn); return 0; }
static PromiseResult VerifyVirtDomain(EvalContext *ctx, char *uri, enum cfhypervisors envtype, Attributes a, const Promise *pp) { int num, i; /* set up the library error handler */ virSetErrorFunc(NULL, (void *) EnvironmentErrorHandler); if (CFVC[envtype] == NULL) { if ((CFVC[envtype] = virConnectOpenAuth(uri, virConnectAuthPtrDefault, 0)) == NULL) { Log(LOG_LEVEL_ERR, "Failed to connect to virtualization monitor '%s'", uri); return PROMISE_RESULT_NOOP; } } for (i = 0; i < CF_MAX_CONCURRENT_ENVIRONMENTS; i++) { CF_RUNNING[i] = -1; CF_SUSPENDED[i] = NULL; } num = virConnectListDomains(CFVC[envtype], CF_RUNNING, CF_MAX_CONCURRENT_ENVIRONMENTS); Log(LOG_LEVEL_VERBOSE, "Found %d running guest environments on this host (including enclosure)", num); ShowRunList(CFVC[envtype]); num = virConnectListDefinedDomains(CFVC[envtype], CF_SUSPENDED, CF_MAX_CONCURRENT_ENVIRONMENTS); Log(LOG_LEVEL_VERBOSE, "Found %d dormant guest environments on this host", num); ShowDormant(); PromiseResult result = PROMISE_RESULT_NOOP; switch (a.env.state) { case ENVIRONMENT_STATE_CREATE: result = PromiseResultUpdate(result, CreateVirtDom(ctx, CFVC[envtype], a, pp)); break; case ENVIRONMENT_STATE_DELETE: result = PromiseResultUpdate(result, DeleteVirt(ctx, CFVC[envtype], a, pp)); break; case ENVIRONMENT_STATE_RUNNING: result = PromiseResultUpdate(result, RunningVirt(ctx, CFVC[envtype], a, pp)); break; case ENVIRONMENT_STATE_SUSPENDED: result = PromiseResultUpdate(result, SuspendedVirt(ctx, CFVC[envtype], a, pp)); break; case ENVIRONMENT_STATE_DOWN: result = PromiseResultUpdate(result, DownVirt(ctx, CFVC[envtype], a, pp)); break; default: Log(LOG_LEVEL_INFO, "No state specified for this environment"); break; } return result; }
static void VerifyVirtDomain(char *uri, enum cfhypervisors envtype, Attributes a, Promise *pp) { int num, i; /* set up the library error handler */ virSetErrorFunc(NULL, (void *) EnvironmentErrorHandler); if (CFVC[envtype] == NULL) { if ((CFVC[envtype] = virConnectOpenAuth(uri, virConnectAuthPtrDefault, 0)) == NULL) { CfOut(cf_error, "", " !! Failed to connect to virtualization monitor \"%s\"", uri); return; } } for (i = 0; i < CF_MAX_CONCURRENT_ENVIRONMENTS; i++) { CF_RUNNING[i] = -1; CF_SUSPENDED[i] = NULL; } num = virConnectListDomains(CFVC[envtype], CF_RUNNING, CF_MAX_CONCURRENT_ENVIRONMENTS); CfOut(cf_verbose, "", " -> Found %d running guest environments on this host (including enclosure)", num); ShowRunList(CFVC[envtype]); num = virConnectListDefinedDomains(CFVC[envtype], CF_SUSPENDED, CF_MAX_CONCURRENT_ENVIRONMENTS); CfOut(cf_verbose, "", " -> Found %d dormant guest environments on this host", num); ShowDormant(CFVC[envtype]); switch (a.env.state) { case cfvs_create: CreateVirtDom(CFVC[envtype], uri, a, pp); break; case cfvs_delete: DeleteVirt(CFVC[envtype], uri, a, pp); break; case cfvs_running: RunningVirt(CFVC[envtype], uri, a, pp); break; case cfvs_suspended: SuspendedVirt(CFVC[envtype], uri, a, pp); break; case cfvs_down: DownVirt(CFVC[envtype], uri, a, pp); break; default: CfOut(cf_inform, "", " !! No state specified for this environment"); break; } }
static void VerifyVirtDomain(EvalContext *ctx, char *uri, enum cfhypervisors envtype, Attributes a, Promise *pp) { int num, i; /* set up the library error handler */ virSetErrorFunc(NULL, (void *) EnvironmentErrorHandler); if (CFVC[envtype] == NULL) { if ((CFVC[envtype] = virConnectOpenAuth(uri, virConnectAuthPtrDefault, 0)) == NULL) { CfOut(OUTPUT_LEVEL_ERROR, "", " !! Failed to connect to virtualization monitor \"%s\"", uri); return; } } for (i = 0; i < CF_MAX_CONCURRENT_ENVIRONMENTS; i++) { CF_RUNNING[i] = -1; CF_SUSPENDED[i] = NULL; } num = virConnectListDomains(CFVC[envtype], CF_RUNNING, CF_MAX_CONCURRENT_ENVIRONMENTS); CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Found %d running guest environments on this host (including enclosure)", num); ShowRunList(CFVC[envtype]); num = virConnectListDefinedDomains(CFVC[envtype], CF_SUSPENDED, CF_MAX_CONCURRENT_ENVIRONMENTS); CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Found %d dormant guest environments on this host", num); ShowDormant(); switch (a.env.state) { case ENVIRONMENT_STATE_CREATE: CreateVirtDom(ctx, CFVC[envtype], a, pp); break; case ENVIRONMENT_STATE_DELETE: DeleteVirt(ctx, CFVC[envtype], a, pp); break; case ENVIRONMENT_STATE_RUNNING: RunningVirt(ctx, CFVC[envtype], a, pp); break; case ENVIRONMENT_STATE_SUSPENDED: SuspendedVirt(ctx, CFVC[envtype], a, pp); break; case ENVIRONMENT_STATE_DOWN: DownVirt(ctx, CFVC[envtype], a, pp); break; default: CfOut(OUTPUT_LEVEL_INFORM, "", " !! No state specified for this environment"); break; } }
/* * Initialize connection. */ static bool virshInit(vshControl *ctl) { virshControlPtr priv = ctl->privData; /* Since we have the commandline arguments parsed, we need to * reload our initial settings to make debugging and readline * work properly */ vshInitReload(ctl); if (priv->conn) return false; /* set up the library error handler */ virSetErrorFunc(NULL, vshErrorHandler); if (virEventRegisterDefaultImpl() < 0) { vshReportError(ctl); return false; } if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0) { vshReportError(ctl); return false; } ctl->eventLoopStarted = true; if ((ctl->eventTimerId = virEventAddTimeout(-1, vshEventTimeout, ctl, NULL)) < 0) { vshReportError(ctl); return false; } if (ctl->connname) { /* Connecting to a named connection must succeed, but we delay * connecting to the default connection until we need it * (since the first command might be 'connect' which allows a * non-default connection, or might be 'help' which needs no * connection). */ if (virshReconnect(ctl, NULL, false, false) < 0) { vshReportError(ctl); return false; } } return true; }
virConnectPtr libvirtConnect(char *uri) { virConnectPtr cp; virSetErrorFunc("vmrunner", errHandler); domainIsOff = 0; lastErrorCode = 0; DPRINTF("Opening connection to hypervisor, uri %s\n", uri ? uri : "probed"); cp = virConnectOpen(uri); if (cp == NULL) { DPRINTF("virConnectOpen call failed\n"); return NULL; } DPRINTF("Connected to %s\n", virConnectGetURI(cp)); return cp; }
static int mymain(void) { int ret = 0; int status; virCommandPtr cmd; struct utsname ut; /* Skip test if xend is not running. Calling xend on a non-xen kernel causes some versions of xend to issue a crash report, so we first probe uname results. */ uname(&ut); if (strstr(ut.release, "xen") == NULL) return EXIT_AM_SKIP; cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL); if (virCommandRun(cmd, &status) != 0 || status != 0) { virCommandFree(cmd); return EXIT_AM_SKIP; } virCommandFree(cmd); /* Some of our tests deliberately test failure cases, so * register a handler to stop error messages cluttering * up display */ if (!virTestGetDebug()) virSetErrorFunc(NULL, testQuietError); #define DO_TEST(dev, num) \ do { \ struct testInfo info = { dev, num }; \ if (virtTestRun("Device " dev " -> " # num, \ 1, testDeviceHelper, &info) < 0) \ ret = -1; \ } while (0) /******************************** * Xen paravirt disks ********************************/ DO_TEST("xvd", -1); /* first valid disk */ DO_TEST("xvda", 51712); DO_TEST("xvda1", 51713); DO_TEST("xvda15", 51727); /* Last non-extended disk */ DO_TEST("xvdp", 51952); DO_TEST("xvdp1", 51953); DO_TEST("xvdp15", 51967); /* First extended disk */ DO_TEST("xvdq", 268439552); DO_TEST("xvdq1", 268439553); DO_TEST("xvdq15", 268439567); /* Last extended disk */ DO_TEST("xvdiz", 268501760); DO_TEST("xvdiz1", 268501761); DO_TEST("xvdiz15", 268501775); /* Disk letter too large */ DO_TEST("xvdja", -1); /* missing disk letter */ DO_TEST("xvd1", -1); /* partition too large */ DO_TEST("xvda16", -1); /* partition too small */ DO_TEST("xvda0", -1); /* leading zeros */ DO_TEST("xvda01", -1); /* leading + */ DO_TEST("xvda+1", -1); /* leading - */ DO_TEST("xvda-1", -1); /******************************** * IDE disks ********************************/ DO_TEST("hd", -1); /* first numbered disk */ DO_TEST("hda", 768); DO_TEST("hda1", 769); DO_TEST("hda63", 831); /* second numbered disk */ DO_TEST("hdb", 832); DO_TEST("hdb1", 833); DO_TEST("hdb63", 895); /* third numbered disk */ DO_TEST("hdc", 5632); DO_TEST("hdc1", 5633); DO_TEST("hdc63", 5695); /* fourth numbered disk */ DO_TEST("hdd", 5696); DO_TEST("hdd1", 5697); DO_TEST("hdd63", 5759); /* last valid disk */ DO_TEST("hdt", 23360); DO_TEST("hdt1", 23361); DO_TEST("hdt63", 23423); /* Disk letter to large */ DO_TEST("hdu", -1); /* missing disk letter */ DO_TEST("hd1", -1); /* partition too large */ DO_TEST("hda64", -1); /* partition too small */ DO_TEST("hda0", -1); /******************************** * SCSI disks ********************************/ DO_TEST("sd", -1); /* first valid disk */ DO_TEST("sda", 2048); DO_TEST("sda1", 2049); DO_TEST("sda15", 2063); /* last valid disk of first SCSI major number */ DO_TEST("sdp", 2288); DO_TEST("sdp1", 2289); DO_TEST("sdp15", 2303); /* first valid disk of second SCSI major number */ DO_TEST("sdq", 16640); DO_TEST("sdq1", 16641); DO_TEST("sdq15", 16655); /* last valid single letter disk */ DO_TEST("sdz", 16784); DO_TEST("sdz1", 16785); DO_TEST("sdz15", 16799); /* first valid dual letter disk */ DO_TEST("sdaa", 16800); DO_TEST("sdaa1", 16801); DO_TEST("sdaa15", 16815); /* second valid dual letter disk */ DO_TEST("sdab", 16816); DO_TEST("sdab1", 16817); DO_TEST("sdab15", 16831); /* first letter of second sequence of dual letter disk */ DO_TEST("sdba", 17216); DO_TEST("sdba1", 17217); DO_TEST("sdba15", 17231); /* last valid dual letter disk */ DO_TEST("sdiv", 34800); DO_TEST("sdiv1", 34801); DO_TEST("sdiv15", 34815); /* Disk letter too large */ DO_TEST("sdix", -1); /* missing disk letter */ DO_TEST("sd1", -1); /* partition too large */ DO_TEST("sda16", -1); /* partition too small */ DO_TEST("sda0", -1); /* Path stripping */ DO_TEST("/dev", -1); DO_TEST("/dev/", -1); DO_TEST("/dev/xvd", -1); DO_TEST("/dev/xvda", 51712); DO_TEST("/dev/xvda1", 51713); DO_TEST("/dev/xvda15", 51727); return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; }
void adopt_instances() { int dom_ids[MAXDOMS]; int num_doms = 0; int i; virDomainPtr dom = NULL; if (! check_hypervisor_conn()) return; logprintfl (EUCAINFO, "looking for existing domains\n"); virSetErrorFunc (NULL, libvirt_error_handler); num_doms = virConnectListDomains(nc_state.conn, dom_ids, MAXDOMS); if (num_doms == 0) { logprintfl (EUCAINFO, "no currently running domains to adopt\n"); return; } if (num_doms < 0) { logprintfl (EUCAWARN, "WARNING: failed to find out about running domains\n"); return; } for ( i=0; i<num_doms; i++) { int error; virDomainInfo info; const char * dom_name; ncInstance * instance; sem_p(hyp_sem); dom = virDomainLookupByID(nc_state.conn, dom_ids[i]); sem_v(hyp_sem); if (!dom) { logprintfl (EUCAWARN, "WARNING: failed to lookup running domain #%d, ignoring it\n", dom_ids[i]); continue; } sem_p(hyp_sem); error = virDomainGetInfo(dom, &info); sem_v(hyp_sem); if (error < 0 || info.state == VIR_DOMAIN_NOSTATE) { logprintfl (EUCAWARN, "WARNING: failed to get info on running domain #%d, ignoring it\n", dom_ids[i]); continue; } if (info.state == VIR_DOMAIN_SHUTDOWN || info.state == VIR_DOMAIN_SHUTOFF || info.state == VIR_DOMAIN_CRASHED ) { logprintfl (EUCADEBUG, "ignoring non-running domain #%d\n", dom_ids[i]); continue; } sem_p(hyp_sem); if ((dom_name = virDomainGetName(dom))==NULL) { sem_v(hyp_sem); logprintfl (EUCAWARN, "WARNING: failed to get name of running domain #%d, ignoring it\n", dom_ids[i]); continue; } sem_v(hyp_sem); if (!strcmp(dom_name, "Domain-0")) continue; if ((instance = scRecoverInstanceInfo (dom_name))==NULL) { logprintfl (EUCAWARN, "WARNING: failed to recover Eucalyptus metadata of running domain %s, ignoring it\n", dom_name); continue; } change_state (instance, info.state); sem_p (inst_sem); int err = add_instance (&global_instances, instance); sem_v (inst_sem); if (err) { free_instance (&instance); continue; } logprintfl (EUCAINFO, "- adopted running domain %s from user %s\n", instance->instanceId, instance->userId); /* TODO: try to look up IPs? */ sem_p(hyp_sem); virDomainFree (dom); sem_v(hyp_sem); } }
static int mymain(void) { int ret = 0; /* Some of our tests deliberately test failure cases, so * register a handler to stop error messages cluttering * up display */ if (!virTestGetDebug()) virSetErrorFunc(NULL, testQuietError); #define DO_TEST_PARSE(addrstr, family, pass) \ do { \ virSocketAddr addr; \ struct testParseData data = { &addr, addrstr, family, pass }; \ memset(&addr, 0, sizeof(addr)); \ if (virtTestRun("Test parse " addrstr, \ 1, testParseHelper, &data) < 0) \ ret = -1; \ } while (0) #define DO_TEST_PARSE_AND_FORMAT(addrstr, family, pass) \ do { \ virSocketAddr addr; \ struct testParseData data = { &addr, addrstr, family, pass }; \ memset(&addr, 0, sizeof(addr)); \ if (virtTestRun("Test parse " addrstr " family " #family, \ 1, testParseHelper, &data) < 0) \ ret = -1; \ struct testFormatData data2 = { &addr, addrstr, pass }; \ if (virtTestRun("Test format " addrstr " family " #family, \ 1, testFormatHelper, &data2) < 0) \ ret = -1; \ } while (0) #define DO_TEST_RANGE(saddr, eaddr, size, pass) \ do { \ struct testRangeData data = { saddr, eaddr, size, pass }; \ if (virtTestRun("Test range " saddr " -> " eaddr " size " #size, \ 1, testRangeHelper, &data) < 0) \ ret = -1; \ } while (0) #define DO_TEST_NETMASK(addr1, addr2, netmask, pass) \ do { \ struct testNetmaskData data = { addr1, addr2, netmask, pass }; \ if (virtTestRun("Test netmask " addr1 " + " addr2 " in " netmask, \ 1, testNetmaskHelper, &data) < 0) \ ret = -1; \ } while (0) DO_TEST_PARSE_AND_FORMAT("127.0.0.1", AF_UNSPEC, true); DO_TEST_PARSE_AND_FORMAT("127.0.0.1", AF_INET, true); DO_TEST_PARSE_AND_FORMAT("127.0.0.1", AF_INET6, false); DO_TEST_PARSE_AND_FORMAT("127.0.0.1", AF_UNIX, false); DO_TEST_PARSE_AND_FORMAT("127.0.0.256", AF_UNSPEC, false); DO_TEST_PARSE_AND_FORMAT("::1", AF_UNSPEC, true); DO_TEST_PARSE_AND_FORMAT("::1", AF_INET, false); DO_TEST_PARSE_AND_FORMAT("::1", AF_INET6, true); DO_TEST_PARSE_AND_FORMAT("::1", AF_UNIX, false); DO_TEST_PARSE_AND_FORMAT("::ffff", AF_UNSPEC, true); DO_TEST_RANGE("192.168.122.1", "192.168.122.1", 1, true); DO_TEST_RANGE("192.168.122.1", "192.168.122.20", 20, true); DO_TEST_RANGE("192.168.122.0", "192.168.122.255", 256, true); DO_TEST_RANGE("192.168.122.20", "192.168.122.1", -1, false); DO_TEST_RANGE("10.0.0.1", "192.168.122.20", -1, false); DO_TEST_RANGE("192.168.122.20", "10.0.0.1", -1, false); DO_TEST_RANGE("2000::1", "2000::1", 1, true); DO_TEST_RANGE("2000::1", "2000::2", 2, true); DO_TEST_RANGE("2000::2", "2000::1", -1, false); DO_TEST_RANGE("2000::1", "9001::1", -1, false); DO_TEST_NETMASK("192.168.122.1", "192.168.122.2", "255.255.255.0", true); DO_TEST_NETMASK("192.168.122.1", "192.168.122.4", "255.255.255.248", true); DO_TEST_NETMASK("192.168.122.1", "192.168.123.2", "255.255.255.0", false); DO_TEST_NETMASK("192.168.122.1", "192.168.123.2", "255.255.0.0", true); DO_TEST_NETMASK("2000::1:1", "2000::1:1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0", true); DO_TEST_NETMASK("2000::1:1", "2000::2:1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0", false); DO_TEST_NETMASK("2000::1:1", "2000::2:1", "ffff:ffff:ffff:ffff:ffff:ffff:fff8:0", true); DO_TEST_NETMASK("2000::1:1", "9000::1:1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0", false); return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); }
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; }