2009-10-21 00:16:44 +04:00
//
// Copyright Red Hat, Inc. 2009
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option) any
// later version.
//
// This program 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
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; see the file COPYING. If not, write to the
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
// MA 02139, USA.
//
// Author: Lon Hohberger <lhh at redhat.com>
//
# include <stdio.h>
# include <simpleconfig.h>
# include <sys/types.h>
# include <stdint.h>
# include <time.h>
# include <server_plugin.h>
# include <string.h>
# include <malloc.h>
# include <errno.h>
2009-11-06 21:16:42 +03:00
# include "uuid-test.h"
2009-10-21 00:16:44 +04:00
# include <qpid/console/SessionManager.h>
using namespace qpid : : console ;
using namespace qpid : : client ;
# define NAME "libvirt-qpid"
# define VERSION "0.1"
# define MAGIC 0x1e01017a
struct lq_info {
int magic ;
2010-01-13 21:38:00 +03:00
int port ;
2009-10-21 00:16:44 +04:00
char * host ;
2010-01-13 21:38:00 +03:00
char * username ;
char * service ;
int use_gssapi ;
2009-10-21 00:16:44 +04:00
} ;
2010-01-11 22:53:51 +03:00
2009-10-21 00:16:44 +04:00
# define VALIDATE(arg) \
do { \
if ( ! arg | | ( ( struct lq_info * ) arg ) - > magic ! = MAGIC ) { \
errno = EINVAL ; \
return - 1 ; \
} \
} while ( 0 )
int
2010-01-13 21:04:46 +03:00
do_lq_request ( struct lq_info * info , const char * vm_name ,
const char * action )
2009-10-21 00:16:44 +04:00
{
Broker * b = NULL ;
SessionManager : : NameVector names ;
Object : : Vector domains ;
Object * domain = NULL ;
2009-11-06 21:16:42 +03:00
const char * property = " name " ;
2009-11-05 22:07:33 +03:00
unsigned i , tries = 0 , found = 0 ;
2009-10-21 00:16:44 +04:00
2009-11-06 21:16:42 +03:00
if ( is_uuid ( vm_name ) = = 1 ) {
property = " uuid " ;
}
2009-10-21 00:16:44 +04:00
SessionManager : : Settings s ;
s . rcvObjects = true ;
s . rcvEvents = false ;
s . rcvHeartbeats = false ;
s . userBindings = false ;
s . methodTimeout = 10 ;
s . getTimeout = 10 ;
SessionManager sm ( NULL , s ) ;
2010-01-13 21:38:00 +03:00
ConnectionSettings cs ;
if ( info - > host )
cs . host = info - > host ;
if ( info - > port )
cs . port = info - > port ;
if ( info - > username )
cs . username = info - > username ;
if ( info - > service )
cs . service = info - > service ;
if ( info - > use_gssapi )
cs . mechanism = " GSSAPI " ;
2009-10-21 00:16:44 +04:00
try {
2010-01-13 21:38:00 +03:00
b = sm . addBroker ( cs ) ;
2009-10-21 00:16:44 +04:00
}
catch ( . . . ) {
std : : cout < < " Error connecting. \n " ;
return 1 ;
}
while ( tries < 10 & & ! found ) {
sleep ( 1 ) ;
// why not com.redhat.libvirt:domain or having
// a way to specify that I want the domain objects from
// the com.redhat.libvirt namespace?!
sm . getObjects ( domains , " domain " , NULL , NULL ) ;
for ( i = 0 ; i < domains . size ( ) ; i + + ) {
#if 0
SchemaClass * c ;
c = domains [ i ] . getSchema ( ) ;
# endif
2009-11-06 21:16:42 +03:00
if ( strcmp ( domains [ i ] . attrString ( property ) . c_str ( ) ,
2009-10-21 00:16:44 +04:00
vm_name ) ) {
continue ;
}
found = 1 ;
domain = & domains [ i ] ;
break ;
#if 0
for ( j = 0 ; j < c - > properties . size ( ) ; j + + ) {
if ( ! strcmp ( c - > properties [ j ] - > name . c_str ( ) , " name " ) & &
! strcmp ( domains [ i ] . attrString ( c - > properties [ j ] - > name ) . c_str ( ) , argv [ 1 ] ) ) {
std : : cout < < c - > properties [ j ] - > name < < " " < < domains [ i ] . attrString ( c - > properties [ j ] - > name ) < < std : : endl ;
}
}
# endif
}
}
if ( ! found ) {
return 1 ;
}
Object : : AttributeMap attrs ;
MethodResponse result ;
2009-11-06 21:16:42 +03:00
std : : cout < < domain - > attrString ( property ) < < " "
2009-10-21 00:16:44 +04:00
< < domain - > attrString ( " state " ) < < std : : endl ;
domain - > invokeMethod ( action , attrs , result ) ;
std : : cout < < " Response: " < < result . code < < " ( " < < result . text < < " ) " < < std : : endl ;
sm . delBroker ( b ) ;
return result . code ;
}
static int
lq_null ( const char * vm_name , void * priv )
{
VALIDATE ( priv ) ;
printf ( " [libvirt-qpid] libvirt-qpid operation on %s \n " , vm_name ) ;
return 1 ;
}
static int
2010-01-13 21:52:55 +03:00
lq_off ( const char * vm_name , const char * src , uint32_t seqno , void * priv )
2009-10-21 00:16:44 +04:00
{
VALIDATE ( priv ) ;
printf ( " [libvirt-qpid] OFF operation on %s \n " , vm_name ) ;
2010-01-13 21:04:46 +03:00
return do_lq_request ( ( lq_info * ) priv , vm_name , " destroy " ) ;
2009-10-21 00:16:44 +04:00
return 1 ;
}
static int
2010-01-13 21:52:55 +03:00
lq_on ( const char * vm_name , const char * src , uint32_t seqno , void * priv )
2009-10-21 00:16:44 +04:00
{
VALIDATE ( priv ) ;
printf ( " [libvirt-qpid] ON operation on %s \n " , vm_name ) ;
2010-01-13 21:04:46 +03:00
return do_lq_request ( ( lq_info * ) priv , vm_name , " create " ) ;
2009-10-21 00:16:44 +04:00
}
static int
lq_devstatus ( void * priv )
{
VALIDATE ( priv ) ;
printf ( " [libvirt-qpid] Device status \n " ) ;
return 0 ;
}
static int
lq_status ( const char * vm_name , void * priv )
{
VALIDATE ( priv ) ;
printf ( " [libvirt-qpid] STATUS operation on %s \n " , vm_name ) ;
return 1 ;
}
static int
2010-01-13 21:52:55 +03:00
lq_reboot ( const char * vm_name , const char * src , uint32_t seqno , void * priv )
2009-10-21 00:16:44 +04:00
{
VALIDATE ( priv ) ;
printf ( " [libvirt-qpid] REBOOT operation on %s \n " , vm_name ) ;
2009-11-05 20:59:41 +03:00
2010-01-13 21:52:55 +03:00
if ( lq_off ( vm_name , src , seqno , priv ) ! = 0 )
2009-11-05 20:59:41 +03:00
return 1 ;
sleep ( 1 ) ;
2010-01-13 21:52:55 +03:00
lq_on ( vm_name , src , seqno , priv ) ;
2009-10-21 00:16:44 +04:00
return 1 ;
}
2009-12-07 20:55:48 +03:00
static int
lq_hostlist ( hostlist_callback callback , void * arg , void * priv )
{
VALIDATE ( priv ) ;
2010-01-13 21:04:46 +03:00
struct lq_info * info = ( struct lq_info * ) priv ;
2009-12-07 20:55:48 +03:00
Broker * b = NULL ;
SessionManager : : NameVector names ;
Object : : Vector domains ;
unsigned i , tries = 0 ;
const char * vm_name , * vm_uuid , * vm_state_str ;
int vm_state = 0 , ret = 1 ;
printf ( " [libvirt-qpid] HOSTLIST operation \n " ) ;
SessionManager : : Settings s ;
s . rcvObjects = true ;
s . rcvEvents = false ;
s . rcvHeartbeats = false ;
s . userBindings = false ;
s . methodTimeout = 10 ;
s . getTimeout = 10 ;
SessionManager sm ( NULL , s ) ;
2010-01-13 21:38:00 +03:00
ConnectionSettings cs ;
if ( info - > host )
cs . host = info - > host ;
if ( info - > port )
cs . port = info - > port ;
if ( info - > username )
cs . username = info - > username ;
if ( info - > service )
cs . service = info - > service ;
if ( info - > use_gssapi )
cs . mechanism = " GSSAPI " ;
2009-12-07 20:55:48 +03:00
try {
2010-01-13 21:38:00 +03:00
b = sm . addBroker ( cs ) ;
2009-12-07 20:55:48 +03:00
}
catch ( . . . ) {
std : : cout < < " Error connecting. \n " ;
return 1 ;
}
while ( tries < 10 ) {
sleep ( 1 ) ;
sm . getObjects ( domains , " domain " , NULL , NULL ) ;
if ( domains . size ( ) > = 1 ) {
break ;
}
}
if ( domains . size ( ) < 1 )
goto out ;
for ( i = 0 ; i < domains . size ( ) ; i + + ) {
vm_name = domains [ i ] . attrString ( " name " ) . c_str ( ) ;
vm_uuid = domains [ i ] . attrString ( " uuid " ) . c_str ( ) ;
vm_state_str = domains [ i ] . attrString ( " state " ) . c_str ( ) ;
if ( ! strcasecmp ( vm_state_str , " shutoff " ) )
vm_state = 0 ;
else
vm_state = 1 ;
callback ( vm_name , vm_uuid , vm_state , arg ) ;
}
ret = 0 ;
out :
sm . delBroker ( b ) ;
return 0 ;
}
2009-10-21 00:16:44 +04:00
static int
lq_init ( backend_context_t * c , config_object_t * config )
{
char value [ 256 ] ;
struct lq_info * info = NULL ;
info = ( lq_info * ) malloc ( sizeof ( * info ) ) ;
if ( ! info )
return - 1 ;
memset ( info , 0 , sizeof ( * info ) ) ;
2010-01-13 21:38:00 +03:00
info - > port = 5672 ;
2010-01-13 21:04:46 +03:00
2010-01-11 22:53:51 +03:00
if ( sc_get ( config , " backends/libvirt-qpid/@host " ,
value , sizeof ( value ) ) = = 0 ) {
printf ( " \n \n HOST = %s \n \n " , value ) ;
2010-01-13 21:38:00 +03:00
info - > host = strdup ( value ) ;
if ( ! info - > host ) {
goto out_fail ;
}
} else {
info - > host = strdup ( " 127.0.0.1 " ) ;
2010-01-11 22:53:51 +03:00
}
if ( sc_get ( config , " backends/libvirt-qpid/@port " ,
value , sizeof ( value ) - 1 ) = = 0 ) {
printf ( " \n \n PORT = %d \n \n " , atoi ( value ) ) ;
2010-01-13 21:38:00 +03:00
info - > port = atoi ( value ) ;
2009-10-21 00:16:44 +04:00
}
2010-01-13 21:38:00 +03:00
if ( sc_get ( config , " backends/libvirt-qpid/@username " ,
value , sizeof ( value ) ) = = 0 ) {
printf ( " \n \n USERNAME = %s \n \n " , value ) ;
info - > username = strdup ( value ) ;
if ( ! info - > username ) {
goto out_fail ;
}
}
if ( sc_get ( config , " backends/libvirt-qpid/@service " ,
value , sizeof ( value ) ) = = 0 ) {
printf ( " \n \n SERVICE = %s \n \n " , value ) ;
info - > service = strdup ( value ) ;
if ( ! info - > service ) {
goto out_fail ;
}
}
if ( sc_get ( config , " backends/libvirt-qpid/@gssapi " ,
value , sizeof ( value ) - 1 ) = = 0 ) {
printf ( " \n \n GSSAPI = %d \n \n " , atoi ( value ) ) ;
if ( atoi ( value ) > 0 ) {
info - > use_gssapi = 1 ;
}
2009-10-21 00:16:44 +04:00
}
info - > magic = MAGIC ;
* c = ( void * ) info ;
return 0 ;
2010-01-13 21:38:00 +03:00
out_fail :
free ( info - > service ) ;
free ( info - > username ) ;
free ( info - > host ) ;
free ( info ) ;
return - 1 ;
2009-10-21 00:16:44 +04:00
}
static int
lq_shutdown ( backend_context_t c )
{
struct lq_info * info = ( struct lq_info * ) c ;
VALIDATE ( info ) ;
info - > magic = 0 ;
2010-01-13 21:38:00 +03:00
free ( info - > service ) ;
free ( info - > username ) ;
free ( info - > host ) ;
2009-10-21 00:16:44 +04:00
free ( info ) ;
return 0 ;
}
static fence_callbacks_t lq_callbacks = {
2009-12-07 20:55:48 +03:00
lq_null , lq_off , lq_on , lq_reboot , lq_status , lq_devstatus ,
lq_hostlist
2009-10-21 00:16:44 +04:00
} ;
static backend_plugin_t lq_plugin = {
NAME , VERSION , & lq_callbacks , lq_init , lq_shutdown
} ;
# ifdef _MODULE
2009-11-12 22:12:42 +03:00
extern " C " double
2009-10-21 00:16:44 +04:00
BACKEND_VER_SYM ( void )
{
return PLUGIN_VERSION_BACKEND ;
}
2009-11-12 22:12:42 +03:00
extern " C " const backend_plugin_t *
2009-10-21 00:16:44 +04:00
BACKEND_INFO_SYM ( void )
{
return & lq_plugin ;
}
# else
static void __attribute__ ( ( constructor ) )
2009-11-05 22:01:35 +03:00
lq_register_plugin ( void )
2009-10-21 00:16:44 +04:00
{
2009-11-05 22:01:35 +03:00
plugin_reg_backend ( & lq_plugin ) ;
2009-10-21 00:16:44 +04:00
}
# endif