2008-11-21 12:16:08 +00:00
/*
* driver . c : Helpers for loading drivers
*
2011-04-11 16:25:25 -06:00
* Copyright ( C ) 2006 - 2011 Red Hat , Inc .
2008-11-21 12:16:08 +00:00
*
* 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
2012-09-20 16:30:55 -06:00
* License along with this library . If not , see
2012-07-21 18:06:23 +08:00
* < http : //www.gnu.org/licenses/>.
2008-11-21 12:16:08 +00:00
*
*/
# include <config.h>
# include <unistd.h>
# include "driver.h"
2012-12-12 18:06:53 +00:00
# include "viralloc.h"
2014-04-24 16:45:49 +01:00
# include "virfile.h"
2012-12-12 17:59:27 +00:00
# include "virlog.h"
2018-04-25 15:35:27 +01:00
# include "virmodule.h"
2019-10-04 16:57:04 +02:00
# include "virstring.h"
2018-02-13 10:08:00 +00:00
# include "virthread.h"
2020-02-25 10:01:09 +00:00
# include "virutil.h"
2010-11-16 07:54:17 -07:00
# include "configmake.h"
2008-11-21 12:16:08 +00:00
2014-02-28 12:16:17 +00:00
VIR_LOG_INIT ( " driver " ) ;
2018-04-19 16:21:38 +01:00
# define VIR_FROM_THIS VIR_FROM_NONE
2008-11-21 12:16:08 +00:00
2016-09-22 00:47:30 +05:30
/* XXX re-implement this for other OS, or use libtools helper lib ? */
2017-07-26 21:31:47 +02:00
# define DEFAULT_DRIVER_DIR LIBDIR " / libvirt / connection-driver"
2008-11-21 12:16:08 +00:00
2017-08-02 11:21:12 +01:00
2017-01-18 16:44:20 +01:00
2017-01-26 14:57:41 +01:00
int
virDriverLoadModule ( const char * name ,
2018-04-19 16:50:56 +01:00
const char * regfunc ,
bool required )
2008-11-21 12:16:08 +00:00
{
2020-04-13 18:18:57 +05:30
g_autofree char * modfile = NULL ;
2017-01-26 14:57:41 +01:00
int ret ;
2008-11-21 12:16:08 +00:00
2011-02-16 16:37:57 -07:00
VIR_DEBUG ( " Module load %s " , name ) ;
2008-11-21 12:16:08 +00:00
2014-04-24 16:45:49 +01:00
if ( ! ( modfile = virFileFindResourceFull ( name ,
" libvirt_driver_ " ,
" .so " ,
2020-05-28 02:40:50 +02:00
abs_top_builddir " /src " ,
2015-04-01 12:38:42 +02:00
DEFAULT_DRIVER_DIR ,
2014-04-24 16:45:49 +01:00
" LIBVIRT_DRIVER_DIR " ) ) )
2018-04-19 15:25:01 +01:00
return - 1 ;
2008-11-21 12:16:08 +00:00
2018-04-25 15:35:27 +01:00
ret = virModuleLoad ( modfile , regfunc , required ) ;
2017-01-26 14:57:41 +01:00
return ret ;
2008-11-21 12:16:08 +00:00
}
/* XXX unload modules, but we can't until we can unregister libvirt drivers */
2018-01-31 18:21:52 +00:00
2019-10-04 16:57:04 +02:00
/**
* virDriverShouldAutostart :
* @ dir : driver ' s run state directory ( usually / var / run / libvirt / $ driver )
* @ autostart : whether driver should initiate autostart
*
* Automatic starting of libvirt ' s objects ( e . g . domains , networks , storage
* pools , etc . ) doesn ' t play nice with using ' - - timeout ' on daemon ' s command
* line because the objects are attempted to autostart on every start of
* corresponding driver / daemon . To resolve this problem , a file is created in
* driver ' s private directory ( which doesn ' t survive host ' s reboot ) and thus
* autostart is attempted only once .
*/
int
virDriverShouldAutostart ( const char * dir ,
bool * autostart )
{
2019-10-15 15:16:31 +02:00
g_autofree char * path = NULL ;
2019-10-04 16:57:04 +02:00
* autostart = false ;
2019-10-22 15:48:08 +02:00
path = g_strdup_printf ( " %s/autostarted " , dir ) ;
2019-10-04 16:57:04 +02:00
if ( virFileExists ( path ) ) {
VIR_DEBUG ( " Autostart file %s exists, skipping autostart " , path ) ;
return 0 ;
}
VIR_DEBUG ( " Autostart file %s does not exist, do autostart " , path ) ;
* autostart = true ;
if ( virFileTouch ( path , 0600 ) < 0 )
return - 1 ;
return 0 ;
}
2018-02-13 10:08:00 +00:00
virThreadLocal connectInterface ;
virThreadLocal connectNetwork ;
virThreadLocal connectNWFilter ;
virThreadLocal connectNodeDev ;
virThreadLocal connectSecret ;
virThreadLocal connectStorage ;
static int
virConnectCacheOnceInit ( void )
{
if ( virThreadLocalInit ( & connectInterface , NULL ) < 0 )
return - 1 ;
if ( virThreadLocalInit ( & connectNetwork , NULL ) < 0 )
return - 1 ;
if ( virThreadLocalInit ( & connectNWFilter , NULL ) < 0 )
return - 1 ;
if ( virThreadLocalInit ( & connectNodeDev , NULL ) < 0 )
return - 1 ;
if ( virThreadLocalInit ( & connectSecret , NULL ) < 0 )
return - 1 ;
if ( virThreadLocalInit ( & connectStorage , NULL ) < 0 )
return - 1 ;
return 0 ;
}
VIR_ONCE_GLOBAL_INIT ( virConnectCache ) ;
2019-10-08 18:02:00 -03:00
static virConnectPtr
virGetConnectGeneric ( virThreadLocalPtr threadPtr , const char * name )
2018-01-31 18:21:52 +00:00
{
2018-02-13 10:08:00 +00:00
virConnectPtr conn ;
if ( virConnectCacheInitialize ( ) < 0 )
return NULL ;
2019-10-08 18:02:00 -03:00
conn = virThreadLocalGet ( threadPtr ) ;
2018-02-13 10:08:00 +00:00
if ( conn ) {
2019-10-08 18:02:00 -03:00
VIR_DEBUG ( " Return cached %s connection %p " , name , conn ) ;
2018-02-13 10:08:00 +00:00
virObjectRef ( conn ) ;
} else {
2019-10-15 15:16:31 +02:00
g_autofree char * uri = NULL ;
2019-10-08 18:02:00 -03:00
const char * uriPath = geteuid ( ) = = 0 ? " /system " : " /session " ;
2019-10-22 15:48:08 +02:00
uri = g_strdup_printf ( " %s://%s " , name , uriPath ) ;
2019-10-08 18:02:00 -03:00
conn = virConnectOpen ( uri ) ;
VIR_DEBUG ( " Opened new %s connection %p " , name , conn ) ;
2018-02-13 10:08:00 +00:00
}
return conn ;
2018-01-31 18:21:52 +00:00
}
2018-02-13 10:08:00 +00:00
2019-10-08 18:02:00 -03:00
virConnectPtr virGetConnectInterface ( void )
{
return virGetConnectGeneric ( & connectInterface , " interface " ) ;
}
2018-02-13 10:08:00 +00:00
2019-10-08 18:02:00 -03:00
virConnectPtr virGetConnectNetwork ( void )
{
return virGetConnectGeneric ( & connectNetwork , " network " ) ;
2018-01-31 18:21:52 +00:00
}
virConnectPtr virGetConnectNWFilter ( void )
{
2019-10-08 18:02:00 -03:00
return virGetConnectGeneric ( & connectNWFilter , " nwfilter " ) ;
2018-01-31 18:21:52 +00:00
}
virConnectPtr virGetConnectNodeDev ( void )
{
2019-10-08 18:02:00 -03:00
return virGetConnectGeneric ( & connectNodeDev , " nodedev " ) ;
2018-01-31 18:21:52 +00:00
}
virConnectPtr virGetConnectSecret ( void )
{
2019-10-08 18:02:00 -03:00
return virGetConnectGeneric ( & connectSecret , " secret " ) ;
2018-01-31 18:21:52 +00:00
}
virConnectPtr virGetConnectStorage ( void )
{
2019-10-08 18:02:00 -03:00
return virGetConnectGeneric ( & connectStorage , " storage " ) ;
2018-02-13 10:08:00 +00:00
}
int
virSetConnectInterface ( virConnectPtr conn )
{
if ( virConnectCacheInitialize ( ) < 0 )
return - 1 ;
VIR_DEBUG ( " Override interface connection with %p " , conn ) ;
return virThreadLocalSet ( & connectInterface , conn ) ;
}
int
virSetConnectNetwork ( virConnectPtr conn )
{
if ( virConnectCacheInitialize ( ) < 0 )
return - 1 ;
VIR_DEBUG ( " Override network connection with %p " , conn ) ;
return virThreadLocalSet ( & connectNetwork , conn ) ;
}
int
virSetConnectNWFilter ( virConnectPtr conn )
{
if ( virConnectCacheInitialize ( ) < 0 )
return - 1 ;
VIR_DEBUG ( " Override nwfilter connection with %p " , conn ) ;
return virThreadLocalSet ( & connectNWFilter , conn ) ;
}
int
virSetConnectNodeDev ( virConnectPtr conn )
{
if ( virConnectCacheInitialize ( ) < 0 )
return - 1 ;
VIR_DEBUG ( " Override nodedev connection with %p " , conn ) ;
return virThreadLocalSet ( & connectNodeDev , conn ) ;
}
int
virSetConnectSecret ( virConnectPtr conn )
{
if ( virConnectCacheInitialize ( ) < 0 )
return - 1 ;
VIR_DEBUG ( " Override secret connection with %p " , conn ) ;
return virThreadLocalSet ( & connectSecret , conn ) ;
}
int
virSetConnectStorage ( virConnectPtr conn )
{
if ( virConnectCacheInitialize ( ) < 0 )
return - 1 ;
VIR_DEBUG ( " Override storage connection with %p " , conn ) ;
return virThreadLocalSet ( & connectStorage , conn ) ;
2018-01-31 18:21:52 +00:00
}
2019-09-26 11:56:36 -03:00
bool
virConnectValidateURIPath ( const char * uriPath ,
const char * entityName ,
bool privileged )
{
if ( privileged ) {
2019-09-26 11:56:43 -03:00
/* TODO: qemu and vbox drivers allow '/session'
* connections as root . This is not ideal , but changing
* these drivers to refuse privileged ' / session '
* connections , like everyone else is already doing , can
* break existing applications . Until we decide what to do ,
* for now we can handle them as exception in this validate
* function .
*/
bool compatSessionRoot = ( STREQ ( entityName , " qemu " ) | |
STREQ ( entityName , " vbox " ) ) & &
STREQ ( uriPath , " /session " ) ;
if ( STRNEQ ( uriPath , " /system " ) & & ! compatSessionRoot ) {
2019-09-26 11:56:36 -03:00
virReportError ( VIR_ERR_INTERNAL_ERROR ,
_ ( " unexpected %s URI path '%s', try "
" %s:///system " ) ,
entityName , uriPath , entityName ) ;
return false ;
}
} else {
if ( STRNEQ ( uriPath , " /session " ) ) {
virReportError ( VIR_ERR_INTERNAL_ERROR ,
_ ( " unexpected %s URI path '%s', try "
" %s:///session " ) ,
entityName , uriPath , entityName ) ;
return false ;
}
}
return true ;
}