Beispiel #1
0
static char *
openvzGenerateContainerVethName(int veid)
{
    char *temp = NULL;
    char *name = NULL;

    /* try to get line "^NETIF=..." from config */
    if (openvzReadVPSConfigParam(veid, "NETIF", &temp) <= 0) {
        name = strdup("eth0");
    } else {
        char *saveptr = NULL;
        char *s;
        int max = 0;

        /* get maximum interface number (actually, it is the last one) */
        for (s=strtok_r(temp, ";", &saveptr); s; s=strtok_r(NULL, ";", &saveptr)) {
            int x;

            if (sscanf(s, "ifname=eth%d", &x) != 1) return NULL;
            if (x > max) max = x;
        }

        /* set new name */
        ignore_value(virAsprintf(&name, "eth%d", max + 1));
    }

    VIR_FREE(temp);

    if (name == NULL) {
        virReportOOMError();
    }

    return name;
}
Beispiel #2
0
static int
openvzDomainGetAutostart(virDomainPtr dom, int *autostart)
{
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *value = NULL;
    int ret = -1;

    openvzDriverLock(driver);
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
    openvzDriverUnlock(driver);

    if (!vm) {
        openvzError(VIR_ERR_NO_DOMAIN, "%s",
                    _("no domain with matching uuid"));
        goto cleanup;
    }

    if (openvzReadVPSConfigParam(strtoI(vm->def->name), "ONBOOT", &value) < 0) {
        openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("Could not read container config"));
        goto cleanup;
    }

    *autostart = 0;
    if (STREQ(value,"yes"))
        *autostart = 1;
    ret = 0;

