2015-05-22 15:21:46 +03:00
/*
* Copyright ( C ) 2015 Red Hat , Inc .
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library . If not , see
* < http : //www.gnu.org/licenses/>.
*/
# include <config.h>
2020-03-19 14:02:45 +03:00
# include <unistd.h>
2015-05-22 15:21:46 +03:00
# include "testutils.h"
# include "virerror.h"
2015-06-11 15:02:30 +03:00
# include "rpc/virnetdaemon.h"
2015-05-22 15:21:46 +03:00
# define VIR_FROM_THIS VIR_FROM_RPC
2020-03-19 14:02:45 +03:00
# if !defined(WIN32) && defined(WITH_YAJL)
2018-02-01 18:32:49 +03:00
struct testClientPriv {
int magic ;
} ;
static void *
2019-10-14 15:45:03 +03:00
testClientNew ( virNetServerClientPtr client G_GNUC_UNUSED ,
void * opaque G_GNUC_UNUSED )
2018-02-01 18:32:49 +03:00
{
struct testClientPriv * priv ;
2020-09-23 01:42:45 +03:00
priv = g_new0 ( struct testClientPriv , 1 ) ;
2018-02-01 18:32:49 +03:00
priv - > magic = 1729 ;
return priv ;
}
static virJSONValuePtr
2019-10-14 15:45:03 +03:00
testClientPreExec ( virNetServerClientPtr client G_GNUC_UNUSED ,
2018-02-01 18:32:49 +03:00
void * data )
{
struct testClientPriv * priv = data ;
return virJSONValueNewNumberInt ( priv - > magic ) ;
}
static void *
testClientNewPostExec ( virNetServerClientPtr client ,
virJSONValuePtr object ,
void * opaque )
{
int magic ;
if ( virJSONValueGetNumberInt ( object , & magic ) < 0 )
return NULL ;
if ( magic ! = 1729 )
return NULL ;
return testClientNew ( client , opaque ) ;
}
static void
testClientFree ( void * opaque )
{
2021-02-03 22:35:02 +03:00
g_free ( opaque ) ;
2018-02-01 18:32:49 +03:00
}
2015-05-22 15:21:46 +03:00
static virNetServerPtr
2016-03-01 17:34:15 +03:00
testCreateServer ( const char * server_name , const char * host , int family )
2015-05-22 15:21:46 +03:00
{
virNetServerPtr srv = NULL ;
virNetServerServicePtr svc1 = NULL , svc2 = NULL ;
virNetServerClientPtr cln1 = NULL , cln2 = NULL ;
virNetSocketPtr sk1 = NULL , sk2 = NULL ;
int fdclient [ 2 ] ;
if ( socketpair ( PF_UNIX , SOCK_STREAM , 0 , fdclient ) < 0 ) {
virReportSystemError ( errno , " %s " ,
" Cannot create socket pair " ) ;
goto cleanup ;
}
2016-04-13 21:54:40 +03:00
if ( ! ( srv = virNetServerNew ( server_name , 1 ,
2016-03-01 17:34:15 +03:00
10 , 50 , 5 , 100 , 10 ,
2015-07-20 15:51:24 +03:00
120 , 5 ,
2018-02-01 18:32:49 +03:00
testClientNew ,
testClientPreExec ,
testClientFree ,
2015-05-22 15:21:46 +03:00
NULL ) ) )
goto error ;
if ( ! ( svc1 = virNetServerServiceNewTCP ( host ,
NULL ,
family ,
VIR_NET_SERVER_SERVICE_AUTH_NONE ,
NULL ,
true ,
5 ,
2 ) ) )
goto error ;
if ( ! ( svc2 = virNetServerServiceNewTCP ( host ,
NULL ,
family ,
VIR_NET_SERVER_SERVICE_AUTH_POLKIT ,
NULL ,
false ,
25 ,
5 ) ) )
goto error ;
2019-06-19 17:19:23 +03:00
if ( virNetServerAddService ( srv , svc1 ) < 0 )
2015-05-22 15:21:46 +03:00
goto error ;
2019-06-19 17:19:23 +03:00
if ( virNetServerAddService ( srv , svc2 ) < 0 )
2015-05-22 15:21:46 +03:00
goto error ;
if ( virNetSocketNewConnectSockFD ( fdclient [ 0 ] , & sk1 ) < 0 )
goto error ;
if ( virNetSocketNewConnectSockFD ( fdclient [ 1 ] , & sk2 ) < 0 )
goto error ;
2016-04-13 21:54:40 +03:00
if ( ! ( cln1 = virNetServerClientNew ( virNetServerNextClientID ( srv ) ,
sk1 ,
2015-05-22 15:21:46 +03:00
VIR_NET_SERVER_SERVICE_AUTH_SASL ,
true ,
15 ,
NULL ,
2018-02-01 18:32:49 +03:00
testClientNew ,
testClientPreExec ,
testClientFree ,
NULL ) ) )
2015-05-22 15:21:46 +03:00
goto error ;
2016-04-13 21:54:40 +03:00
if ( ! ( cln2 = virNetServerClientNew ( virNetServerNextClientID ( srv ) ,
sk2 ,
2015-05-22 15:21:46 +03:00
VIR_NET_SERVER_SERVICE_AUTH_POLKIT ,
true ,
66 ,
NULL ,
2018-02-01 18:32:49 +03:00
testClientNew ,
testClientPreExec ,
testClientFree ,
NULL ) ) )
2015-05-22 15:21:46 +03:00
goto error ;
if ( virNetServerAddClient ( srv , cln1 ) < 0 )
goto error ;
if ( virNetServerAddClient ( srv , cln2 ) < 0 )
goto error ;
cleanup :
2015-06-15 11:41:17 +03:00
if ( ! srv )
virDispatchError ( NULL ) ;
2015-05-22 15:21:46 +03:00
virObjectUnref ( cln1 ) ;
virObjectUnref ( cln2 ) ;
virObjectUnref ( svc1 ) ;
virObjectUnref ( svc2 ) ;
2015-09-08 14:21:17 +03:00
virObjectUnref ( sk1 ) ;
virObjectUnref ( sk2 ) ;
2015-05-22 15:21:46 +03:00
return srv ;
error :
virObjectUnref ( srv ) ;
srv = NULL ;
goto cleanup ;
}
2015-08-10 14:01:44 +03:00
static char * testGenerateJSON ( const char * server_name )
2015-05-22 15:21:46 +03:00
{
2015-06-11 15:02:30 +03:00
virNetDaemonPtr dmn = NULL ;
2015-05-22 15:21:46 +03:00
virNetServerPtr srv = NULL ;
virJSONValuePtr json = NULL ;
char * jsonstr = NULL ;
bool has_ipv4 , has_ipv6 ;
/* Our pre-saved JSON file is created so that each service
* only has one socket . If we let libvirt bind to IPv4 and
* IPv6 we might end up with two sockets , so force one or
* the other based on what ' s available on thehost
*/
if ( virNetSocketCheckProtocols ( & has_ipv4 ,
& has_ipv6 ) < 0 )
return NULL ;
if ( ! has_ipv4 & & ! has_ipv6 )
return NULL ;
2016-03-01 17:34:15 +03:00
if ( ! ( srv = testCreateServer ( server_name ,
has_ipv4 ? " 127.0.0.1 " : " ::1 " ,
2015-08-10 14:01:44 +03:00
has_ipv4 ? AF_INET : AF_INET6 ) ) )
2015-05-22 15:21:46 +03:00
goto cleanup ;
2015-06-11 15:02:30 +03:00
if ( ! ( dmn = virNetDaemonNew ( ) ) )
goto cleanup ;
2016-03-01 17:40:31 +03:00
if ( virNetDaemonAddServer ( dmn , srv ) < 0 )
2015-06-11 15:02:30 +03:00
goto cleanup ;
if ( ! ( json = virNetDaemonPreExecRestart ( dmn ) ) )
2015-05-22 15:21:46 +03:00
goto cleanup ;
if ( ! ( jsonstr = virJSONValueToString ( json , true ) ) )
goto cleanup ;
2015-06-11 15:02:30 +03:00
2015-05-22 15:21:46 +03:00
fprintf ( stderr , " %s \n " , jsonstr ) ;
cleanup :
virNetServerClose ( srv ) ;
virObjectUnref ( srv ) ;
2015-06-11 15:02:30 +03:00
virObjectUnref ( dmn ) ;
2015-05-22 15:21:46 +03:00
virJSONValueFree ( json ) ;
2015-06-11 15:02:30 +03:00
if ( ! jsonstr )
virDispatchError ( NULL ) ;
2015-05-22 15:21:46 +03:00
return jsonstr ;
}
struct testExecRestartData {
const char * jsonfile ;
2015-08-10 14:01:44 +03:00
const char * * serverNames ;
2015-06-11 15:02:30 +03:00
int nservers ;
bool pass ;
2015-05-22 15:21:46 +03:00
} ;
2018-01-22 20:38:55 +03:00
static virNetServerPtr
2019-10-14 15:45:03 +03:00
testNewServerPostExecRestart ( virNetDaemonPtr dmn G_GNUC_UNUSED ,
2018-01-22 20:38:55 +03:00
const char * name ,
virJSONValuePtr object ,
void * opaque )
{
struct testExecRestartData * data = opaque ;
size_t i ;
for ( i = 0 ; i < data - > nservers ; i + + ) {
if ( STREQ ( data - > serverNames [ i ] , name ) ) {
return virNetServerNewPostExecRestart ( object ,
name ,
2018-02-01 18:32:49 +03:00
testClientNew ,
testClientNewPostExec ,
testClientPreExec ,
testClientFree ,
NULL ) ;
2018-01-22 20:38:55 +03:00
}
}
virReportError ( VIR_ERR_INTERNAL_ERROR , " Unexpected server name '%s' " , name ) ;
return NULL ;
}
2015-05-22 15:21:46 +03:00
static int testExecRestart ( const void * opaque )
{
2015-06-11 15:02:30 +03:00
size_t i ;
2015-05-22 15:21:46 +03:00
int ret = - 1 ;
2015-06-11 15:02:30 +03:00
virNetDaemonPtr dmn = NULL ;
2015-05-22 15:21:46 +03:00
const struct testExecRestartData * data = opaque ;
char * infile = NULL , * outfile = NULL ;
char * injsonstr = NULL , * outjsonstr = NULL ;
virJSONValuePtr injson = NULL , outjson = NULL ;
int fdclient [ 2 ] = { - 1 , - 1 } , fdserver [ 2 ] = { - 1 , - 1 } ;
if ( socketpair ( PF_UNIX , SOCK_STREAM , 0 , fdclient ) < 0 ) {
virReportSystemError ( errno , " %s " ,
" Cannot create socket pair " ) ;
goto cleanup ;
}
if ( socketpair ( PF_UNIX , SOCK_STREAM , 0 , fdserver ) < 0 ) {
virReportSystemError ( errno , " %s " ,
" Cannot create socket pair " ) ;
goto cleanup ;
}
/* We're blindly assuming the test case isn't using
* fds 100 - > 103 for something else , which is probably
* fairly reasonable in general
*/
2019-07-23 15:14:50 +03:00
if ( dup2 ( fdserver [ 0 ] , 100 ) < 0 | |
dup2 ( fdserver [ 1 ] , 101 ) < 0 | |
dup2 ( fdclient [ 0 ] , 102 ) < 0 | |
dup2 ( fdclient [ 1 ] , 103 ) < 0 ) {
virReportSystemError ( errno , " %s " , " dup2() failed " ) ;
goto cleanup ;
}
2015-05-22 15:21:46 +03:00
2019-10-22 16:26:14 +03:00
infile = g_strdup_printf ( " %s/virnetdaemondata/input-data-%s.json " , abs_srcdir ,
data - > jsonfile ) ;
2015-05-22 15:21:46 +03:00
2019-10-22 16:26:14 +03:00
outfile = g_strdup_printf ( " %s/virnetdaemondata/output-data-%s.json " ,
abs_srcdir , data - > jsonfile ) ;
2015-05-22 15:21:46 +03:00
if ( virFileReadAll ( infile , 8192 , & injsonstr ) < 0 )
goto cleanup ;
if ( ! ( injson = virJSONValueFromString ( injsonstr ) ) )
goto cleanup ;
2018-01-22 20:38:55 +03:00
if ( ! ( dmn = virNetDaemonNewPostExecRestart ( injson ,
data - > nservers ,
data - > serverNames ,
testNewServerPostExecRestart ,
( void * ) data ) ) )
2015-05-22 15:21:46 +03:00
goto cleanup ;
2015-06-11 15:02:30 +03:00
for ( i = 0 ; i < data - > nservers ; i + + ) {
2018-01-22 20:38:55 +03:00
if ( ! virNetDaemonHasServer ( dmn , data - > serverNames [ i ] ) ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
" Server %s was not created " ,
data - > serverNames [ i ] ) ;
2015-06-11 15:02:30 +03:00
goto cleanup ;
2018-01-22 20:38:55 +03:00
}
2015-06-11 15:02:30 +03:00
}
if ( ! ( outjson = virNetDaemonPreExecRestart ( dmn ) ) )
2015-05-22 15:21:46 +03:00
goto cleanup ;
if ( ! ( outjsonstr = virJSONValueToString ( outjson , true ) ) )
goto cleanup ;
2016-05-26 18:01:53 +03:00
if ( virTestCompareToFile ( outjsonstr , outfile ) < 0 )
2015-06-11 15:02:30 +03:00
goto cleanup ;
2015-05-22 15:21:46 +03:00
2015-06-11 15:02:30 +03:00
ret = 0 ;
2015-05-22 15:21:46 +03:00
cleanup :
2015-06-11 15:02:30 +03:00
if ( ret < 0 ) {
2015-08-10 14:01:44 +03:00
if ( ! data - > pass ) {
2019-05-03 11:31:02 +03:00
VIR_TEST_DEBUG ( " Got expected error: %s " ,
2015-08-10 14:01:44 +03:00
virGetLastErrorMessage ( ) ) ;
virResetLastError ( ) ;
2015-06-11 15:02:30 +03:00
ret = 0 ;
2015-08-10 14:01:44 +03:00
}
} else if ( ! data - > pass ) {
2019-05-03 11:31:02 +03:00
VIR_TEST_DEBUG ( " Test should have failed " ) ;
2015-08-10 14:01:44 +03:00
ret = - 1 ;
2015-06-11 15:02:30 +03:00
}
2015-05-22 15:21:46 +03:00
VIR_FREE ( infile ) ;
VIR_FREE ( outfile ) ;
VIR_FREE ( injsonstr ) ;
VIR_FREE ( outjsonstr ) ;
virJSONValueFree ( injson ) ;
virJSONValueFree ( outjson ) ;
2015-06-11 15:02:30 +03:00
virObjectUnref ( dmn ) ;
2015-05-22 15:21:46 +03:00
VIR_FORCE_CLOSE ( fdserver [ 0 ] ) ;
VIR_FORCE_CLOSE ( fdserver [ 1 ] ) ;
VIR_FORCE_CLOSE ( fdclient [ 0 ] ) ;
VIR_FORCE_CLOSE ( fdclient [ 1 ] ) ;
return ret ;
}
static int
mymain ( void )
{
int ret = 0 ;
2015-08-10 14:01:44 +03:00
const char * server_names [ ] = { " testServer0 " , " testServer1 " } ;
2015-05-22 15:21:46 +03:00
2015-06-15 11:41:17 +03:00
if ( virInitialize ( ) < 0 | |
virEventRegisterDefaultImpl ( ) < 0 ) {
virDispatchError ( NULL ) ;
return EXIT_FAILURE ;
}
2015-05-22 15:21:46 +03:00
/* Hack to make it easier to generate new JSON files when
* the RPC classes change . Just set this env var , save
* the generated JSON , and replace the file descriptor
* numbers with 100 , 101 , 102 , 103.
*/
if ( getenv ( " VIR_GENERATE_JSON " ) ) {
2015-08-10 14:01:44 +03:00
char * json = testGenerateJSON ( server_names [ 0 ] ) ;
2015-06-11 15:02:30 +03:00
if ( ! json )
return EXIT_FAILURE ;
2015-05-22 15:21:46 +03:00
fprintf ( stdout , " %s \n " , json ) ;
VIR_FREE ( json ) ;
2015-06-11 15:02:30 +03:00
return ret ;
2015-05-22 15:21:46 +03:00
}
2017-11-03 15:09:47 +03:00
# define EXEC_RESTART_TEST_FULL(file, nservers, pass) \
do { \
struct testExecRestartData data = { \
file , server_names , nservers , pass \
} ; \
if ( virTestRun ( " ExecRestart " file , \
testExecRestart , & data ) < 0 ) \
ret = - 1 ; \
2015-05-22 15:21:46 +03:00
} while ( 0 )
2015-08-10 14:01:44 +03:00
# define EXEC_RESTART_TEST(file, N) EXEC_RESTART_TEST_FULL(file, N, true)
# define EXEC_RESTART_TEST_FAIL(file, N) EXEC_RESTART_TEST_FULL(file, N, false)
2015-06-11 15:02:30 +03:00
2015-08-10 14:01:44 +03:00
EXEC_RESTART_TEST ( " initial " , 1 ) ;
EXEC_RESTART_TEST ( " anon-clients " , 1 ) ;
2019-06-19 17:19:23 +03:00
EXEC_RESTART_TEST ( " admin " , 2 ) ;
2015-08-10 14:01:44 +03:00
EXEC_RESTART_TEST ( " admin-server-names " , 2 ) ;
2016-04-13 22:06:00 +03:00
EXEC_RESTART_TEST ( " no-keepalive-required " , 2 ) ;
2016-04-13 21:54:40 +03:00
EXEC_RESTART_TEST ( " client-ids " , 1 ) ;
2016-04-12 20:21:43 +03:00
EXEC_RESTART_TEST ( " client-timestamp " , 1 ) ;
2015-08-10 14:01:44 +03:00
EXEC_RESTART_TEST_FAIL ( " anon-clients " , 2 ) ;
2017-12-21 17:29:06 +03:00
EXEC_RESTART_TEST ( " client-auth-pending " , 1 ) ;
EXEC_RESTART_TEST_FAIL ( " client-auth-pending-failure " , 1 ) ;
2015-06-11 15:02:30 +03:00
2015-05-22 15:21:46 +03:00
return ret = = 0 ? EXIT_SUCCESS : EXIT_FAILURE ;
}
2019-08-21 19:13:16 +03:00
VIR_TEST_MAIN_PRELOAD ( mymain , VIR_TEST_MOCK ( " virnetdaemon " ) )
2015-05-22 15:21:46 +03:00
# else
static int
mymain ( void )
{
return EXIT_AM_SKIP ;
}
2017-03-29 17:45:42 +03:00
VIR_TEST_MAIN ( mymain ) ;
2016-04-12 20:21:43 +03:00
# endif