/* * file=gluster[+transport]://[server[:port]]/volname/image[?socket=...] * * 'gluster' is the protocol. * * 'transport' specifies the transport type used to connect to gluster * management daemon (glusterd). Valid transport types are * tcp, unix and rdma. If a transport type isn't specified, then tcp * type is assumed. * * 'server' specifies the server where the volume file specification for * the given volume resides. This can be either hostname, ipv4 address * or ipv6 address. ipv6 address needs to be within square brackets [ ]. * If transport type is 'unix', then 'server' field should not be specifed. * The 'socket' field needs to be populated with the path to unix domain * socket. * * 'port' is the port number on which glusterd is listening. This is optional * and if not specified, QEMU will send 0 which will make gluster to use the * default port. If the transport type is unix, then 'port' should not be * specified. * * 'volname' is the name of the gluster volume which contains the VM image. * * 'image' is the path to the actual VM image that resides on gluster volume. * * Examples: * * file=gluster://1.2.3.4/testvol/a.img * file=gluster+tcp://1.2.3.4/testvol/a.img * file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img * file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img * file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img * file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img * file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket * file=gluster+rdma://1.2.3.4:24007/testvol/a.img */ static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename) { URI *uri; QueryParams *qp = NULL; bool is_unix = false; int ret = 0; uri = uri_parse(filename); if (!uri) { return -EINVAL; } /* transport */ if (!strcmp(uri->scheme, "gluster")) { gconf->transport = g_strdup("tcp"); } else if (!strcmp(uri->scheme, "gluster+tcp")) { gconf->transport = g_strdup("tcp"); } else if (!strcmp(uri->scheme, "gluster+unix")) { gconf->transport = g_strdup("unix"); is_unix = true; } else if (!strcmp(uri->scheme, "gluster+rdma")) { gconf->transport = g_strdup("rdma"); } else { ret = -EINVAL; goto out; } ret = parse_volume_options(gconf, uri->path); if (ret < 0) { goto out; } qp = query_params_parse(uri->query); if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) { ret = -EINVAL; goto out; } if (is_unix) { if (uri->server || uri->port) { ret = -EINVAL; goto out; } if (strcmp(qp->p[0].name, "socket")) { ret = -EINVAL; goto out; } gconf->server = g_strdup(qp->p[0].value); } else { gconf->server = g_strdup(uri->server); gconf->port = uri->port; } out: if (qp) { query_params_free(qp); } uri_free(uri); return ret; }
static int parse_uri(const char *filename, QDict *options, Error **errp) { URI *uri = NULL; QueryParams *qp = NULL; int i; uri = uri_parse(filename); if (!uri) { return -EINVAL; } if (strcmp(uri->scheme, "ssh") != 0) { error_setg(errp, "URI scheme must be 'ssh'"); goto err; } if (!uri->server || strcmp(uri->server, "") == 0) { error_setg(errp, "missing hostname in URI"); goto err; } if (!uri->path || strcmp(uri->path, "") == 0) { error_setg(errp, "missing remote path in URI"); goto err; } qp = query_params_parse(uri->query); if (!qp) { error_setg(errp, "could not parse query parameters"); goto err; } if(uri->user && strcmp(uri->user, "") != 0) { qdict_put(options, "user", qstring_from_str(uri->user)); } qdict_put(options, "host", qstring_from_str(uri->server)); if (uri->port) { qdict_put(options, "port", qint_from_int(uri->port)); } qdict_put(options, "path", qstring_from_str(uri->path)); /* Pick out any query parameters that we understand, and ignore * the rest. */ for (i = 0; i < qp->n; ++i) { if (strcmp(qp->p[i].name, "host_key_check") == 0) { qdict_put(options, "host_key_check", qstring_from_str(qp->p[i].value)); } } query_params_free(qp); uri_free(uri); return 0; err: if (qp) { query_params_free(qp); } if (uri) { uri_free(uri); } return -EINVAL; }
static int nbd_parse_uri(const char *filename, QDict *options) { URI *uri; const char *p; QueryParams *qp = NULL; int ret = 0; bool is_unix; uri = uri_parse(filename); if (!uri) { return -EINVAL; } /* transport */ if (!strcmp(uri->scheme, "nbd")) { is_unix = false; } else if (!strcmp(uri->scheme, "nbd+tcp")) { is_unix = false; } else if (!strcmp(uri->scheme, "nbd+unix")) { is_unix = true; } else { ret = -EINVAL; goto out; } p = uri->path ? uri->path : "/"; p += strspn(p, "/"); if (p[0]) { qdict_put(options, "export", qstring_from_str(p)); } qp = query_params_parse(uri->query); if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) { ret = -EINVAL; goto out; } if (is_unix) { /* nbd+unix:///export?socket=path */ if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) { ret = -EINVAL; goto out; } qdict_put(options, "path", qstring_from_str(qp->p[0].value)); } else { QString *host; /* nbd[+tcp]://host[:port]/export */ if (!uri->server) { ret = -EINVAL; goto out; } /* strip braces from literal IPv6 address */ if (uri->server[0] == '[') { host = qstring_from_substr(uri->server, 1, strlen(uri->server) - 2); } else { host = qstring_from_str(uri->server); } qdict_put(options, "host", host); if (uri->port) { char* port_str = g_strdup_printf("%d", uri->port); qdict_put(options, "port", qstring_from_str(port_str)); g_free(port_str); } } out: if (qp) { query_params_free(qp); } uri_free(uri); return ret; }
static int nfs_parse_uri(const char *filename, QDict *options, Error **errp) { URI *uri = NULL; QueryParams *qp = NULL; int ret = -EINVAL, i; uri = uri_parse(filename); if (!uri) { error_setg(errp, "Invalid URI specified"); goto out; } if (strcmp(uri->scheme, "nfs") != 0) { error_setg(errp, "URI scheme must be 'nfs'"); goto out; } if (!uri->server) { error_setg(errp, "missing hostname in URI"); goto out; } if (!uri->path) { error_setg(errp, "missing file path in URI"); goto out; } qp = query_params_parse(uri->query); if (!qp) { error_setg(errp, "could not parse query parameters"); goto out; } qdict_put(options, "server.host", qstring_from_str(uri->server)); qdict_put(options, "server.type", qstring_from_str("inet")); qdict_put(options, "path", qstring_from_str(uri->path)); for (i = 0; i < qp->n; i++) { unsigned long long val; if (!qp->p[i].value) { error_setg(errp, "Value for NFS parameter expected: %s", qp->p[i].name); goto out; } if (parse_uint_full(qp->p[i].value, &val, 0)) { error_setg(errp, "Illegal value for NFS parameter: %s", qp->p[i].name); goto out; } if (!strcmp(qp->p[i].name, "uid")) { qdict_put(options, "user", qstring_from_str(qp->p[i].value)); } else if (!strcmp(qp->p[i].name, "gid")) { qdict_put(options, "group", qstring_from_str(qp->p[i].value)); } else if (!strcmp(qp->p[i].name, "tcp-syncnt")) { qdict_put(options, "tcp-syn-count", qstring_from_str(qp->p[i].value)); } else if (!strcmp(qp->p[i].name, "readahead")) { qdict_put(options, "readahead-size", qstring_from_str(qp->p[i].value)); } else if (!strcmp(qp->p[i].name, "pagecache")) { qdict_put(options, "page-cache-size", qstring_from_str(qp->p[i].value)); } else if (!strcmp(qp->p[i].name, "debug")) { qdict_put(options, "debug", qstring_from_str(qp->p[i].value)); } else { error_setg(errp, "Unknown NFS parameter name: %s", qp->p[i].name); goto out; } } ret = 0; out: if (qp) { query_params_free(qp); } if (uri) { uri_free(uri); } return ret; }