Esempio n. 1
0
static void
test_ascii (guestfs_h *g, const struct filesystem *fs)
{
  char **files;
  size_t count;

  /* Create various ASCII-named files. */
  if (guestfs_touch (g, "/ABC") == -1)
    exit (EXIT_FAILURE);
  if (guestfs_touch (g, "/def") == -1)
    exit (EXIT_FAILURE);
  if (guestfs_touch (g, "/abc") == -1)
    exit (EXIT_FAILURE);

  /* Read list of files, check for case sensitivity. */
  files = guestfs_ls (g, "/");
  if (files == NULL)
    exit (EXIT_FAILURE);
  ignore_lost_and_found (files);
  count = guestfs___count_strings (files);

  if (fs->fs_case_insensitive) { /* case insensitive */
    if (count != 2)
      error (EXIT_FAILURE, 0,
             "error: %s: %s is supposed to be case-insensitive, but %zu files "
             "(instead of 2) were returned",
             __func__, fs->fs_name, count);

    if (STRCASENEQ (files[0], "abc") ||
        STRCASENEQ (files[1], "def"))
      error (EXIT_FAILURE, 0,
             "error: %s: %s returned unexpected filenames '%s' and '%s'",
             __func__, fs->fs_name, files[0], files[1]);
  }
  else {                        /* case sensitive */
    if (count != 3)
      error (EXIT_FAILURE, 0,
             "error: %s: %s is supposed to be case-sensitive, but %zu files "
             "(instead of 3) were returned",
             __func__, fs->fs_name, count);

    if (STRNEQ (files[0], "ABC") == -1 ||
        STRNEQ (files[1], "abc") == -1 ||
        STRNEQ (files[2], "def") == -1)
      error (EXIT_FAILURE, 0,
             "error: %s: %s returned unexpected filenames '%s', '%s', '%s'",
             __func__, fs->fs_name, files[0], files[1], files[2]);

    if (guestfs_rm (g, "/abc") == -1)
      exit (EXIT_FAILURE);
  }

  if (guestfs_rm (g, "/ABC") == -1)
    exit (EXIT_FAILURE);
  if (guestfs_rm (g, "/def") == -1)
    exit (EXIT_FAILURE);
}
Esempio n. 2
0
/* Matches Windows registry HKLM\SYSYTEM\MountedDevices\DosDevices blob to
 * to libguestfs GPT partition device. For GPT disks, the blob is made of
 * "DMIO:ID:" prefix followed by the GPT partition GUID.
 */
