Remove listen mode
Changing behaviour so that instead of rebinding after a successful migration and continuing as an ordinary server, we simply quit with a 0 exit code and let our caller restart us as a server if they want to. This means that everything in listen.c, listen.h, and anything making reference to a rebind address is unneeded.
This commit is contained in:
26
Rakefile
26
Rakefile
@@ -115,7 +115,6 @@ file check("client") =>
|
|||||||
%w{build/tests/check_client.o
|
%w{build/tests/check_client.o
|
||||||
build/self_pipe.o
|
build/self_pipe.o
|
||||||
build/nbdtypes.o
|
build/nbdtypes.o
|
||||||
build/listen.o
|
|
||||||
build/flexnbd.o
|
build/flexnbd.o
|
||||||
build/flexthread.o
|
build/flexthread.o
|
||||||
build/control.o
|
build/control.o
|
||||||
@@ -160,7 +159,6 @@ file check("serve") =>
|
|||||||
build/flexnbd.o
|
build/flexnbd.o
|
||||||
build/mirror.o
|
build/mirror.o
|
||||||
build/status.o
|
build/status.o
|
||||||
build/listen.o
|
|
||||||
build/acl.o
|
build/acl.o
|
||||||
build/mbox.o
|
build/mbox.o
|
||||||
build/ioutil.o
|
build/ioutil.o
|
||||||
@@ -181,7 +179,6 @@ file check("readwrite") =>
|
|||||||
build/flexnbd.o
|
build/flexnbd.o
|
||||||
build/mirror.o
|
build/mirror.o
|
||||||
build/status.o
|
build/status.o
|
||||||
build/listen.o
|
|
||||||
build/nbdtypes.o
|
build/nbdtypes.o
|
||||||
build/mbox.o
|
build/mbox.o
|
||||||
build/ioutil.o
|
build/ioutil.o
|
||||||
@@ -189,26 +186,6 @@ file check("readwrite") =>
|
|||||||
gcc_link t.name, t.prerequisites + [LIBCHECK]
|
gcc_link t.name, t.prerequisites + [LIBCHECK]
|
||||||
end
|
end
|
||||||
|
|
||||||
file check("listen") =>
|
|
||||||
%w{build/tests/check_listen.o
|
|
||||||
build/listen.o
|
|
||||||
build/flexnbd.o
|
|
||||||
build/status.o
|
|
||||||
build/flexthread.o
|
|
||||||
build/mbox.o
|
|
||||||
build/mirror.o
|
|
||||||
build/self_pipe.o
|
|
||||||
build/nbdtypes.o
|
|
||||||
build/control.o
|
|
||||||
build/readwrite.o
|
|
||||||
build/parse.o
|
|
||||||
build/client.o
|
|
||||||
build/serve.o
|
|
||||||
build/acl.o
|
|
||||||
build/ioutil.o
|
|
||||||
build/util.o} do |t|
|
|
||||||
gcc_link t.name, t.prerequisites + [LIBCHECK]
|
|
||||||
end
|
|
||||||
|
|
||||||
file check("flexnbd") =>
|
file check("flexnbd") =>
|
||||||
%w{build/tests/check_flexnbd.o
|
%w{build/tests/check_flexnbd.o
|
||||||
@@ -216,7 +193,6 @@ file check("flexnbd") =>
|
|||||||
build/ioutil.o
|
build/ioutil.o
|
||||||
build/util.o
|
build/util.o
|
||||||
build/control.o
|
build/control.o
|
||||||
build/listen.o
|
|
||||||
build/mbox.o
|
build/mbox.o
|
||||||
build/flexthread.o
|
build/flexthread.o
|
||||||
build/status.o
|
build/status.o
|
||||||
@@ -236,7 +212,7 @@ file check("control") =>
|
|||||||
gcc_link t.name, t.prerequisites + [LIBCHECK]
|
gcc_link t.name, t.prerequisites + [LIBCHECK]
|
||||||
end
|
end
|
||||||
|
|
||||||
(TEST_MODULES- %w{control flexnbd acl client serve readwrite listen util}).each do |m|
|
(TEST_MODULES- %w{control flexnbd acl client serve readwrite util}).each do |m|
|
||||||
tgt = "build/tests/check_#{m}.o"
|
tgt = "build/tests/check_#{m}.o"
|
||||||
maybe_obj_name = "build/#{m}.o"
|
maybe_obj_name = "build/#{m}.o"
|
||||||
# Take it out in case we're testing util.o or ioutil.o
|
# Take it out in case we're testing util.o or ioutil.o
|
||||||
|
107
src/control.c
107
src/control.c
@@ -353,48 +353,38 @@ int control_mirror(struct control_client* client, int linesc, char** lines)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In theory, we should never have to worry about the switch
|
struct server * serve = flexnbd_server(flexnbd);
|
||||||
* lock here, since we should never be able to start more than
|
|
||||||
* one mirror at a time. This is enforced by only accepting a
|
|
||||||
* single client at a time on the control socket.
|
|
||||||
*/
|
|
||||||
flexnbd_lock_switch( flexnbd );
|
|
||||||
{
|
|
||||||
struct server * serve = flexnbd_server(flexnbd);
|
|
||||||
|
|
||||||
if ( serve->mirror_super ) {
|
if ( serve->mirror_super ) {
|
||||||
warn( "Tried to start a second mirror run" );
|
warn( "Tried to start a second mirror run" );
|
||||||
write_socket( "1: mirror already running" );
|
write_socket( "1: mirror already running" );
|
||||||
} else {
|
} else {
|
||||||
serve->mirror_super = mirror_super_create(
|
serve->mirror_super = mirror_super_create(
|
||||||
serve->filename,
|
serve->filename,
|
||||||
connect_to,
|
connect_to,
|
||||||
connect_from,
|
connect_from,
|
||||||
max_Bps ,
|
max_Bps ,
|
||||||
action_at_finish,
|
action_at_finish,
|
||||||
client->mirror_state_mbox );
|
client->mirror_state_mbox );
|
||||||
serve->mirror = serve->mirror_super->mirror;
|
serve->mirror = serve->mirror_super->mirror;
|
||||||
|
|
||||||
FATAL_IF( 0 != pthread_create(
|
FATAL_IF( 0 != pthread_create(
|
||||||
&serve->mirror_super->thread,
|
&serve->mirror_super->thread,
|
||||||
NULL,
|
NULL,
|
||||||
mirror_super_runner,
|
mirror_super_runner,
|
||||||
serve
|
serve
|
||||||
),
|
),
|
||||||
"Failed to create mirror thread"
|
"Failed to create mirror thread"
|
||||||
);
|
);
|
||||||
|
|
||||||
debug("Control thread mirror super waiting");
|
debug("Control thread mirror super waiting");
|
||||||
enum mirror_state state =
|
enum mirror_state state =
|
||||||
control_client_mirror_wait( client );
|
control_client_mirror_wait( client );
|
||||||
debug("Control thread writing response");
|
debug("Control thread writing response");
|
||||||
control_write_mirror_response( state, client->socket );
|
control_write_mirror_response( state, client->socket );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
debug( "Control thread unlocking switch" );
|
|
||||||
flexnbd_unlock_switch( flexnbd );
|
|
||||||
debug( "Control thread going away." );
|
debug( "Control thread going away." );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,33 +431,29 @@ int control_break(
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
struct flexnbd* flexnbd = client->flexnbd;
|
struct flexnbd* flexnbd = client->flexnbd;
|
||||||
|
|
||||||
flexnbd_lock_switch( flexnbd );
|
struct server * serve = flexnbd_server( flexnbd );
|
||||||
{
|
if ( server_is_mirroring( serve ) ) {
|
||||||
struct server * serve = flexnbd_server( flexnbd );
|
|
||||||
if ( server_is_mirroring( serve ) ) {
|
|
||||||
|
|
||||||
info( "Signaling to abandon mirror" );
|
info( "Signaling to abandon mirror" );
|
||||||
server_abandon_mirror( serve );
|
server_abandon_mirror( serve );
|
||||||
debug( "Abandon signaled" );
|
debug( "Abandon signaled" );
|
||||||
|
|
||||||
if ( server_is_closed( serve ) ) {
|
if ( server_is_closed( serve ) ) {
|
||||||
info( "Mirror completed while canceling" );
|
info( "Mirror completed while canceling" );
|
||||||
write( client->socket,
|
write( client->socket,
|
||||||
"1: mirror completed\n", 20 );
|
"1: mirror completed\n", 20 );
|
||||||
}
|
|
||||||
else {
|
|
||||||
info( "Mirror successfully stopped." );
|
|
||||||
write( client->socket,
|
|
||||||
"0: mirror stopped\n", 18 );
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
warn( "Not mirroring." );
|
|
||||||
write( client->socket, "1: not mirroring\n", 17 );
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
info( "Mirror successfully stopped." );
|
||||||
|
write( client->socket,
|
||||||
|
"0: mirror stopped\n", 18 );
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
warn( "Not mirroring." );
|
||||||
|
write( client->socket, "1: not mirroring\n", 17 );
|
||||||
}
|
}
|
||||||
flexnbd_unlock_switch( flexnbd );
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -499,7 +485,6 @@ void control_client_cleanup(struct control_client* client,
|
|||||||
/* This is wrongness */
|
/* This is wrongness */
|
||||||
if ( server_io_locked( client->flexnbd->serve ) ) { server_unlock_io( client->flexnbd->serve ); }
|
if ( server_io_locked( client->flexnbd->serve ) ) { server_unlock_io( client->flexnbd->serve ); }
|
||||||
if ( server_acl_locked( client->flexnbd->serve ) ) { server_unlock_acl( client->flexnbd->serve ); }
|
if ( server_acl_locked( client->flexnbd->serve ) ) { server_unlock_acl( client->flexnbd->serve ); }
|
||||||
if ( flexnbd_switch_locked( client->flexnbd ) ) { flexnbd_unlock_switch( client->flexnbd ); }
|
|
||||||
|
|
||||||
control_client_destroy( client );
|
control_client_destroy( client );
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,14 @@
|
|||||||
#ifndef CONTROL_H
|
#ifndef CONTROL_H
|
||||||
#define CONTROL_H
|
#define CONTROL_H
|
||||||
|
|
||||||
|
/* We need this to avoid a complaint about struct server * in
|
||||||
|
* void accept_control_connection
|
||||||
|
*/
|
||||||
|
struct server;
|
||||||
|
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
#include "mirror.h"
|
#include "mirror.h"
|
||||||
#include "control.h"
|
#include "serve.h"
|
||||||
#include "flexnbd.h"
|
#include "flexnbd.h"
|
||||||
#include "mbox.h"
|
#include "mbox.h"
|
||||||
|
|
||||||
|
164
src/flexnbd.c
164
src/flexnbd.c
@@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
#include "flexnbd.h"
|
#include "flexnbd.h"
|
||||||
#include "serve.h"
|
#include "serve.h"
|
||||||
#include "listen.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
@@ -76,8 +75,6 @@ void flexnbd_create_shared(
|
|||||||
}
|
}
|
||||||
|
|
||||||
flexnbd->signal_fd = flexnbd_build_signal_fd();
|
flexnbd->signal_fd = flexnbd_build_signal_fd();
|
||||||
|
|
||||||
flexnbd->switch_mutex = flexthread_mutex_create();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -102,36 +99,31 @@ struct flexnbd * flexnbd_create_serving(
|
|||||||
s_acl_entries,
|
s_acl_entries,
|
||||||
max_nbd_clients,
|
max_nbd_clients,
|
||||||
1);
|
1);
|
||||||
flexnbd_create_shared( flexnbd, s_ctrl_sock );
|
flexnbd_create_shared( flexnbd,
|
||||||
|
s_ctrl_sock );
|
||||||
return flexnbd;
|
return flexnbd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct flexnbd * flexnbd_create_listening(
|
struct flexnbd * flexnbd_create_listening(
|
||||||
char* s_ip_address,
|
char* s_ip_address,
|
||||||
char* s_rebind_ip_address,
|
|
||||||
char* s_port,
|
char* s_port,
|
||||||
char* s_rebind_port,
|
|
||||||
char* s_file,
|
char* s_file,
|
||||||
char *s_ctrl_sock,
|
char *s_ctrl_sock,
|
||||||
int default_deny,
|
int default_deny,
|
||||||
int acl_entries,
|
int acl_entries,
|
||||||
char** s_acl_entries,
|
char** s_acl_entries )
|
||||||
int max_nbd_clients )
|
|
||||||
{
|
{
|
||||||
struct flexnbd * flexnbd = xmalloc( sizeof( struct flexnbd ) );
|
struct flexnbd * flexnbd = xmalloc( sizeof( struct flexnbd ) );
|
||||||
flexnbd->listen = listen_create(
|
flexnbd->serve = server_create(
|
||||||
flexnbd,
|
flexnbd,
|
||||||
s_ip_address,
|
s_ip_address,
|
||||||
s_rebind_ip_address,
|
|
||||||
s_port,
|
s_port,
|
||||||
s_rebind_port,
|
s_file,
|
||||||
s_file,
|
|
||||||
default_deny,
|
default_deny,
|
||||||
acl_entries,
|
acl_entries,
|
||||||
s_acl_entries,
|
s_acl_entries,
|
||||||
max_nbd_clients);
|
1, 0);
|
||||||
flexnbd->serve = flexnbd->listen->init_serve;
|
|
||||||
flexnbd_create_shared( flexnbd, s_ctrl_sock );
|
flexnbd_create_shared( flexnbd, s_ctrl_sock );
|
||||||
return flexnbd;
|
return flexnbd;
|
||||||
}
|
}
|
||||||
@@ -175,37 +167,12 @@ void flexnbd_destroy( struct flexnbd * flexnbd )
|
|||||||
if ( flexnbd->control ) {
|
if ( flexnbd->control ) {
|
||||||
control_destroy( flexnbd->control );
|
control_destroy( flexnbd->control );
|
||||||
}
|
}
|
||||||
if ( flexnbd->listen ) {
|
|
||||||
listen_destroy( flexnbd->listen );
|
|
||||||
}
|
|
||||||
|
|
||||||
flexthread_mutex_destroy( flexnbd->switch_mutex );
|
|
||||||
|
|
||||||
close( flexnbd->signal_fd );
|
close( flexnbd->signal_fd );
|
||||||
free( flexnbd );
|
free( flexnbd );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* THOU SHALT NOT DEREFERENCE flexnbd->serve OUTSIDE A SWITCH LOCK
|
|
||||||
*/
|
|
||||||
void flexnbd_lock_switch( struct flexnbd * flexnbd )
|
|
||||||
{
|
|
||||||
NULLCHECK( flexnbd );
|
|
||||||
flexthread_mutex_lock( flexnbd->switch_mutex );
|
|
||||||
}
|
|
||||||
|
|
||||||
void flexnbd_unlock_switch( struct flexnbd * flexnbd )
|
|
||||||
{
|
|
||||||
NULLCHECK( flexnbd );
|
|
||||||
flexthread_mutex_unlock( flexnbd->switch_mutex );
|
|
||||||
}
|
|
||||||
|
|
||||||
int flexnbd_switch_locked( struct flexnbd * flexnbd )
|
|
||||||
{
|
|
||||||
NULLCHECK( flexnbd );
|
|
||||||
return flexthread_mutex_held( flexnbd->switch_mutex );
|
|
||||||
}
|
|
||||||
|
|
||||||
struct server * flexnbd_server( struct flexnbd * flexnbd )
|
struct server * flexnbd_server( struct flexnbd * flexnbd )
|
||||||
{
|
{
|
||||||
NULLCHECK( flexnbd );
|
NULLCHECK( flexnbd );
|
||||||
@@ -216,11 +183,7 @@ struct server * flexnbd_server( struct flexnbd * flexnbd )
|
|||||||
void flexnbd_replace_acl( struct flexnbd * flexnbd, struct acl * acl )
|
void flexnbd_replace_acl( struct flexnbd * flexnbd, struct acl * acl )
|
||||||
{
|
{
|
||||||
NULLCHECK( flexnbd );
|
NULLCHECK( flexnbd );
|
||||||
flexnbd_lock_switch( flexnbd );
|
server_replace_acl( flexnbd_server(flexnbd), acl );
|
||||||
{
|
|
||||||
server_replace_acl( flexnbd_server(flexnbd), acl );
|
|
||||||
}
|
|
||||||
flexnbd_unlock_switch( flexnbd );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -229,16 +192,10 @@ struct status * flexnbd_status_create( struct flexnbd * flexnbd )
|
|||||||
NULLCHECK( flexnbd );
|
NULLCHECK( flexnbd );
|
||||||
struct status * status;
|
struct status * status;
|
||||||
|
|
||||||
flexnbd_lock_switch( flexnbd );
|
status = status_create( flexnbd_server( flexnbd ) );
|
||||||
{
|
|
||||||
status = status_create( flexnbd_server( flexnbd ) );
|
|
||||||
}
|
|
||||||
flexnbd_unlock_switch( flexnbd );
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** THOU SHALT *ONLY* CALL THIS FROM INSIDE A SWITCH LOCK
|
|
||||||
*/
|
|
||||||
void flexnbd_set_server( struct flexnbd * flexnbd, struct server * serve )
|
void flexnbd_set_server( struct flexnbd * flexnbd, struct server * serve )
|
||||||
{
|
{
|
||||||
NULLCHECK( flexnbd );
|
NULLCHECK( flexnbd );
|
||||||
@@ -246,40 +203,11 @@ void flexnbd_set_server( struct flexnbd * flexnbd, struct server * serve )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Calls the given callback to exchange server objects, then sets
|
/* Get the default_deny of the current server object. */
|
||||||
* flexnbd->server so everything else can see it. */
|
|
||||||
void flexnbd_switch( struct flexnbd * flexnbd, struct server *(listen_cb)(struct listen *) )
|
|
||||||
{
|
|
||||||
NULLCHECK( flexnbd );
|
|
||||||
NULLCHECK( flexnbd->listen );
|
|
||||||
|
|
||||||
flexnbd_lock_switch( flexnbd );
|
|
||||||
{
|
|
||||||
struct server * new_server = listen_cb( flexnbd->listen );
|
|
||||||
NULLCHECK( new_server );
|
|
||||||
flexnbd_set_server( flexnbd, new_server );
|
|
||||||
}
|
|
||||||
flexnbd_unlock_switch( flexnbd );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the default_deny of the current server object. This takes the
|
|
||||||
* switch_lock to avoid nastiness if the server switches and gets freed
|
|
||||||
* in the dereference chain.
|
|
||||||
* This means that this function must not be called if the switch lock
|
|
||||||
* is already held.
|
|
||||||
*/
|
|
||||||
int flexnbd_default_deny( struct flexnbd * flexnbd )
|
int flexnbd_default_deny( struct flexnbd * flexnbd )
|
||||||
{
|
{
|
||||||
int result;
|
|
||||||
|
|
||||||
NULLCHECK( flexnbd );
|
NULLCHECK( flexnbd );
|
||||||
flexnbd_lock_switch( flexnbd );
|
return server_default_deny( flexnbd->serve );
|
||||||
{
|
|
||||||
result = server_default_deny( flexnbd->serve );
|
|
||||||
}
|
|
||||||
flexnbd_unlock_switch( flexnbd );
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -300,67 +228,6 @@ void make_writable( const char * filename )
|
|||||||
strerror( errno ) );
|
strerror( errno ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Drops a marker file on the filesystem to show that the image we're
|
|
||||||
* serving hasn't yet finished its migration yet
|
|
||||||
*/
|
|
||||||
void flexnbd_mark_incomplete( struct flexnbd * flexnbd )
|
|
||||||
{
|
|
||||||
char * filename =
|
|
||||||
flexnbd_incomplete_filename( flexnbd );
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
NULLCHECK( filename );
|
|
||||||
|
|
||||||
/* It's OK if the file already exists - it's perfectly possible
|
|
||||||
* that a previous process died part-way through and left it
|
|
||||||
* behind. However, we might have left the file mode in a bad
|
|
||||||
* state.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct stat ignored;
|
|
||||||
int exists = stat( filename, &ignored ) == 0;
|
|
||||||
if ( exists ) {
|
|
||||||
/* definitely there, need to chmod */
|
|
||||||
debug( "%s exists, making it writable", filename );
|
|
||||||
make_writable( filename );
|
|
||||||
}
|
|
||||||
else if ( ENOENT != errno ) {
|
|
||||||
/* Can't tell if it's there or not, weirdness. */
|
|
||||||
fatal( "Unable to stat %s: %s", filename, strerror( errno ) );
|
|
||||||
}
|
|
||||||
else { /* definitely not there. NOP. */ }
|
|
||||||
|
|
||||||
|
|
||||||
fd = open( filename, O_CREAT|O_WRONLY, 0 );
|
|
||||||
FATAL_IF_NEGATIVE( fd,
|
|
||||||
"Couldn't open %s: %s",
|
|
||||||
filename,
|
|
||||||
strerror( errno ) );
|
|
||||||
|
|
||||||
/* Minor race here - in principle we could see the file
|
|
||||||
* disappear before the chmod */
|
|
||||||
close( fd );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Removes the .INCOMPLETE marker file from the filesystem. Call this
|
|
||||||
* only when you know the migration has completed successfully.
|
|
||||||
*/
|
|
||||||
void flexnbd_mark_complete( struct flexnbd * flexnbd )
|
|
||||||
{
|
|
||||||
char * filename =
|
|
||||||
flexnbd_incomplete_filename( flexnbd );
|
|
||||||
|
|
||||||
NULLCHECK( filename );
|
|
||||||
|
|
||||||
make_writable( filename );
|
|
||||||
|
|
||||||
FATAL_IF_NEGATIVE( unlink( filename ),
|
|
||||||
"Couldn't unlink %s: %s",
|
|
||||||
filename,
|
|
||||||
strerror( errno ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int flexnbd_serve( struct flexnbd * flexnbd )
|
int flexnbd_serve( struct flexnbd * flexnbd )
|
||||||
{
|
{
|
||||||
@@ -372,16 +239,7 @@ int flexnbd_serve( struct flexnbd * flexnbd )
|
|||||||
flexnbd_spawn_control( flexnbd );
|
flexnbd_spawn_control( flexnbd );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( flexnbd->listen ){
|
success = do_serve( flexnbd->serve );
|
||||||
success = do_listen( flexnbd->listen );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
do_serve( flexnbd->serve );
|
|
||||||
/* We can't tell here what the intent was. We can
|
|
||||||
* legitimately exit either in control or not.
|
|
||||||
*/
|
|
||||||
success = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( flexnbd->control ) {
|
if ( flexnbd->control ) {
|
||||||
debug( "Stopping control thread" );
|
debug( "Stopping control thread" );
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
#include "acl.h"
|
#include "acl.h"
|
||||||
#include "mirror.h"
|
#include "mirror.h"
|
||||||
#include "serve.h"
|
#include "serve.h"
|
||||||
#include "listen.h"
|
|
||||||
#include "self_pipe.h"
|
#include "self_pipe.h"
|
||||||
#include "mbox.h"
|
#include "mbox.h"
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
@@ -12,29 +11,21 @@
|
|||||||
|
|
||||||
/* Carries the "globals". */
|
/* Carries the "globals". */
|
||||||
struct flexnbd {
|
struct flexnbd {
|
||||||
|
|
||||||
/* We always have a serve pointer, but it should never be
|
/* We always have a serve pointer, but it should never be
|
||||||
* dereferenced outside a flexnbd_switch_lock/unlock pair.
|
* dereferenced outside a flexnbd_switch_lock/unlock pair.
|
||||||
*/
|
*/
|
||||||
struct server * serve;
|
struct server * serve;
|
||||||
/* We only have a listen object if the process was started in
|
|
||||||
* listen mode.
|
|
||||||
*/
|
|
||||||
struct listen * listen;
|
|
||||||
/* We only have a control object if a control socket name was
|
/* We only have a control object if a control socket name was
|
||||||
* passed on the command line.
|
* passed on the command line.
|
||||||
*/
|
*/
|
||||||
struct control * control;
|
struct control * control;
|
||||||
|
|
||||||
/* switch_mutex is the lock around dereferencing the serve
|
|
||||||
* pointer.
|
|
||||||
*/
|
|
||||||
struct flexthread_mutex * switch_mutex;
|
|
||||||
|
|
||||||
/* File descriptor for a signalfd(2) signal stream. */
|
/* File descriptor for a signalfd(2) signal stream. */
|
||||||
int signal_fd;
|
int signal_fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct flexnbd * flexnbd_create(void);
|
struct flexnbd * flexnbd_create(void);
|
||||||
struct flexnbd * flexnbd_create_serving(
|
struct flexnbd * flexnbd_create_serving(
|
||||||
char* s_ip_address,
|
char* s_ip_address,
|
||||||
@@ -47,31 +38,21 @@ struct flexnbd * flexnbd_create_serving(
|
|||||||
int max_nbd_clients);
|
int max_nbd_clients);
|
||||||
|
|
||||||
struct flexnbd * flexnbd_create_listening(
|
struct flexnbd * flexnbd_create_listening(
|
||||||
char* s_ip_address,
|
char* s_ip_address,
|
||||||
char* s_rebind_ip_address,
|
char* s_port,
|
||||||
char* s_port,
|
char* s_file,
|
||||||
char* s_rebind_port,
|
char *s_ctrl_sock,
|
||||||
char* s_file,
|
int default_deny,
|
||||||
char *s_ctrl_sock,
|
int acl_entries,
|
||||||
int default_deny,
|
char** s_acl_entries );
|
||||||
int acl_entries,
|
|
||||||
char** s_acl_entries,
|
|
||||||
int max_nbd_clients );
|
|
||||||
|
|
||||||
void flexnbd_destroy( struct flexnbd * );
|
void flexnbd_destroy( struct flexnbd * );
|
||||||
enum mirror_state;
|
enum mirror_state;
|
||||||
enum mirror_state flexnbd_get_mirror_state( struct flexnbd * );
|
enum mirror_state flexnbd_get_mirror_state( struct flexnbd * );
|
||||||
void flexnbd_lock_switch( struct flexnbd * );
|
|
||||||
void flexnbd_unlock_switch( struct flexnbd * );
|
|
||||||
int flexnbd_switch_locked( struct flexnbd * );
|
|
||||||
int flexnbd_default_deny( struct flexnbd * );
|
int flexnbd_default_deny( struct flexnbd * );
|
||||||
void flexnbd_set_server( struct flexnbd * flexnbd, struct server * serve );
|
void flexnbd_set_server( struct flexnbd * flexnbd, struct server * serve );
|
||||||
void flexnbd_switch( struct flexnbd * flexnbd, struct server *(listen_cb)(struct listen *) );
|
|
||||||
int flexnbd_signal_fd( struct flexnbd * flexnbd );
|
int flexnbd_signal_fd( struct flexnbd * flexnbd );
|
||||||
|
|
||||||
void flexnbd_mark_incomplete( struct flexnbd * flexnbd );
|
|
||||||
void flexnbd_mark_complete( struct flexnbd * flexnbd );
|
|
||||||
|
|
||||||
|
|
||||||
int flexnbd_serve( struct flexnbd * flexnbd );
|
int flexnbd_serve( struct flexnbd * flexnbd );
|
||||||
struct server * flexnbd_server( struct flexnbd * flexnbd );
|
struct server * flexnbd_server( struct flexnbd * flexnbd );
|
||||||
|
123
src/listen.c
123
src/listen.c
@@ -1,123 +0,0 @@
|
|||||||
#include "listen.h"
|
|
||||||
#include "serve.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "flexnbd.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
struct listen * listen_create(
|
|
||||||
struct flexnbd * flexnbd,
|
|
||||||
char* s_ip_address,
|
|
||||||
char* s_rebind_ip_address,
|
|
||||||
char* s_port,
|
|
||||||
char* s_rebind_port,
|
|
||||||
char* s_file,
|
|
||||||
int default_deny,
|
|
||||||
int acl_entries,
|
|
||||||
char** s_acl_entries,
|
|
||||||
int max_nbd_clients )
|
|
||||||
{
|
|
||||||
NULLCHECK( flexnbd );
|
|
||||||
struct listen * listen;
|
|
||||||
|
|
||||||
listen = (struct listen *)xmalloc( sizeof( struct listen ) );
|
|
||||||
listen->flexnbd = flexnbd;
|
|
||||||
listen->init_serve = server_create(
|
|
||||||
flexnbd,
|
|
||||||
s_ip_address,
|
|
||||||
s_port,
|
|
||||||
s_file,
|
|
||||||
default_deny,
|
|
||||||
acl_entries,
|
|
||||||
s_acl_entries,
|
|
||||||
1, 0);
|
|
||||||
listen->main_serve = server_create(
|
|
||||||
flexnbd,
|
|
||||||
s_rebind_ip_address ? s_rebind_ip_address : s_ip_address,
|
|
||||||
s_rebind_port ? s_rebind_port : s_port,
|
|
||||||
s_file,
|
|
||||||
default_deny,
|
|
||||||
acl_entries,
|
|
||||||
s_acl_entries,
|
|
||||||
max_nbd_clients, 1);
|
|
||||||
return listen;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void listen_destroy( struct listen * listen )
|
|
||||||
{
|
|
||||||
NULLCHECK( listen );
|
|
||||||
free( listen );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct server *listen_switch( struct listen * listen )
|
|
||||||
{
|
|
||||||
NULLCHECK( listen );
|
|
||||||
|
|
||||||
/* TODO: Copy acl from init_serve to main_serve */
|
|
||||||
/* TODO: rename underlying file from foo.INCOMPLETE to foo */
|
|
||||||
|
|
||||||
server_destroy( listen->init_serve );
|
|
||||||
listen->init_serve = NULL;
|
|
||||||
info( "Switched to the main server, serving." );
|
|
||||||
return listen->main_serve;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void listen_cleanup( struct listen * listen )
|
|
||||||
{
|
|
||||||
NULLCHECK( listen );
|
|
||||||
|
|
||||||
if ( flexnbd_switch_locked( listen->flexnbd ) ) {
|
|
||||||
flexnbd_unlock_switch( listen->flexnbd );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int do_listen( struct listen * listen )
|
|
||||||
{
|
|
||||||
NULLCHECK( listen );
|
|
||||||
|
|
||||||
int have_control = 0;
|
|
||||||
|
|
||||||
flexnbd_lock_switch( listen->flexnbd );
|
|
||||||
{
|
|
||||||
flexnbd_set_server( listen->flexnbd, listen->init_serve );
|
|
||||||
flexnbd_mark_incomplete( listen->flexnbd );
|
|
||||||
}
|
|
||||||
flexnbd_unlock_switch( listen->flexnbd );
|
|
||||||
|
|
||||||
/* WATCH FOR RACES HERE: flexnbd->serve is set, but the server
|
|
||||||
* isn't running yet and the switch lock is released.
|
|
||||||
*/
|
|
||||||
have_control = do_serve( listen->init_serve );
|
|
||||||
|
|
||||||
|
|
||||||
if( have_control ) {
|
|
||||||
flexnbd_mark_complete( listen->flexnbd );
|
|
||||||
|
|
||||||
info( "Taking control.");
|
|
||||||
flexnbd_switch( listen->flexnbd, listen_switch );
|
|
||||||
/* WATCH FOR RACES HERE: the server hasn't been
|
|
||||||
* restarted before we release the flexnbd switch lock.
|
|
||||||
* do_serve doesn't return, so there's not a lot of
|
|
||||||
* choice about that.
|
|
||||||
*/
|
|
||||||
do_serve( listen->main_serve );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
warn("Failed to take control, giving up.");
|
|
||||||
server_destroy( listen->init_serve );
|
|
||||||
listen->init_serve = NULL;
|
|
||||||
}
|
|
||||||
/* TODO: here we must signal the control thread to stop before
|
|
||||||
* it tries to */
|
|
||||||
server_destroy( listen->main_serve );
|
|
||||||
listen->main_serve = NULL;
|
|
||||||
|
|
||||||
debug("Listen done, cleaning up");
|
|
||||||
listen_cleanup( listen );
|
|
||||||
|
|
||||||
return have_control;
|
|
||||||
}
|
|
||||||
|
|
28
src/listen.h
28
src/listen.h
@@ -1,28 +0,0 @@
|
|||||||
#ifndef LISTEN_H
|
|
||||||
#define LISTEN_H
|
|
||||||
|
|
||||||
#include "flexnbd.h"
|
|
||||||
#include "serve.h"
|
|
||||||
|
|
||||||
struct listen {
|
|
||||||
struct flexnbd * flexnbd;
|
|
||||||
struct server * init_serve;
|
|
||||||
struct server * main_serve;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct listen * listen_create(
|
|
||||||
struct flexnbd * flexnbd,
|
|
||||||
char* s_ip_address,
|
|
||||||
char* s_rebind_ip_address,
|
|
||||||
char* s_port,
|
|
||||||
char* s_rebind_port,
|
|
||||||
char* s_file,
|
|
||||||
int default_deny,
|
|
||||||
int acl_entries,
|
|
||||||
char** s_acl_entries,
|
|
||||||
int max_nbd_clients );
|
|
||||||
void listen_destroy( struct listen* );
|
|
||||||
|
|
||||||
int do_listen( struct listen * );
|
|
||||||
|
|
||||||
#endif
|
|
51
src/mode.c
51
src/mode.c
@@ -32,31 +32,15 @@ static char serve_help_text[] =
|
|||||||
QUIET_LINE;
|
QUIET_LINE;
|
||||||
|
|
||||||
|
|
||||||
static struct option listen_options[] = {
|
static struct option * listen_options = serve_options;
|
||||||
GETOPT_HELP,
|
static char * listen_short_options = serve_short_options;
|
||||||
GETOPT_ADDR,
|
|
||||||
GETOPT_REBIND_ADDR,
|
|
||||||
GETOPT_PORT,
|
|
||||||
GETOPT_REBIND_PORT,
|
|
||||||
GETOPT_FILE,
|
|
||||||
GETOPT_SOCK,
|
|
||||||
GETOPT_DENY,
|
|
||||||
GETOPT_QUIET,
|
|
||||||
GETOPT_VERBOSE,
|
|
||||||
{0}
|
|
||||||
};
|
|
||||||
static char listen_short_options[] = "hl:L:p:P:f:s:d" SOPT_QUIET SOPT_VERBOSE;
|
|
||||||
static char listen_help_text[] =
|
static char listen_help_text[] =
|
||||||
"Usage: flexnbd " CMD_LISTEN " <options> [<acl_address>*]\n\n"
|
"Usage: flexnbd " CMD_LISTEN " <options> [<acl_address>*]\n\n"
|
||||||
"Listen for an incoming migration on ADDR:PORT, "
|
"Listen for an incoming migration on ADDR:PORT.\n\n"
|
||||||
"then switch to REBIND_ADDR:REBIND_PORT on completion "
|
|
||||||
"to serve FILE.\n\n"
|
|
||||||
HELP_LINE
|
HELP_LINE
|
||||||
"\t--" OPT_ADDR ",-l <ADDR>\tThe address to listen on.\n"
|
"\t--" OPT_ADDR ",-l <ADDR>\tThe address to listen on.\n"
|
||||||
"\t--" OPT_REBIND_ADDR ",-L <REBIND_ADDR>\tThe address to switch to, if given.\n"
|
|
||||||
"\t--" OPT_PORT ",-p <PORT>\tThe port to listen on.\n"
|
"\t--" OPT_PORT ",-p <PORT>\tThe port to listen on.\n"
|
||||||
"\t--" OPT_REBIND_PORT ",-P <REBIND_PORT>\tThe port to switch to, if given..\n"
|
"\t--" OPT_FILE ",-f <FILE>\tThe file to write to.\n"
|
||||||
"\t--" OPT_FILE ",-f <FILE>\tThe file to serve.\n"
|
|
||||||
"\t--" OPT_DENY ",-d\tDeny connections by default unless in ACL.\n"
|
"\t--" OPT_DENY ",-d\tDeny connections by default unless in ACL.\n"
|
||||||
SOCK_LINE
|
SOCK_LINE
|
||||||
VERBOSE_LINE
|
VERBOSE_LINE
|
||||||
@@ -234,9 +218,7 @@ void read_serve_param( int c, char **ip_addr, char **ip_port, char **file, char
|
|||||||
|
|
||||||
void read_listen_param( int c,
|
void read_listen_param( int c,
|
||||||
char **ip_addr,
|
char **ip_addr,
|
||||||
char **rebind_ip_addr,
|
|
||||||
char **ip_port,
|
char **ip_port,
|
||||||
char **rebind_ip_port,
|
|
||||||
char **file,
|
char **file,
|
||||||
char **sock,
|
char **sock,
|
||||||
int *default_deny )
|
int *default_deny )
|
||||||
@@ -249,15 +231,9 @@ void read_listen_param( int c,
|
|||||||
case 'l':
|
case 'l':
|
||||||
*ip_addr = optarg;
|
*ip_addr = optarg;
|
||||||
break;
|
break;
|
||||||
case 'L':
|
|
||||||
*rebind_ip_addr = optarg;
|
|
||||||
break;
|
|
||||||
case 'p':
|
case 'p':
|
||||||
*ip_port = optarg;
|
*ip_port = optarg;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
|
||||||
*rebind_ip_port = optarg;
|
|
||||||
break;
|
|
||||||
case 'f':
|
case 'f':
|
||||||
*file = optarg;
|
*file = optarg;
|
||||||
break;
|
break;
|
||||||
@@ -428,7 +404,15 @@ int mode_serve( int argc, char *argv[] )
|
|||||||
}
|
}
|
||||||
if ( err ) { exit_err( serve_help_text ); }
|
if ( err ) { exit_err( serve_help_text ); }
|
||||||
|
|
||||||
flexnbd = flexnbd_create_serving( ip_addr, ip_port, file, sock, default_deny, argc - optind, argv + optind, MAX_NBD_CLIENTS );
|
flexnbd = flexnbd_create_serving(
|
||||||
|
ip_addr,
|
||||||
|
ip_port,
|
||||||
|
file,
|
||||||
|
sock,
|
||||||
|
default_deny,
|
||||||
|
argc - optind,
|
||||||
|
argv + optind,
|
||||||
|
MAX_NBD_CLIENTS );
|
||||||
flexnbd_serve( flexnbd );
|
flexnbd_serve( flexnbd );
|
||||||
flexnbd_destroy( flexnbd );
|
flexnbd_destroy( flexnbd );
|
||||||
|
|
||||||
@@ -440,9 +424,7 @@ int mode_listen( int argc, char *argv[] )
|
|||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
char *ip_addr = NULL;
|
char *ip_addr = NULL;
|
||||||
char *rebind_ip_addr = NULL;
|
|
||||||
char *ip_port = NULL;
|
char *ip_port = NULL;
|
||||||
char *rebind_ip_port = NULL;
|
|
||||||
char *file = NULL;
|
char *file = NULL;
|
||||||
char *sock = NULL;
|
char *sock = NULL;
|
||||||
int default_deny = 0; // not on by default
|
int default_deny = 0; // not on by default
|
||||||
@@ -456,7 +438,7 @@ int mode_listen( int argc, char *argv[] )
|
|||||||
c = getopt_long(argc, argv, listen_short_options, listen_options, NULL);
|
c = getopt_long(argc, argv, listen_short_options, listen_options, NULL);
|
||||||
if ( c == -1 ) { break; }
|
if ( c == -1 ) { break; }
|
||||||
|
|
||||||
read_listen_param( c, &ip_addr, &rebind_ip_addr, &ip_port, &rebind_ip_port,
|
read_listen_param( c, &ip_addr, &ip_port,
|
||||||
&file, &sock, &default_deny );
|
&file, &sock, &default_deny );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,15 +454,12 @@ int mode_listen( int argc, char *argv[] )
|
|||||||
|
|
||||||
flexnbd = flexnbd_create_listening(
|
flexnbd = flexnbd_create_listening(
|
||||||
ip_addr,
|
ip_addr,
|
||||||
rebind_ip_addr,
|
|
||||||
ip_port,
|
ip_port,
|
||||||
rebind_ip_port,
|
|
||||||
file,
|
file,
|
||||||
sock,
|
sock,
|
||||||
default_deny,
|
default_deny,
|
||||||
argc - optind,
|
argc - optind,
|
||||||
argv + optind,
|
argv + optind );
|
||||||
MAX_NBD_CLIENTS );
|
|
||||||
success = flexnbd_serve( flexnbd );
|
success = flexnbd_serve( flexnbd );
|
||||||
flexnbd_destroy( flexnbd );
|
flexnbd_destroy( flexnbd );
|
||||||
|
|
||||||
|
@@ -17,8 +17,8 @@ class Environment
|
|||||||
@rebind_port1 = @available_ports.shift
|
@rebind_port1 = @available_ports.shift
|
||||||
@port2 = @available_ports.shift
|
@port2 = @available_ports.shift
|
||||||
@rebind_port2 = @available_ports.shift
|
@rebind_port2 = @available_ports.shift
|
||||||
@nbd1 = FlexNBD.new("../../build/flexnbd", @ip, @port1, @ip, @rebind_port1)
|
@nbd1 = FlexNBD.new("../../build/flexnbd", @ip, @port1)
|
||||||
@nbd2 = FlexNBD.new("../../build/flexnbd", @ip, @port2, @ip, @rebind_port2)
|
@nbd2 = FlexNBD.new("../../build/flexnbd", @ip, @port2)
|
||||||
|
|
||||||
@fake_pid = nil
|
@fake_pid = nil
|
||||||
end
|
end
|
||||||
@@ -115,7 +115,7 @@ class Environment
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def run_fake( name, addr, port, rebind_addr = addr, rebind_port = port, sock=nil )
|
def run_fake( name, addr, port, sock=nil )
|
||||||
fakedir = File.join( File.dirname( __FILE__ ), "fakes" )
|
fakedir = File.join( File.dirname( __FILE__ ), "fakes" )
|
||||||
fake = Dir[File.join( fakedir, name ) + "*"].sort.find { |fn|
|
fake = Dir[File.join( fakedir, name ) + "*"].sort.find { |fn|
|
||||||
File.executable?( fn )
|
File.executable?( fn )
|
||||||
@@ -124,11 +124,9 @@ class Environment
|
|||||||
raise "no fake executable" unless fake
|
raise "no fake executable" unless fake
|
||||||
raise "no addr" unless addr
|
raise "no addr" unless addr
|
||||||
raise "no port" unless port
|
raise "no port" unless port
|
||||||
raise "no rebind_addr" unless rebind_addr
|
|
||||||
raise "no rebind_port" unless rebind_port
|
|
||||||
|
|
||||||
@fake_pid = fork do
|
@fake_pid = fork do
|
||||||
exec [fake, addr, port, @nbd1.pid, rebind_addr, rebind_port, sock].map{|x| x.to_s}.join(" ")
|
exec [fake, addr, port, @nbd1.pid, sock].map{|x| x.to_s}.join(" ")
|
||||||
end
|
end
|
||||||
sleep(0.5)
|
sleep(0.5)
|
||||||
end
|
end
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
require 'flexnbd/fake_dest'
|
require 'flexnbd/fake_dest'
|
||||||
include FlexNBD
|
include FlexNBD
|
||||||
|
|
||||||
addr, port, src_pid, _, _, sock = *ARGV
|
addr, port, src_pid, sock = *ARGV
|
||||||
server = FakeDest.new( addr, port )
|
server = FakeDest.new( addr, port )
|
||||||
client = server.accept
|
client = server.accept
|
||||||
|
|
||||||
|
@@ -3,8 +3,8 @@
|
|||||||
# Connect, send a migration, entrust then *immediately* disconnect.
|
# Connect, send a migration, entrust then *immediately* disconnect.
|
||||||
# This simulates a client which fails while the client is blocked.
|
# This simulates a client which fails while the client is blocked.
|
||||||
#
|
#
|
||||||
# We attempt to reconnect immediately afterwards to prove that we can
|
# In this situation we expect the destination to quit with an error
|
||||||
# retry the mirroring.
|
# status.
|
||||||
|
|
||||||
require 'flexnbd/fake_source'
|
require 'flexnbd/fake_source'
|
||||||
include FlexNBD
|
include FlexNBD
|
||||||
@@ -28,7 +28,11 @@ system "kill -CONT #{srv_pid}"
|
|||||||
|
|
||||||
sleep(0.25)
|
sleep(0.25)
|
||||||
|
|
||||||
client2 = FakeSource.new( addr, port, "Timed out reconnecting" )
|
begin
|
||||||
client2.close
|
client2 = FakeSource.new( addr, port, "Expected timeout" )
|
||||||
|
fail "Unexpected reconnection"
|
||||||
|
rescue Timeout::Error
|
||||||
|
# expected
|
||||||
|
end
|
||||||
|
|
||||||
exit(0)
|
exit(0)
|
||||||
|
@@ -1,10 +1,9 @@
|
|||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
# Connect, send a migration, entrust then *immediately* disconnect.
|
# Connect, send a migration, entrust, read the reply, then disconnect.
|
||||||
# This simulates a client which fails while the client is blocked.
|
# This simulates a client which fails while the client is blocked.
|
||||||
#
|
#
|
||||||
# We attempt to reconnect immediately afterwards to prove that we can
|
# We expect the destination to quit with an error status.
|
||||||
# retry the mirroring.
|
|
||||||
|
|
||||||
require 'flexnbd/fake_source'
|
require 'flexnbd/fake_source'
|
||||||
include FlexNBD
|
include FlexNBD
|
||||||
@@ -22,11 +21,12 @@ client.close
|
|||||||
|
|
||||||
sleep(0.25)
|
sleep(0.25)
|
||||||
|
|
||||||
client2 = FakeSource.new( addr, port, "Timed out reconnecting to mirror" )
|
|
||||||
client2.send_mirror
|
|
||||||
|
|
||||||
sleep(1)
|
begin
|
||||||
client3 = FakeSource.new( rebind_addr, rebind_port, "Timed out reconnecting to read" )
|
client2 = FakeSource.new( addr, port, "Expected timeout" )
|
||||||
client3.close
|
fail "Unexpected reconnection"
|
||||||
|
rescue Timeout::Error
|
||||||
|
# expected
|
||||||
|
end
|
||||||
|
|
||||||
exit(0)
|
exit(0)
|
||||||
|
@@ -12,10 +12,11 @@ addr, port, srv_pid = *ARGV
|
|||||||
|
|
||||||
client = FakeSource.new( addr, port, "Timed out connecting" )
|
client = FakeSource.new( addr, port, "Timed out connecting" )
|
||||||
client.read_hello
|
client.read_hello
|
||||||
Process.kill( "STOP", srv_pid.to_i )
|
|
||||||
|
system "kill -STOP #{srv_pid}"
|
||||||
client.write_write_request( 0, 8 )
|
client.write_write_request( 0, 8 )
|
||||||
client.close
|
client.close
|
||||||
Process.kill( "CONT", srv_pid.to_i )
|
system "kill -CONT #{srv_pid}"
|
||||||
|
|
||||||
# This sleep ensures that we don't return control to the test runner
|
# This sleep ensures that we don't return control to the test runner
|
||||||
# too soon, giving the flexnbd process time to fall over if it's going
|
# too soon, giving the flexnbd process time to fall over if it's going
|
||||||
|
@@ -13,13 +13,13 @@ addr, port, srv_pid = *ARGV
|
|||||||
client = FakeSource.new( addr, port, "Timed out connecting" )
|
client = FakeSource.new( addr, port, "Timed out connecting" )
|
||||||
client.read_hello
|
client.read_hello
|
||||||
|
|
||||||
Process.kill( "STOP", srv_pid.to_i )
|
system "kill -STOP #{srv_pid}"
|
||||||
|
|
||||||
client.write_write_request( 0, 8 )
|
client.write_write_request( 0, 8 )
|
||||||
client.write_data( "12345678" )
|
client.write_data( "12345678" )
|
||||||
client.close
|
client.close
|
||||||
|
|
||||||
Process.kill( "CONT", srv_pid.to_i )
|
system "kill -CONT #{srv_pid}"
|
||||||
|
|
||||||
# This sleep ensures that we don't return control to the test runner
|
# This sleep ensures that we don't return control to the test runner
|
||||||
# too soon, giving the flexnbd process time to fall over if it's going
|
# too soon, giving the flexnbd process time to fall over if it's going
|
||||||
|
@@ -1,17 +1,14 @@
|
|||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
# Successfully send a migration, but squat on the IP and port which
|
# Successfully send a migration. This test just makes sure that the
|
||||||
# the destination wants to rebind to. The destination should retry
|
# happy path is covered. We expect the destination to quit with a
|
||||||
# every second, so we give it up then attempt to connect to the new
|
# success status.
|
||||||
# server.
|
|
||||||
|
|
||||||
require 'flexnbd/fake_source'
|
require 'flexnbd/fake_source'
|
||||||
include FlexNBD
|
include FlexNBD
|
||||||
|
|
||||||
addr, port, srv_pid, newaddr, newport = *ARGV
|
addr, port, srv_pid, newaddr, newport = *ARGV
|
||||||
|
|
||||||
squatter = TCPServer.open( newaddr, newport.to_i )
|
|
||||||
|
|
||||||
client = FakeSource.new( addr, port, "Timed out connecting" )
|
client = FakeSource.new( addr, port, "Timed out connecting" )
|
||||||
client.send_mirror()
|
client.send_mirror()
|
||||||
|
|
||||||
|
@@ -166,7 +166,7 @@ end # class ValgrindExecutor
|
|||||||
# Noddy test class to exercise FlexNBD from the outside for testing.
|
# Noddy test class to exercise FlexNBD from the outside for testing.
|
||||||
#
|
#
|
||||||
class FlexNBD
|
class FlexNBD
|
||||||
attr_reader :bin, :ctrl, :pid, :ip, :port, :rebind_ip, :rebind_port
|
attr_reader :bin, :ctrl, :pid, :ip, :port
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def counter
|
def counter
|
||||||
@@ -195,7 +195,7 @@ class FlexNBD
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(bin, ip, port, rebind_ip = ip, rebind_port = port)
|
def initialize(bin, ip, port)
|
||||||
@bin = bin
|
@bin = bin
|
||||||
@do_debug = ENV['DEBUG']
|
@do_debug = ENV['DEBUG']
|
||||||
@debug = build_debug_opt
|
@debug = build_debug_opt
|
||||||
@@ -204,8 +204,6 @@ class FlexNBD
|
|||||||
@ctrl = "/tmp/.flexnbd.ctrl.#{Time.now.to_i}.#{rand}"
|
@ctrl = "/tmp/.flexnbd.ctrl.#{Time.now.to_i}.#{rand}"
|
||||||
@ip = ip
|
@ip = ip
|
||||||
@port = port
|
@port = port
|
||||||
@rebind_ip = rebind_ip
|
|
||||||
@rebind_port = rebind_port
|
|
||||||
@kill = []
|
@kill = []
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -235,8 +233,6 @@ class FlexNBD
|
|||||||
"--addr #{ip} "\
|
"--addr #{ip} "\
|
||||||
"--port #{port} "\
|
"--port #{port} "\
|
||||||
"--file #{file} "\
|
"--file #{file} "\
|
||||||
"--rebind-addr #{rebind_ip} " \
|
|
||||||
"--rebind-port #{rebind_port} " \
|
|
||||||
"--sock #{ctrl} "\
|
"--sock #{ctrl} "\
|
||||||
"#{@debug} "\
|
"#{@debug} "\
|
||||||
"#{acl.join(' ')}"
|
"#{acl.join(' ')}"
|
||||||
|
@@ -80,15 +80,15 @@ class TestDestErrorHandling < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def test_cant_rebind_dies
|
def test_straight_migration
|
||||||
@env.nbd1.can_die(6)
|
@env.nbd1.can_die(0)
|
||||||
run_fake( "source/successful_transfer" )
|
run_fake( "source/successful_transfer" )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
def run_fake( name )
|
def run_fake( name )
|
||||||
@env.run_fake( name, @env.ip, @env.port1, @env.ip, @env.rebind_port1 )
|
@env.run_fake( name, @env.ip, @env.port1 )
|
||||||
assert @env.fake_reports_success, "#{name} failed."
|
assert @env.fake_reports_success, "#{name} failed."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -97,7 +97,7 @@ class TestSourceErrorHandling < Test::Unit::TestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def run_fake(name, opts = {})
|
def run_fake(name, opts = {})
|
||||||
@env.run_fake( name, @env.ip, @env.port2, @env.ip, @env.port2, @env.nbd1.ctrl )
|
@env.run_fake( name, @env.ip, @env.port2, @env.nbd1.ctrl )
|
||||||
stdout, stderr = @env.mirror12_unchecked
|
stdout, stderr = @env.mirror12_unchecked
|
||||||
assert_success
|
assert_success
|
||||||
assert_match( opts[:err], stderr ) if opts[:err]
|
assert_match( opts[:err], stderr ) if opts[:err]
|
||||||
|
@@ -1,57 +0,0 @@
|
|||||||
#include "serve.h"
|
|
||||||
#include "listen.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "flexnbd.h"
|
|
||||||
|
|
||||||
#include <check.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
START_TEST( test_defaults_main_serve_opts )
|
|
||||||
{
|
|
||||||
struct flexnbd flexnbd;
|
|
||||||
struct listen * listen = listen_create( &flexnbd, "127.0.0.1", NULL, "4777", NULL,
|
|
||||||
"foo", 0, 0, NULL, 1 );
|
|
||||||
NULLCHECK( listen );
|
|
||||||
struct server *init_serve = listen->init_serve;
|
|
||||||
struct server *main_serve = listen->main_serve;
|
|
||||||
NULLCHECK( init_serve );
|
|
||||||
NULLCHECK( main_serve );
|
|
||||||
|
|
||||||
fail_unless( 0 == memcmp(&init_serve->bind_to,
|
|
||||||
&main_serve->bind_to,
|
|
||||||
sizeof( union mysockaddr )),
|
|
||||||
"Main serve bind_to was not set" );
|
|
||||||
}
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
|
|
||||||
Suite* listen_suite(void)
|
|
||||||
{
|
|
||||||
Suite *s = suite_create("listen");
|
|
||||||
TCase *tc_create = tcase_create("create");
|
|
||||||
|
|
||||||
tcase_add_exit_test(tc_create, test_defaults_main_serve_opts, 0);
|
|
||||||
|
|
||||||
suite_add_tcase(s, tc_create);
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
# define LOG_LEVEL 0
|
|
||||||
#else
|
|
||||||
# define LOG_LEVEL 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
log_level = LOG_LEVEL;
|
|
||||||
int number_failed;
|
|
||||||
Suite *s = listen_suite();
|
|
||||||
SRunner *sr = srunner_create(s);
|
|
||||||
srunner_run_all(sr, CK_NORMAL);
|
|
||||||
number_failed = srunner_ntests_failed(sr);
|
|
||||||
srunner_free(sr);
|
|
||||||
return (number_failed == 0) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
Reference in New Issue
Block a user