diff --git a/daemon/admin_server.c b/daemon/admin_server.c index 0bd142c435..9ea1164571 100644 --- a/daemon/admin_server.c +++ b/daemon/admin_server.c @@ -201,3 +201,13 @@ adminServerListClients(virNetServerPtr srv, virObjectListFreeCount(clts, ret); return ret; } + +virNetServerClientPtr +adminServerLookupClient(virNetServerPtr srv, + unsigned long long id, + unsigned int flags) +{ + virCheckFlags(0, NULL); + + return virNetServerGetClient(srv, id); +} diff --git a/daemon/admin_server.h b/daemon/admin_server.h index 3e4786ebda..a593251d7a 100644 --- a/daemon/admin_server.h +++ b/daemon/admin_server.h @@ -50,4 +50,8 @@ int adminServerListClients(virNetServerPtr srv, virNetServerClientPtr **clients, unsigned int flags); +virNetServerClientPtr adminServerLookupClient(virNetServerPtr srv, + unsigned long long id, + unsigned int flags); + #endif /* __LIBVIRTD_ADMIN_SERVER_H__ */ diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h index 20768e218a..e51f2bab4d 100644 --- a/include/libvirt/libvirt-admin.h +++ b/include/libvirt/libvirt-admin.h @@ -219,6 +219,11 @@ int virAdmServerListClients(virAdmServerPtr srv, virAdmClientPtr **clients, unsigned int flags); +virAdmClientPtr +virAdmServerLookupClient(virAdmServerPtr srv, + unsigned long long id, + unsigned int flags); + # ifdef __cplusplus } # endif diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index c6abdf7669..2ec560e063 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -314,6 +314,7 @@ typedef enum { VIR_ERR_MIGRATE_FINISH_OK = 93, /* Finish API succeeded but it is expected to return NULL */ VIR_ERR_AUTH_UNAVAILABLE = 94, /* authentication unavailable */ VIR_ERR_NO_SERVER = 95, /* Server was not found */ + VIR_ERR_NO_CLIENT = 96, /* Client was not found */ } virErrorNumber; /** diff --git a/src/admin/admin_protocol.x b/src/admin/admin_protocol.x index e77ce9e455..da21db8d39 100644 --- a/src/admin/admin_protocol.x +++ b/src/admin/admin_protocol.x @@ -138,6 +138,16 @@ struct admin_server_list_clients_ret { /* insert@1 */ unsigned int ret; }; +struct admin_server_lookup_client_args { + admin_nonnull_server srv; + unsigned hyper id; + unsigned int flags; +}; + +struct admin_server_lookup_client_ret { + admin_nonnull_client clnt; +}; + /* Define the program number, protocol version and procedure numbers here. */ const ADMIN_PROGRAM = 0x06900690; const ADMIN_PROTOCOL_VERSION = 1; @@ -198,5 +208,10 @@ enum admin_procedure { /** * @generate: both */ - ADMIN_PROC_SERVER_LIST_CLIENTS = 8 + ADMIN_PROC_SERVER_LIST_CLIENTS = 8, + + /** + * @generate: both + */ + ADMIN_PROC_SERVER_LOOKUP_CLIENT = 9 }; diff --git a/src/admin_protocol-structs b/src/admin_protocol-structs index 055ddd5917..dc2220e3ef 100644 --- a/src/admin_protocol-structs +++ b/src/admin_protocol-structs @@ -87,6 +87,14 @@ struct admin_server_list_clients_ret { } clients; u_int ret; }; +struct admin_server_lookup_client_args { + admin_nonnull_server srv; + uint64_t id; + u_int flags; +}; +struct admin_server_lookup_client_ret { + admin_nonnull_client clnt; +}; enum admin_procedure { ADMIN_PROC_CONNECT_OPEN = 1, ADMIN_PROC_CONNECT_CLOSE = 2, @@ -96,4 +104,5 @@ enum admin_procedure { ADMIN_PROC_SERVER_GET_THREADPOOL_PARAMETERS = 6, ADMIN_PROC_SERVER_SET_THREADPOOL_PARAMETERS = 7, ADMIN_PROC_SERVER_LIST_CLIENTS = 8, + ADMIN_PROC_SERVER_LOOKUP_CLIENT = 9, }; diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c index f8b5bd7df0..d9cdb811f1 100644 --- a/src/libvirt-admin.c +++ b/src/libvirt-admin.c @@ -889,3 +889,39 @@ virAdmServerListClients(virAdmServerPtr srv, virDispatchError(NULL); return -1; } + +/** + * virAdmServerLookupClient: + * @srv: a valid server object reference + * @id: ID of the client to lookup on server @srv + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * Try to lookup a client on the given server based on @id. + * + * virAdmClientFree() should be used to free the resources after the + * client object is no longer needed. + * + * Returns the requested client or NULL in case of failure. If the + * client could not be found, then VIR_ERR_NO_CLIENT error is raised. + */ +virAdmClientPtr +virAdmServerLookupClient(virAdmServerPtr srv, + unsigned long long id, + unsigned int flags) +{ + virAdmClientPtr ret = NULL; + + VIR_DEBUG("srv=%p, id=%llu, flags=%x", srv, id, flags); + virResetLastError(); + + virCheckAdmServerGoto(srv, error); + virCheckFlagsGoto(0, error); + + if (!(ret = remoteAdminServerLookupClient(srv, id, flags))) + goto error; + + return ret; + error: + virDispatchError(NULL); + return NULL; +} diff --git a/src/libvirt_admin_private.syms b/src/libvirt_admin_private.syms index 621b502ddd..3d7ecbcb71 100644 --- a/src/libvirt_admin_private.syms +++ b/src/libvirt_admin_private.syms @@ -16,6 +16,8 @@ xdr_admin_server_get_threadpool_parameters_args; xdr_admin_server_get_threadpool_parameters_ret; xdr_admin_server_list_clients_args; xdr_admin_server_list_clients_ret; +xdr_admin_server_lookup_client_args; +xdr_admin_server_lookup_client_ret; xdr_admin_server_set_threadpool_parameters_args; # datatypes.h diff --git a/src/libvirt_admin_public.syms b/src/libvirt_admin_public.syms index bf6643a19f..066ae0ce98 100644 --- a/src/libvirt_admin_public.syms +++ b/src/libvirt_admin_public.syms @@ -29,6 +29,7 @@ LIBVIRT_ADMIN_1.3.0 { virAdmServerGetName; virAdmServerGetThreadPoolParameters; virAdmServerFree; + virAdmServerLookupClient; virAdmConnectLookupServer; virAdmServerSetThreadPoolParameters; virAdmServerListClients; diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index fcc79f4c1e..60541cba8c 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -972,3 +972,26 @@ virNetServerGetClients(virNetServerPtr srv, virObjectUnlock(srv); return ret; } + +virNetServerClientPtr +virNetServerGetClient(virNetServerPtr srv, + unsigned long long id) +{ + size_t i; + virNetServerClientPtr ret = NULL; + + virObjectLock(srv); + + for (i = 0; i < srv->nclients; i++) { + virNetServerClientPtr client = srv->clients[i]; + if (virNetServerClientGetID(client) == id) + ret = virObjectRef(client); + } + + virObjectUnlock(srv); + + if (!ret) + virReportError(VIR_ERR_NO_CLIENT, + _("No client with matching ID '%llu'"), id); + return ret; +} diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h index f5bb20052a..993bda76e0 100644 --- a/src/rpc/virnetserver.h +++ b/src/rpc/virnetserver.h @@ -105,6 +105,9 @@ int virNetServerSetThreadPoolParameters(virNetServerPtr srv, unsigned long long virNetServerNextClientID(virNetServerPtr srv); +virNetServerClientPtr virNetServerGetClient(virNetServerPtr srv, + unsigned long long id); + int virNetServerGetClients(virNetServerPtr srv, virNetServerClientPtr **clients); diff --git a/src/util/virerror.c b/src/util/virerror.c index 4766e13c0e..5d875e3776 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -1388,6 +1388,12 @@ virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("Server not found: %s"); break; + case VIR_ERR_NO_CLIENT: + if (info == NULL) + errmsg = _("Client not found"); + else + errmsg = _("Client not found: %s"); + break; } return errmsg; }