static char *
map_registry_disk_blob_gpt (guestfs_h *g, const void *blob)
{
  CLEANUP_FREE_STRING_LIST char **parts = NULL;
  CLEANUP_FREE char *blob_guid = extract_guid_from_registry_blob (g, blob);
  size_t i;

  parts = guestfs_list_partitions (g);
  if (parts == NULL)
    return NULL;

  for (i = 0; parts[i] != NULL; ++i) {
    CLEANUP_FREE char *fs_guid = NULL;
    int partnum;
    CLEANUP_FREE char *device = NULL;
    CLEANUP_FREE char *type = NULL;

    partnum = guestfs_part_to_partnum (g, parts[i]);
    if (partnum == -1)
      continue;

    device = guestfs_part_to_dev (g, parts[i]);
    if (device == NULL)
      continue;

    type = guestfs_part_get_parttype (g, device);
    if (type == NULL)
      continue;

    if (STRCASENEQ (type, "gpt"))
      continue;

    /* get the GPT parition GUID from the partition block device */
    fs_guid = guestfs_part_get_gpt_guid (g, device, partnum);
    if (fs_guid == NULL)
      continue;

    /* if both GUIDs match, we have found the mapping for our device */
    if (STRCASEEQ (fs_guid, blob_guid))
      return safe_strdup (g, parts[i]);
  }

  return NULL;
}
Esempio n. 3
0
int
virNetDevVlanParse(xmlNodePtr node, xmlXPathContextPtr ctxt, virNetDevVlanPtr def)
{
    int ret = -1;
    xmlNodePtr save = ctxt->node;
    char *trunk = NULL;
    char *nativeMode = NULL;
    xmlNodePtr *tagNodes = NULL;
    int nTags;
    size_t i;

    ctxt->node = node;

    nTags = virXPathNodeSet("./tag", ctxt, &tagNodes);
    if (nTags < 0)
        goto cleanup;

    if (nTags == 0) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing tag id - each <vlan> must have "
                         "at least one <tag id='n'/> subelement"));
        goto cleanup;
    }

    if (VIR_ALLOC_N(def->tag, nTags) < 0)
        goto cleanup;

    def->nativeMode = 0;
    def->nativeTag = 0;
    for (i = 0; i < nTags; i++) {
        unsigned long id;

        ctxt->node = tagNodes[i];
        if (virXPathULong("string(./@id)", ctxt, &id) < 0) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing or invalid vlan tag id attribute"));
            goto cleanup;
        }
        if (id > 4095) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("vlan tag id %lu too large (maximum 4095)"), id);
            goto cleanup;
        }
        if ((nativeMode = virXPathString("string(./@nativeMode)", ctxt))) {
            if (def->nativeMode != 0) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("duplicate native vlan setting"));
                goto cleanup;
            }
            if ((def->nativeMode
                 = virNativeVlanModeTypeFromString(nativeMode)) <= 0) {
                virReportError(VIR_ERR_XML_ERROR,
                               _("Invalid \"nativeMode='%s'\" "
                                 "in vlan <tag> element"),
                               nativeMode);
                goto cleanup;
            }
            VIR_FREE(nativeMode);
            def->nativeTag = id;
        }
        def->tag[i] = id;
    }

    def->nTags = nTags;

    /* now that we know how many tags there are, look for an explicit
     * trunk setting.
     */
    if (nTags > 1)
        def->trunk = true;

    ctxt->node = node;
    if ((trunk = virXPathString("string(./@trunk)", ctxt)) != NULL) {
        def->trunk = STRCASEEQ(trunk, "yes");
        if (!def->trunk) {
            if (nTags > 1) {
                virReportError(VIR_ERR_XML_ERROR,
                               _("invalid \"trunk='%s'\" in <vlan> - trunk='yes' "
                                 "is required for more than one vlan tag"), trunk);
                goto cleanup;
            }
            if (def->nativeMode != 0) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("invalid configuration in <vlan> - \"trunk='no'\" is "
                                 "not allowed with a native vlan id"));
                goto cleanup;
            }
            /* allow (but discard) "trunk='no' if there is a single tag */
            if (STRCASENEQ(trunk, "no")) {
                virReportError(VIR_ERR_XML_ERROR,
                               _("invalid \"trunk='%s'\" in <vlan> "
                                 "- must be yes or no"), trunk);
                goto cleanup;
            }
        }
    }

    ret = 0;
cleanup:
    ctxt->node = save;
    VIR_FREE(tagNodes);
    VIR_FREE(trunk);
    VIR_FREE(nativeMode);
    if (ret < 0)
        virNetDevVlanClear(def);
    return ret;
}
Esempio n. 4
0
/**
 * virNumaGetPages:
 * @node: NUMA node id
 * @pages_size: list of pages supported on @node
 * @pages_avail: list of the pool sizes on @node
 * @pages_free: list of free pages on @node
 * @npages: the lists size
 *
 * For given NUMA node fetch info on pages. The size of pages
 * (e.g.  4K, 2M, 1G) is stored into @pages_size, the size of the
 * pool is then stored into @pages_avail and the number of free
 * pages in the pool is stored into @pages_free.
 *
 * If you're interested only in some lists, pass NULL to the
 * other ones.
 *
 * As a special case, if @node == -1, overall info is fetched
 * from the system.
 *
 * Returns 0 on success, -1 otherwise.
 */