cleanup:
    VIR_FREE(value);

    if (vm)
        virDomainObjUnlock(vm);
    return ret;
}
Beispiel #3
0
int openvzLoadDomains(struct openvz_driver *driver)
{
    int veid, ret;
    char *status;
    char uuidstr[VIR_UUID_STRING_BUFLEN];
    virDomainObjPtr dom = NULL;
    virDomainDefPtr def = NULL;
    char *temp = NULL;
    char *outbuf = NULL;
    char *line;
    virCommandPtr cmd = NULL;
    unsigned int vcpus = 0;

    if (openvzAssignUUIDs() < 0)
        return -1;

    cmd = virCommandNewArgList(VZLIST, "-a", "-ovpsid,status", "-H", NULL);
    virCommandSetOutputBuffer(cmd, &outbuf);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    line = outbuf;
    while (line[0] != '\0') {
        unsigned int flags = 0;
        if (virStrToLong_i(line, &status, 10, &veid) < 0 ||
            *status++ != ' ' ||
            (line = strchr(status, '\n')) == NULL) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Failed to parse vzlist output"));
            goto cleanup;
        }
        *line++ = '\0';

        if (!(def = virDomainDefNew()))
            goto cleanup;

        def->virtType = VIR_DOMAIN_VIRT_OPENVZ;

        if (STREQ(status, "stopped"))
            def->id = -1;
        else
            def->id = veid;
        if (virAsprintf(&def->name, "%i", veid) < 0)
            goto cleanup;

        openvzGetVPSUUID(veid, uuidstr, sizeof(uuidstr));
        ret = virUUIDParse(uuidstr, def->uuid);

        if (ret == -1) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("UUID in config file malformed"));
            goto cleanup;
        }

        def->os.type = VIR_DOMAIN_OSTYPE_EXE;
        if (VIR_STRDUP(def->os.init, "/sbin/init") < 0)
            goto cleanup;

        ret = openvzReadVPSConfigParam(veid, "CPUS", &temp);
        if (ret < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not read config for container %d"),
                           veid);
            goto cleanup;
        } else if (ret > 0) {
            vcpus = strtoI(temp);
        }

        if (ret == 0 || vcpus == 0)
            vcpus = openvzGetNodeCPUs();

        def->maxvcpus = vcpus;
        def->vcpus = vcpus;

        /* XXX load rest of VM config data .... */

        openvzReadNetworkConf(def, veid);
        openvzReadFSConf(def, veid);
        openvzReadMemConf(def, veid);

        virUUIDFormat(def->uuid, uuidstr);
        flags = VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE;
        if (STRNEQ(status, "stopped"))
            flags |= VIR_DOMAIN_OBJ_LIST_ADD_LIVE;

        if (!(dom = virDomainObjListAdd(driver->domains,
                                        def,
                                        driver->xmlopt,
                                        flags,
                                        NULL)))
            goto cleanup;

        if (STREQ(status, "stopped")) {
            virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF,
                                 VIR_DOMAIN_SHUTOFF_UNKNOWN);
            dom->pid = -1;
        } else {
            virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
                                 VIR_DOMAIN_RUNNING_UNKNOWN);
            dom->pid = veid;
        }
        /* XXX OpenVZ doesn't appear to have concept of a transient domain */
        dom->persistent = 1;

        virObjectUnlock(dom);
        dom = NULL;
        def = NULL;
    }

    virCommandFree(cmd);
    VIR_FREE(temp);
    VIR_FREE(outbuf);

    return 0;

 cleanup:
    virCommandFree(cmd);
    VIR_FREE(temp);
    VIR_FREE(outbuf);
    virObjectUnref(dom);
    virDomainDefFree(def);
    return -1;
}
Beispiel #4
0
static int
openvzReadMemConf(virDomainDefPtr def, int veid)
{
    int ret = -1;
    char *temp = NULL;
    unsigned long long barrier, limit;
    const char *param;
    long kb_per_pages;

    kb_per_pages = openvzKBPerPages();
    if (kb_per_pages < 0)
        goto error;

    /* Memory allocation guarantee */
    param = "VMGUARPAGES";
    ret = openvzReadVPSConfigParam(veid, param, &temp);
    if (ret < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not read '%s' from config for container %d"),
                       param, veid);
        goto error;
    } else if (ret > 0) {
        ret = openvzParseBarrierLimit(temp, &barrier, NULL);
        if (ret < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not parse barrier of '%s' "
                             "from config for container %d"), param, veid);
            goto error;
        }
        if (barrier == LONG_MAX)
            def->mem.min_guarantee = 0ull;
        else
            def->mem.min_guarantee = barrier * kb_per_pages;
    }

    /* Memory hard and soft limits */
    param = "PRIVVMPAGES";
    ret = openvzReadVPSConfigParam(veid, param, &temp);
    if (ret < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not read '%s' from config for container %d"),
                       param, veid);
        goto error;
    } else if (ret > 0) {
        ret = openvzParseBarrierLimit(temp, &barrier, &limit);
        if (ret < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not parse barrier and limit of '%s' "
                             "from config for container %d"), param, veid);
            goto error;
        }
        if (barrier == LONG_MAX)
            def->mem.soft_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
        else
            def->mem.soft_limit = barrier * kb_per_pages;

        if (limit == LONG_MAX)
            def->mem.hard_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
        else
            def->mem.hard_limit = limit * kb_per_pages;
    }

    ret = 0;
 error:
    VIR_FREE(temp);
    return ret;
}
Beispiel #5
0
static int
openvzReadFSConf(virDomainDefPtr def,
                 int veid)
{
    int ret;
    virDomainFSDefPtr fs = NULL;
    char *veid_str = NULL;
    char *temp = NULL;
    const char *param;
    unsigned long long barrier, limit;

    ret = openvzReadVPSConfigParam(veid, "OSTEMPLATE", &temp);
    if (ret < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not read 'OSTEMPLATE' from config for container %d"),
                       veid);
        goto error;
    } else if (ret > 0) {
        if (VIR_ALLOC(fs) < 0)
            goto error;

        fs->type = VIR_DOMAIN_FS_TYPE_TEMPLATE;
        if (VIR_STRDUP(fs->src, temp) < 0)
            goto error;
    } else {
        /* OSTEMPLATE was not found, VE was booted from a private dir directly */
        ret = openvzReadVPSConfigParam(veid, "VE_PRIVATE", &temp);
        if (ret <= 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not read 'VE_PRIVATE' from config for container %d"),
                           veid);
            goto error;
        }

        if (VIR_ALLOC(fs) < 0)
            goto error;

        if (virAsprintf(&veid_str, "%d", veid) < 0)
            goto error;

        fs->type = VIR_DOMAIN_FS_TYPE_MOUNT;
        if (!(fs->src = virStringReplace(temp, "$VEID", veid_str)))
            goto error;

        VIR_FREE(veid_str);
    }

    if (VIR_STRDUP(fs->dst, "/") < 0)
        goto error;

    param = "DISKSPACE";
    ret = openvzReadVPSConfigParam(veid, param, &temp);
    if (ret > 0) {
        if (openvzParseBarrierLimit(temp, &barrier, &limit)) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not read '%s' from config for container %d"),
                           param, veid);
            goto error;
        } else {
            /* Ensure that we can multiply by 1024 without overflowing. */
            if (barrier > ULLONG_MAX / 1024 ||
                limit > ULLONG_MAX / 1024) {
                virReportError(VIR_ERR_OVERFLOW, "%s",
                               _("Unable to parse quota"));
                goto error;
            }
            fs->space_soft_limit = barrier * 1024; /* unit is bytes */
            fs->space_hard_limit = limit * 1024;   /* unit is bytes */
        }
    }

    if (VIR_APPEND_ELEMENT(def->fss, def->nfss, fs) < 0)
        goto error;

    VIR_FREE(temp);

    return 0;
 error:
    VIR_FREE(temp);
    virDomainFSDefFree(fs);
    return -1;
}
Beispiel #6
0
int
openvzReadNetworkConf(virDomainDefPtr def,
                      int veid)
{
    int ret;
    virDomainNetDefPtr net = NULL;
    char *temp = NULL;
    char *token, *saveptr = NULL;

    /*parse routing network configuration*
     * Sample from config:
     *   IP_ADDRESS="1.1.1.1 1.1.1.2"
     * IPs split by space
     */
    ret = openvzReadVPSConfigParam(veid, "IP_ADDRESS", &temp);
    if (ret < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not read 'IP_ADDRESS' from config for container %d"),
                       veid);
        goto error;
    } else if (ret > 0) {
        token = strtok_r(temp, " ", &saveptr);
        while (token != NULL) {
            if (VIR_ALLOC(net) < 0)
                goto error;

            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
            if (virDomainNetAppendIpAddress(net, token, AF_UNSPEC, 0) < 0)
                goto error;

            if (VIR_APPEND_ELEMENT_COPY(def->nets, def->nnets, net) < 0)
                goto error;

            token = strtok_r(NULL, " ", &saveptr);
        }
    }

    /*parse bridge devices*/
    /*Sample from config:
     * NETIF="ifname=eth10,mac=00:18:51:C1:05:EE,host_ifname=veth105.10,host_mac=00:18:51:8F:D9:F3"
     *devices split by ';'
     */
    ret = openvzReadVPSConfigParam(veid, "NETIF", &temp);
    if (ret < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not read 'NETIF' from config for container %d"),
                       veid);
        goto error;
    } else if (ret > 0) {
        token = strtok_r(temp, ";", &saveptr);
        while (token != NULL) {
            /*add new device to list*/
            if (VIR_ALLOC(net) < 0)
                goto error;

            net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;

            char *p = token;
            char cpy_temp[32];
            int len;

            /*parse string*/
            do {
                char *next = strchrnul(p, ',');
                if (STRPREFIX(p, "ifname=")) {
                    /* skip in libvirt */
                } else if (STRPREFIX(p, "host_ifname=")) {
                    p += 12;
                    len = next - p;
                    if (len > 16) {
                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                       _("Too long network device name"));
                        goto error;
                    }

                    if (VIR_ALLOC_N(net->ifname, len+1) < 0)
                        goto error;

                    if (virStrncpy(net->ifname, p, len, len+1) == NULL) {
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("Network ifname %s too long for destination"), p);
                        goto error;
                    }
                } else if (STRPREFIX(p, "bridge=")) {
                    p += 7;
                    len = next - p;
                    if (len > 16) {
                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                       _("Too long bridge device name"));
                        goto error;
                    }

                    if (VIR_ALLOC_N(net->data.bridge.brname, len+1) < 0)
                        goto error;

                    if (virStrncpy(net->data.bridge.brname, p, len, len+1) == NULL) {
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("Bridge name %s too long for destination"), p);
                        goto error;
                    }
                } else if (STRPREFIX(p, "mac=")) {
                    p += 4;
                    len = next - p;
                    if (len != 17) { /* should be 17 */
                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                       _("Wrong length MAC address"));
                        goto error;
                    }
                    if (virStrncpy(cpy_temp, p, len, sizeof(cpy_temp)) == NULL) {
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("MAC address %s too long for destination"), p);
                        goto error;
                    }
                    if (virMacAddrParse(cpy_temp, &net->mac) < 0) {
                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                       _("Wrong MAC address"));
                        goto error;
                    }
                }
                p = ++next;
            } while (p < token + strlen(token));

            if (VIR_APPEND_ELEMENT_COPY(def->nets, def->nnets, net) < 0)
                goto error;

            token = strtok_r(NULL, ";", &saveptr);
        }
    }

    VIR_FREE(temp);

    return 0;

 error:
    VIR_FREE(temp);
    virDomainNetDefFree(net);
    return -1;
}