int
virNumaGetPages(int node,
                unsigned int **pages_size,
                unsigned int **pages_avail,
                unsigned int **pages_free,
                size_t *npages)
{
    int ret = -1;
    char *path = NULL;
    DIR *dir = NULL;
    int direrr = 0;
    struct dirent *entry;
    unsigned int *tmp_size = NULL, *tmp_avail = NULL, *tmp_free = NULL;
    unsigned int ntmp = 0;
    size_t i;
    bool exchange;
    long system_page_size;
    unsigned long long huge_page_sum = 0;

    /* sysconf() returns page size in bytes,
     * but we are storing the page size in kibibytes. */
    system_page_size = virGetSystemPageSizeKB();

    /* Query huge pages at first.
     * On Linux systems, the huge pages pool cuts off the available memory and
     * is always shown as used memory. Here, however, we want to report
     * slightly different information. So we take the total memory on a node
     * and subtract memory taken by the huge pages. */
    if (virNumaGetHugePageInfoPath(&path, node, 0, NULL) < 0)
        goto cleanup;

    if (!(dir = opendir(path))) {
        /* It's okay if the @path doesn't exist. Maybe we are running on
         * system without huge pages support where the path may not exist. */
        if (errno != ENOENT) {
            virReportSystemError(errno,
                                 _("unable to open path: %s"),
                                 path);
            goto cleanup;
        }
    }

    while (dir && (direrr = virDirRead(dir, &entry, path)) > 0) {
        const char *page_name = entry->d_name;
        unsigned int page_size, page_avail = 0, page_free = 0;
        char *end;

        /* Just to give you a hint, we're dealing with this:
         * hugepages-2048kB/  or   hugepages-1048576kB/ */
        if (!STRPREFIX(entry->d_name, HUGEPAGES_PREFIX))
            continue;

        page_name += strlen(HUGEPAGES_PREFIX);

        if (virStrToLong_ui(page_name, &end, 10, &page_size) < 0 ||
                STRCASENEQ(end, "kB")) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unable to parse %s"),
                           entry->d_name);
            goto cleanup;
        }

        if (virNumaGetHugePageInfo(node, page_size,
                                   &page_avail, &page_free) < 0)
            goto cleanup;

        if (VIR_REALLOC_N(tmp_size, ntmp + 1) < 0 ||
                VIR_REALLOC_N(tmp_avail, ntmp + 1) < 0 ||
                VIR_REALLOC_N(tmp_free, ntmp + 1) < 0)
            goto cleanup;

        tmp_size[ntmp] = page_size;
        tmp_avail[ntmp] = page_avail;
        tmp_free[ntmp] = page_free;
        ntmp++;

        /* page_size is in kibibytes while we want huge_page_sum
         * in just bytes. */
        huge_page_sum += 1024 * page_size * page_avail;
    }

    if (direrr < 0)
        goto cleanup;

    /* Now append the ordinary system pages */
    if (VIR_REALLOC_N(tmp_size, ntmp + 1) < 0 ||
            VIR_REALLOC_N(tmp_avail, ntmp + 1) < 0 ||
            VIR_REALLOC_N(tmp_free, ntmp + 1) < 0)
        goto cleanup;

    if (virNumaGetPageInfo(node, system_page_size, huge_page_sum,
                           &tmp_avail[ntmp], &tmp_free[ntmp]) < 0)
        goto cleanup;
    tmp_size[ntmp] = system_page_size;
    ntmp++;

    /* Just to produce nice output, sort the arrays by increasing page size */
    do {
        exchange = false;
        for (i = 0; i < ntmp -1; i++) {
            if (tmp_size[i] > tmp_size[i + 1]) {
                exchange = true;
                SWAP(tmp_size[i], tmp_size[i + 1]);
                SWAP(tmp_avail[i], tmp_avail[i + 1]);
                SWAP(tmp_free[i], tmp_free[i + 1]);
            }
        }
    } while (exchange);

    if (pages_size) {
        *pages_size = tmp_size;
        tmp_size = NULL;
    }
    if (pages_avail) {
        *pages_avail = tmp_avail;
        tmp_avail = NULL;
    }
    if (pages_free) {
        *pages_free = tmp_free;
        tmp_free = NULL;
    }
    *npages = ntmp;
    ret = 0;
cleanup:
    VIR_FREE(tmp_free);
    VIR_FREE(tmp_avail);
    VIR_FREE(tmp_size);
    if (dir)
        closedir(dir);
    VIR_FREE(path);
    return ret;
}
static virDrvOpenStatus
hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
{
    virDrvOpenStatus result = VIR_DRV_OPEN_ERROR;
    char *plus;
    hypervPrivate *priv = NULL;
    char *username = NULL;
    char *password = NULL;
    virBuffer query = VIR_BUFFER_INITIALIZER;
    Msvm_ComputerSystem *computerSystem = NULL;

    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

    /* Decline if the URI is NULL or the scheme is NULL */
    if (conn->uri == NULL || conn->uri->scheme == NULL) {
        return VIR_DRV_OPEN_DECLINED;
    }

    /* Decline if the scheme is not hyperv */
    plus = strchr(conn->uri->scheme, '+');

    if (plus == NULL) {
        if (STRCASENEQ(conn->uri->scheme, "hyperv")) {
            return VIR_DRV_OPEN_DECLINED;
        }
    } else {
        if (plus - conn->uri->scheme != 6 ||
            STRCASENEQLEN(conn->uri->scheme, "hyperv", 6)) {
            return VIR_DRV_OPEN_DECLINED;
        }

        virReportError(VIR_ERR_INVALID_ARG,
                       _("Transport '%s' in URI scheme is not supported, try again "
                         "without the transport part"), plus + 1);
        return VIR_DRV_OPEN_ERROR;
    }

    /* Require server part */
    if (conn->uri->server == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("URI is missing the server part"));
        return VIR_DRV_OPEN_ERROR;
    }

    /* Require auth */
    if (auth == NULL || auth->cb == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("Missing or invalid auth pointer"));
        return VIR_DRV_OPEN_ERROR;
    }

    /* Allocate per-connection private data */
    if (VIR_ALLOC(priv) < 0)
        goto cleanup;

    if (hypervParseUri(&priv->parsedUri, conn->uri) < 0) {
        goto cleanup;
    }

    /* Set the port dependent on the transport protocol if no port is
     * specified. This allows us to rely on the port parameter being
     * correctly set when building URIs later on, without the need to
     * distinguish between the situations port == 0 and port != 0 */
    if (conn->uri->port == 0) {
        if (STRCASEEQ(priv->parsedUri->transport, "https")) {
            conn->uri->port = 5986;
        } else {
            conn->uri->port = 5985;
        }
    }

    /* Request credentials */
    if (conn->uri->user != NULL) {
        if (VIR_STRDUP(username, conn->uri->user) < 0)
            goto cleanup;
    } else {
        username = virAuthGetUsername(conn, auth, "hyperv", "administrator", conn->uri->server);

        if (username == NULL) {
            virReportError(VIR_ERR_AUTH_FAILED, "%s", _("Username request failed"));
            goto cleanup;
        }
    }

    password = virAuthGetPassword(conn, auth, "hyperv", username, conn->uri->server);

    if (password == NULL) {
        virReportError(VIR_ERR_AUTH_FAILED, "%s", _("Password request failed"));
        goto cleanup;
    }

    /* Initialize the openwsman connection */
    priv->client = wsmc_create(conn->uri->server, conn->uri->port, "/wsman",
                               priv->parsedUri->transport, username, password);

    if (priv->client == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Could not create openwsman client"));
        goto cleanup;
    }

    if (wsmc_transport_init(priv->client, NULL) != 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Could not initialize openwsman transport"));
        goto cleanup;
    }

    /* FIXME: Currently only basic authentication is supported  */
    wsman_transport_set_auth_method(priv->client, "basic");

    /* Check if the connection can be established and if the server has the
     * Hyper-V role installed. If the call to hypervGetMsvmComputerSystemList
     * succeeds than the connection has been established. If the returned list
     * is empty than the server isn't a Hyper-V server. */
    virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
    virBufferAddLit(&query, "where ");
    virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_PHYSICAL);

    if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) {
        goto cleanup;
    }

    if (computerSystem == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("%s is not a Hyper-V server"), conn->uri->server);
        goto cleanup;
    }

    conn->privateData = priv;
    priv = NULL;
    result = VIR_DRV_OPEN_SUCCESS;

 cleanup:
    hypervFreePrivate(&priv);
    VIR_FREE(username);
    VIR_FREE(password);
    hypervFreeObject(priv, (hypervObject *)computerSystem);

    return result;
}
Esempio n. 6
0
static virDrvOpenStatus
hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
                  virConfPtr conf ATTRIBUTE_UNUSED,
                  unsigned int flags)
{
    virDrvOpenStatus result = VIR_DRV_OPEN_ERROR;
    char *plus;
    hypervPrivate *priv = NULL;
    char *username = NULL;
    char *password = NULL;

    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

    /* Decline if the URI is NULL or the scheme is NULL */
    if (conn->uri == NULL || conn->uri->scheme == NULL)
        return VIR_DRV_OPEN_DECLINED;

    /* Decline if the scheme is not hyperv */
    plus = strchr(conn->uri->scheme, '+');

    if (plus == NULL) {
        if (STRCASENEQ(conn->uri->scheme, "hyperv"))
            return VIR_DRV_OPEN_DECLINED;
    } else {
        if (plus - conn->uri->scheme != 6 ||
            STRCASENEQLEN(conn->uri->scheme, "hyperv", 6)) {
            return VIR_DRV_OPEN_DECLINED;
        }

        virReportError(VIR_ERR_INVALID_ARG,
                       _("Transport '%s' in URI scheme is not supported, try again "
                         "without the transport part"), plus + 1);
        return VIR_DRV_OPEN_ERROR;
    }

    /* Require server part */
    if (conn->uri->server == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("URI is missing the server part"));
        return VIR_DRV_OPEN_ERROR;
    }

    /* Require auth */
    if (auth == NULL || auth->cb == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("Missing or invalid auth pointer"));
        return VIR_DRV_OPEN_ERROR;
    }

    /* Allocate per-connection private data */
    if (VIR_ALLOC(priv) < 0)
        goto cleanup;

    if (hypervParseUri(&priv->parsedUri, conn->uri) < 0)
        goto cleanup;

    /* Set the port dependent on the transport protocol if no port is
     * specified. This allows us to rely on the port parameter being
     * correctly set when building URIs later on, without the need to
     * distinguish between the situations port == 0 and port != 0 */
    if (conn->uri->port == 0) {
        if (STRCASEEQ(priv->parsedUri->transport, "https")) {
            conn->uri->port = 5986;
        } else {
            conn->uri->port = 5985;
        }
    }

    /* Request credentials */
    if (conn->uri->user != NULL) {
        if (VIR_STRDUP(username, conn->uri->user) < 0)
            goto cleanup;
    } else {
        username = virAuthGetUsername(conn, auth, "hyperv", "administrator", conn->uri->server);

        if (username == NULL) {
            virReportError(VIR_ERR_AUTH_FAILED, "%s", _("Username request failed"));
            goto cleanup;
        }
    }

    password = virAuthGetPassword(conn, auth, "hyperv", username, conn->uri->server);

    if (password == NULL) {
        virReportError(VIR_ERR_AUTH_FAILED, "%s", _("Password request failed"));
        goto cleanup;
    }


    if (hypervInitConnection(conn, priv, username, password) < 0)
        goto cleanup;

    conn->privateData = priv;
    priv = NULL;
    result = VIR_DRV_OPEN_SUCCESS;

 cleanup:
    hypervFreePrivate(&priv);
    VIR_FREE(username);
    VIR_FREE(password);

    return result;
}