List:Commits« Previous MessageNext Message »
From:Serge Kozlov Date:July 7 2010 6:45pm
Subject:bzr commit into nuts branch (Serge.Kozlov:372) WL#5333
View as plain text  
#At file:///home/ksm/oracle/repo/WL5333/nuts-3/ based on revid:serge.kozlov@stripped

  372 Serge Kozlov	2010-07-07
      WL#5333. Support of MySQL Cluster for NUTS

    added:
      suites/samples/cluster.pm
    modified:
      lib/My.pm
      lib/My/Nuts/Instance/Server.pm
      lib/My/Nuts/Library/Kernel/Manager.pm
      lib/My/Nuts/Library/Kernel/Server.pm
      lib/My/Nuts/Library/Kernel/ServerResult.pm
      lib/My/Nuts/Library/Tests/SimpleTest.pm
      lib/My/Nuts/Management/Manager.pm
      lib/My/Nuts/Management/SimpleDeployer.pm
      lib/My/Nuts/Properties/MyProperties.pm
=== modified file 'lib/My.pm'
--- a/lib/My.pm	2009-04-13 19:41:13 +0000
+++ b/lib/My.pm	2010-07-07 18:45:40 +0000
@@ -14,6 +14,7 @@ use constant ROLE_SLAVE            => 'S
 use constant ROLE_BOTH             => 'B';
 use constant WAIT                  => 1;
 use constant EFFORT                => 5;
+use constant NDB_EFFORT            => 60;
 use constant DIE                   => 0;
 use constant CONTINUE              => 1;
 use constant UNDEPLOYED            => 0;
@@ -26,6 +27,12 @@ use constant SUCCESS_IN_DEPLOYMENT => 0;
 use constant FAILURE_IN_DEPLOYMENT => -1;
 use constant UP                    => 100;
 use constant DOWN                  => 101;
+use constant MYSQLD		   => 500;
+use constant NODE_NDB_MGMD	   => 501;
+use constant NODE_NDBD		   => 502;
+use constant NODE_MYSQLD	   => 503;
+use constant NODE_CONNECTED	   => 600;
+use constant NODE_NOT_CONNECTED	   => 601;
 use constant TRUE                  => 1000;
 use constant FALSE                 => 2000;
 

=== modified file 'lib/My/Nuts/Instance/Server.pm'
--- a/lib/My/Nuts/Instance/Server.pm	2009-06-30 14:20:29 +0000
+++ b/lib/My/Nuts/Instance/Server.pm	2010-07-07 18:45:40 +0000
@@ -11,7 +11,9 @@ use DBI;
 use Class::Std::Utils;
 use threads;
 use threads::shared qw(share shared_clone);
+
 $My::Nuts::Instance::Server::version = "0.1";
+my %server_type;
 my %state;
 my %pid;
 my %port;
@@ -43,6 +45,7 @@ sub new
       $in_fault_injection_properties->{'network faults'};
     $server_id{$ident}  = $self->get_my_properties ()->get_my_server_id ();
     $connection{$ident} = {};
+    $server_type{$ident} = $self->get_my_properties ()->get_my_server_type ();;
     $test{$ident}       = $in_test;
     $reportlog{$ident}  = $in_reportlog;
     share (%saved_result);
@@ -90,6 +93,13 @@ sub create_thread_server
     return $self;
 }
 
+sub get_server_type
+{
+    my $self = shift;
+    my $ident = ident ($self);
+    return $server_type{$ident};
+}
+
 sub set_test
 {
     my ( $self, $in_test ) = @_;

=== modified file 'lib/My/Nuts/Library/Kernel/Manager.pm'
--- a/lib/My/Nuts/Library/Kernel/Manager.pm	2010-03-31 20:40:41 +0000
+++ b/lib/My/Nuts/Library/Kernel/Manager.pm	2010-07-07 18:45:40 +0000
@@ -5,7 +5,7 @@ our @EXPORT =
   qw(get_server start_server ok_start_server stop_server ok_stop_server deploy_server 
     undeploy_server wait_start_server ok_wait_start_server wait_stop_server 
     ok_wait_stop_server get_data_dir get_base_dir get_started_server
-    updown_server ok_updown_server);
+    updown_server ok_updown_server set_server_cmd_line_args);
 use strict;
 use warnings;
 use My;
@@ -28,7 +28,7 @@ sub get_started_server
     }
     my $server_id = $properties{"my.server.id"};
     my $server =
-      get_server ( ( "my.server.id" => $properties{"my.server.id"} ) );
+      get_server ( %properties );
     $logger->info ("deploy server: ($server_id)");
     if ( deploy_server ($server) == My::SUCCESS )
     {
@@ -49,6 +49,7 @@ sub get_server
     {
         return (undef);
     }
+    $properties{"my.server.type"} = My::MYSQLD unless ( defined $properties{"my.server.type"} );
     my $manager = $My::Nuts::Management::Manager::reference;
     return $manager->get_server (%properties);
 }
@@ -249,6 +250,11 @@ sub wait_stop_server
     return $manager->wait_stop_server ( $server, $wait );
 }
 
+sub set_server_cmd_line_args
+{
+    return $My::Nuts::Management::Manager::reference->set_server_cmd_line_args(@_);
+}
+
 sub get_data_dir
 {
     my ($server) = @_;

=== modified file 'lib/My/Nuts/Library/Kernel/Server.pm'
--- a/lib/My/Nuts/Library/Kernel/Server.pm	2009-11-25 19:05:08 +0000
+++ b/lib/My/Nuts/Library/Kernel/Server.pm	2010-07-07 18:45:40 +0000
@@ -5,7 +5,7 @@ our @EXPORT =
   qw(execute get_buildproperties get_my_properties get_dsn 
   set_buildproperties set_my_properties async_sql async_result 
   async_function async_join ok_sql err_sql sql ok_execute 
-  ok_async_result state check ok_system);
+  ok_async_result state check ok_system get_server_type);
 use strict;
 use warnings;
 use My;
@@ -230,6 +230,12 @@ sub get_dsn
     return $server->get_dsn();
 }
 
+sub get_server_type
+{
+    my ($server) = @_;
+    return $server->get_my_properties()->get_my_server_type();
+}
+
 1;
 __END__
 

=== modified file 'lib/My/Nuts/Library/Kernel/ServerResult.pm'
--- a/lib/My/Nuts/Library/Kernel/ServerResult.pm	2010-03-30 19:58:02 +0000
+++ b/lib/My/Nuts/Library/Kernel/ServerResult.pm	2010-07-07 18:45:40 +0000
@@ -3,7 +3,7 @@ use Exporter;
 our @ISA = qw(Exporter);
 our @EXPORT =
   qw(compare_dbs ok_compare_dbs get_supported_engines get_table_list get_variable get_status 
-    get_errmsg_by_num ok_wait_status ok_wait_sql);
+    get_errmsg_by_num ok_wait_status ok_wait_sql ok_sql_result);
 use strict;
 use warnings;
 use My;
@@ -104,17 +104,60 @@ sub ok_compare_dbs
 sub sql_result
 {
     my ($server, $query) = @_;
-    my $result = undef;
+    my $results;
     my $rs = sql ( $server, $query );
+    my $idx= 1;
     if ($rs)
-    {
+    {	
 	my @rs_data = get_next($rs);
-	if ( defined ($rs_data[0]) )
+	while ( defined $rs_data[0] )
 	{
-	    $result = $rs_data[0];
+	    push( @{$results->{$idx}}, @rs_data );
+	    @rs_data = get_next($rs);
+	    $idx++;
 	}
     }
-    return $result;
+    return $results;
+}
+
+sub ok_sql_result
+{
+    my ($server, $query, $expected_results) = @_;
+    my $results = sql_result($server, $query);
+    my $diff_list = "";
+    my $i;
+    foreach my $idx ( keys (%$expected_results) )
+    {
+	if ( defined ($results->{$idx}) )
+	{
+	    for ($i = 0; $i < scalar(@{$expected_results->{$idx}}); $i++)
+	    {
+		my $expected_value = $expected_results->{$idx}->[$i];
+		if ( defined ($results->{$idx}->[$i]) )
+		{
+		    my $recieved_value = $results->{$idx}->[$i];
+		    if ( $recieved_value !~ m/^$expected_value$/ )
+		    {
+			$diff_list .= "$idx/$i: '$expected_value' != '$recieved_value', ";
+		    }
+		}
+		else
+		{
+		    $diff_list .= "record $idx/$i '$expected_value' not found, ";
+		}
+	    }
+	}
+	else
+	{
+	    $diff_list .= "row $idx not found, ";
+	}
+    }
+    $diff_list =~ s/\, $//;
+    ok ($diff_list eq "", "Compare the expected data with rows returned by query");
+    if ($diff_list =~ m/^.+$/)
+    {
+	diag("Diff found for query '$query': " . $diff_list);
+    }
 }
 
 sub get_supported_engines
@@ -144,7 +187,7 @@ sub get_table_list
     my $rs;
     if (defined $dbname)
     {
-	$rs = sql ( $conn, "SHOW TABLES FROM $dbname;" );
+	$rs = sql ( $conn, "SHOW TABLES FROM $dbname" );
     }
     else
     {

=== modified file 'lib/My/Nuts/Library/Tests/SimpleTest.pm'
--- a/lib/My/Nuts/Library/Tests/SimpleTest.pm	2009-11-25 01:10:24 +0000
+++ b/lib/My/Nuts/Library/Tests/SimpleTest.pm	2010-07-07 18:45:40 +0000
@@ -1,7 +1,7 @@
 package My::Nuts::Library::Tests::SimpleTest;
 use Exporter;
 our @ISA    = qw(Exporter My::Nuts::Test);
-our @EXPORT = qw(server ok_server get_combination);
+our @EXPORT = qw(server ok_server get_combination cluster ok_cluster get_cluster_nodes);
 use strict;
 use warnings;
 use My;
@@ -11,6 +11,7 @@ use My::Nuts::Library::Kernel::Server;
 use Class::Std::Utils;
 use Test::More;
 my %server;
+my %cluster_counter;
 my %counter;
 use Log::Log4perl qw(get_logger :levels);
 my $logger = get_logger ("My::Nuts::Library::Tests::SimpleTest");
@@ -23,14 +24,14 @@ sub get_combination
 
 sub ok_server
 {
-    my ($self) = @_;
+    my ($self, %properties) = @_;
     if ( is_defined ($self) == My::FALSE)
     {
         ok ( 0, "Error in the parameters for server" )
           or diag ("Check the parameters (test)");
         return (My::FAILURE);
     }
-    my $ret = server($self);
+    my $ret = server($self, %properties);
 
     if (is_server($ret) == My::FALSE || state($ret) != My::RUNNING)
     {
@@ -42,13 +43,61 @@ sub ok_server
 
 sub server
 {
-    my ($self) = @_;
+    my ($self, %properties) = @_;
     my $ident = ident ($self);
-    $counter{$ident} = $counter{$ident} ? ( $counter{$ident} + 1 ) : 1;
-    $server{$ident} = get_started_server ( "my.server.id" => $counter{$ident} );
+    $counter{$ident} = $counter{$ident} ? ( $counter{$ident} + 1 ) : 1;	
+    $properties{"my.server.id"} = $counter{$ident};
+    $server{$ident} = get_started_server ( %properties );
     return ( $server{$ident} );
 }
 
+sub ok_cluster
+{
+    my ($self, $parameters) = @_;
+    my $cluster= cluster( $self, $parameters );
+    foreach my $node_type (keys %$cluster)
+    {
+	foreach my $node ( @{$cluster->{$node_type}} )
+	{
+	    if (is_server($node) == My::FALSE || state($node) != My::RUNNING)
+	    {
+    		$logger->fatal("Error allocating cluster node . Please, check the logs for more information.");
+    		die;
+	    }
+	}
+    }
+    return $cluster;
+}
+
+sub cluster
+{
+    my ($self, $parameters) = @_;
+    my $ident = ident ($self);
+    $parameters->{"mysqld_number"}= 3 unless (defined $parameters->{"mysqld_number"});
+    $cluster_counter{$ident} = $cluster_counter{$ident} ? ( $cluster_counter{$ident} + 1 ) : 1;	
+    my $cluster = {};
+    my $ndb_mgmd= server($self, "my.server.type" => My::NODE_NDB_MGMD, "my.cluster.id" => $cluster_counter{$ident});
+    my $connect_string= $ndb_mgmd->get_ip_address() . ":" . $ndb_mgmd->get_port();
+    push( @{$cluster->{My::NODE_NDB_MGMD}}, $ndb_mgmd);
+    push( @{$cluster->{My::NODE_NDBD}}, server($self, "my.server.type" => My::NODE_NDBD, "my.connect.string" => $connect_string, "my.cluster.id" => $cluster_counter{$ident}) );
+    for (1 .. $parameters->{"mysqld_number"})
+    {
+	push( @{$cluster->{My::NODE_MYSQLD}}, server($self, "my.server.type" => My::NODE_MYSQLD, "my.connect.string" => $connect_string, "my.cluster.id" => $cluster_counter{$ident}) );
+    }
+    return $cluster;
+}
+
+sub get_cluster_nodes
+{
+    my ( $cluster, $server_type ) = @_;    
+    my @nodes;
+    foreach my $node ( @{$cluster->{$server_type}} )
+    {
+        push (@nodes, $node);
+    }
+    return @nodes;
+}
+
 sub prepare
 {
     return;

=== modified file 'lib/My/Nuts/Management/Manager.pm'
--- a/lib/My/Nuts/Management/Manager.pm	2010-03-31 20:40:41 +0000
+++ b/lib/My/Nuts/Management/Manager.pm	2010-07-07 18:45:40 +0000
@@ -407,6 +407,13 @@ sub set_updown_server
     return $deployer{$ident}->set_updown_server ( $server );
 }
 
+sub set_server_cmd_line_args
+{
+    my $self = shift;
+    my $ident = ident($self);
+    return $deployer{$ident}->set_server_cmd_line_args( @_ );
+}
+
 sub get_machines
 {
     my ($self) = @_;

=== modified file 'lib/My/Nuts/Management/SimpleDeployer.pm'
--- a/lib/My/Nuts/Management/SimpleDeployer.pm	2010-03-31 20:40:41 +0000
+++ b/lib/My/Nuts/Management/SimpleDeployer.pm	2010-07-07 18:45:40 +0000
@@ -7,7 +7,11 @@ use My::Nuts::Report::Report;
 use My::Nuts::Report::Debug;
 use My::Nuts::Report::ReportLog;
 use My::Nuts::util::mysql;
+use Cwd;
 use File::Path;
+use File::Spec;
+use IO::File;
+use Switch;
 use Class::Std::Utils;
 use Exporter;
 our @ISA = qw(Exporter);
@@ -21,10 +25,14 @@ my %port;
 my %baseport;
 my %nuts_deployer_thread;
 my %updown_server_params;
+my %cluster;
 
 # maps $testname/$server_id id to build
 my %assigned_builds;
 
+# default server command line arguments
+my %default_server_args;
+
 sub new
 {
     my ( $class, %params ) = @_;
@@ -72,16 +80,17 @@ sub deploy_server
     }
     my $build =
       $self->_locate_build_file_for_server ( $server, $path_to_build );
+    my $server_type= $server->get_my_properties->get_my_server_type();
     if ( !$build )
     {
         $server->set_state (My::UNABLE_TO_DEPLOY);
         if ($path_to_build)
         {
-          $logger->error ("Unable to find suitable build for sever " . $server->get_my_properties->get_my_server_id() .  " in $path_to_build. Check that path exists and contains an executable mysqld binary.");
+          $logger->error ("Unable to find suitable build for server " . $server->get_my_properties->get_my_server_id() .  " in $path_to_build. Check that path exists and contains an executable mysqld binary.");
         }
         else 
         {
-          $logger->error ("Unable to find suitable build for sever " . $server->get_my_properties->get_my_server_id() .  ". Most likely the build option was not defined.");
+          $logger->error ("Unable to find suitable build for server " . $server->get_my_properties->get_my_server_id() .  ". Most likely the build option was not defined.");
         }
         return My::FAILURE;
     }
@@ -107,35 +116,78 @@ sub deploy_server
                       . $build->get_build_location
                       . " $full_base_dir" );
 
-    # For updown server we should use datadir/ip/port from previos server
-    if ( $self->is_updown_server($server) == My::TRUE )
+    # MySQL server stuff
+    if ($server_type == My::MYSQLD || $server_type == My::NODE_MYSQLD)
     {
-	$server->set_ip_address (  $updown_server_params{$server}{"ip_address"} );	
-	$server->set_port (  $updown_server_params{$server}{"port"} );	
-	$reportlog->log (   "REUSE_DATADIR "
+	# For updown server we should use datadir/ip/port from previos server
+	if ( $self->is_updown_server($server) == My::TRUE )
+	{
+	    $server->set_ip_address (  $updown_server_params{$server}{"ip_address"} );	
+	    $server->set_port (  $updown_server_params{$server}{"port"} );	
+	    $reportlog->log (   "REUSE_DATADIR "
                       . $server->get_my_properties ()->get_my_server_id ()
                       . " $full_data_dir" );
-    }
-    else
-    {
-	# install db if the directory does not exist
-        rmtree ( [$full_data_dir], 0, 1 );
-        $self->_mkdirs  ($full_data_dir);
+	}
+	else
+	{
+	    # install db if the directory does not exist
+    	    rmtree ( [$full_data_dir], 0, 1 );
+    	    $self->_mkdirs  ($full_data_dir);
     
-	$self->_install_db ( $full_base_dir, $full_data_dir, $server );
-	$reportlog->log (   "INSTALL_DATADIR "
+	    $self->_install_db ( $full_base_dir, $full_data_dir, $server );
+	    $reportlog->log (   "INSTALL_DATADIR "
                       . $server->get_my_properties ()->get_my_server_id ()
                       . " $full_data_dir" );
                       
-	$server->set_port ( $port{$ident} );
-	$port{$ident}++;
-    }
-    $logger->debug (   $server->get_my_properties->get_my_server_id
+	    $server->set_port ( $port{$ident} );
+	    $port{$ident}++;
+	}
+	$logger->debug (   $server->get_my_properties->get_my_server_id
                      . " got PORT: "
                      . $server->get_port );
 
-    # set server state to idle as it is not started
-    $server->set_state (My::IDLE);
+    	$self->_group_cluster_dirs($server) if ($server_type == My::NODE_MYSQLD);	
+	# set server state to idle as it is not started
+	$server->set_state (My::IDLE);
+    }
+    elsif ($server_type == My::NODE_NDB_MGMD)
+    {
+    	rmtree ( [$full_data_dir], 0, 1 );
+    	$self->_mkdirs  ($full_data_dir);	
+	$server->set_port ( $port{$ident} );
+    	my $fh = new IO::File File::Spec->catfile($full_data_dir, "config.ini"), "w";
+    	if (defined $fh)
+    	{
+    	    print $fh join ("\n", 
+    		"[ndbd default]",
+    		    "NoOfReplicas= 1",
+    		    "",
+    		"[ndb_mgmd]", 
+    		    "Id= " . $server->get_my_properties->get_my_server_id(),
+    		    "PortNumber= " . $port{$ident},
+    		    "HostName= " . $server->get_ip_address(),
+    		    "DataDir= " . $full_data_dir,
+    		    "",
+    		"[ndbd]",
+    		    "\n"
+    	    );
+    	    for (1..16) 
+    	    {
+    		print $fh "[mysqld]\n\n";
+    	    }
+    	    $fh = undef;
+    	}
+	$port{$ident}++;
+	$server->set_state (My::IDLE);
+    	$self->_group_cluster_dirs($server);	
+    }
+    elsif ($server_type == My::NODE_NDBD)
+    {
+    	rmtree ( [$full_data_dir], 0, 1 );
+    	$self->_mkdirs  ($full_data_dir);
+    	$self->_group_cluster_dirs($server);	
+	$server->set_state (My::IDLE);
+    }
     return My::SUCCESS;
 }
 
@@ -220,8 +272,22 @@ sub start_server
     }
 
     my ( $full_base_dir, $full_data_dir ) = $self->get_server_dirs ($server);
-    $server->set_pid (
-             $self->_start_server ( $full_base_dir, $full_data_dir, $server ) );
+    my $type = $server->get_my_properties->get_my_server_type();
+    if ($type == My::MYSQLD || $type == My::NODE_MYSQLD)
+    {
+	$server->set_pid (
+             $self->_start_mysql_server ( $full_base_dir, $full_data_dir, $server ) );
+    }
+    elsif ($type == My::NODE_NDB_MGMD)
+    {
+	$server->set_pid (
+             $self->_start_ndb_mgmd_server ( $full_base_dir, $full_data_dir, $server ) );	
+    }
+    elsif ($type == My::NODE_NDBD)
+    {
+	$server->set_pid (
+             $self->_start_ndbd_server ( $full_base_dir, $full_data_dir, $server ) );	
+    }
     my $reportlog = $server->get_reportlog ();
     $reportlog->log (
                 "START " . $server->get_my_properties ()->get_my_server_id () );
@@ -238,7 +304,19 @@ sub stop_server
         return My::SUCCESS;
     }
     my ( $full_base_dir, $full_data_dir ) = $self->get_server_dirs ($server);
-    $self->_stop_server ( $full_base_dir, $server );
+    my $type = $server->get_my_properties->get_my_server_type();
+    if ($type == My::MYSQLD || $type == My::NODE_MYSQLD)
+    {
+	$self->_stop_mysql_server ( $full_base_dir, $server );
+    }
+    elsif ($type == My::NODE_NDB_MGMD)
+    {
+	$self->_cluster_shutdown($server);
+    }
+    elsif ($type == My::NODE_NDBD)
+    {
+	$self->_cluster_shutdown($server);
+    }    
     $server->set_state (My::IDLE);
     my $reportlog = $server->get_reportlog ();
     $reportlog->log (
@@ -265,6 +343,7 @@ sub wait_start_server
 {
     my ( $self, $server, $wait, $test_name ) = @_;
     my $attempt = 0;
+    my $server_type= $server->get_my_properties ()->get_my_server_type;
     if ( $server->get_state() != My::RUNNING )
     {
         return My::FAILURE;
@@ -273,13 +352,28 @@ sub wait_start_server
     {
         $wait = My::WAIT;
     }
-    do
+    my $effort= My::EFFORT;
+    if ($server_type == My::MYSQLD)
     {
-        sleep($wait);
-        $attempt = $attempt + 1;
-      } while (    ( not defined $server->get_connection () )
+	do
+	{
+    	    sleep($wait);
+    	    $attempt = $attempt + 1;
+        } while (    ( not defined $server->get_connection () )
                 && ( $attempt < My::EFFORT ) );
-    if ( $attempt >= My::EFFORT )
+    }
+    elsif ($server_type == My::NODE_NDB_MGMD || $server_type == My::NODE_NDBD || $server_type == My::NODE_MYSQLD)
+    {
+	$effort= My::NDB_EFFORT;
+	do
+	{
+    	    sleep($wait);
+    	    $attempt = $attempt + 1;
+    	
+        } while (    ( $self->_get_cluster_node_status($server) == My::NODE_NOT_CONNECTED )
+                && ( $attempt < My::NDB_EFFORT ) );
+    }
+    if ( $attempt >= $effort )
     {
         $logger->fatal (   "Server "
                          . $server->get_my_properties ()->get_my_server_id ()
@@ -325,6 +419,22 @@ sub wait_stop_server
     return My::SUCCESS;
 }
 
+sub set_server_cmd_line_args
+{
+    my $self = shift;
+    if ( scalar(@_) > 0)
+    {
+	my $stype = "default";
+	if ( $_[0] =~ m/^\d+$/ && ($_[0] == My::MYSQLD || $_[0] == My::NODE_MYSQLD 
+	    || $_[0] == My::NODE_NDBD || $_[0] == My::NODE_NDB_MGMD ) )
+	{
+	    $stype = shift;
+	}
+	$default_server_args{$stype}= undef;
+	push( @{$default_server_args{$stype}}, @_);
+    }
+}
+
 sub _locate_build_file_for_server
 {
     my ( $self, $server, $path_to_build ) = @_;
@@ -476,13 +586,56 @@ sub _install_db
          );
 }
 
-sub _start_server
+sub _add_default_server_args
+{
+    my $self = shift;
+    my $stype = shift;
+    my $command_line = shift;
+    if (! defined $default_server_args{$stype} )
+    {
+	$stype= "default";
+    }
+    foreach my $arg ( @{$default_server_args{$stype}} )
+    {
+	if ($arg =~ m/^\!(.+)/)
+	{
+	    $command_line =~ s/(^| )$1[a-zA-Z0-9\-\_\=]*( |$)//;
+	}
+	elsif ($arg =~ m/(.+)=(.+)/)
+	{
+	    my ($arg_name, $arg_value)= ($1, $2);	    
+	    if ($command_line =~ m/ ($arg_name=\w+)/)
+	    {
+		$command_line =~ s/$1/$arg/;
+	    }
+	    else
+	    {
+		$command_line .= " ".$arg;
+	    }
+	}
+	else
+	{
+	    if ($command_line !~ m/ $arg( |$)/)
+	    {
+		$command_line .= " ".$arg;
+	    }
+	}
+    }
+    return $command_line;
+}
+
+sub _start_mysql_server
 {
     my ( $self, $full_base_dir, $full_data_dir, $server ) = @_;
     my $port      = $server->get_port;
     my $test      = $server->get_test;
     my $server_id = $server->get_my_properties->get_my_server_id;
     my $params    = $server->get_parameters;
+    if ($server->get_my_properties()->get_my_server_type == My::NODE_MYSQLD)
+    {
+	my $cluster_id= $server->get_my_properties->get_my_cluster_id;
+	$params =~ s/--server-id=\d+/--server-id=$cluster_id/;
+    }
     my $command   = File::Spec->catfile ( $full_base_dir, "libexec", "mysqld" );
     $command = verify_file ( $command, My::CONTINUE );
     if ( not defined $command )
@@ -519,9 +672,14 @@ sub _start_server
     {
         $command = $command . " " . $params;
     }
+    if (defined $server->get_my_properties->get_my_connect_string())
+    {
+	$command .= " --ndbcluster=ON --ndb-nodeid=$server_id --ndb-connectstring=" . $server->get_my_properties->get_my_connect_string();
+    }
     $logger->debug (   "command: $command [redirect to: "
                      . $server->get_std_out_err_stream
                      . " ].\n" );
+    $command= $self->_add_default_server_args($server->get_my_properties()->get_my_server_type, $command);
     return
       My::Nuts::Interfaces::Process::spawn_proc_async (
                       $command,
@@ -532,7 +690,68 @@ sub _start_server
       );
 }
 
-sub _stop_server
+sub _start_ndb_mgmd_server
+{
+    my ( $self, $full_base_dir, $full_data_dir, $server ) = @_;
+    my $port      = $server->get_port;
+    my $test      = $server->get_test;
+    my $server_id = $server->get_my_properties->get_my_server_id;
+    my $params    = $server->get_parameters;
+    my $command   = File::Spec->catfile ( $full_base_dir, "libexec", "ndb_mgmd" );
+    $command = verify_file ( $command, My::CONTINUE );
+    if ( not defined $command )
+    {
+        $command =
+            File::Spec->catfile ( $full_base_dir, "storage", "ndb", "src", "mgmsrv", "ndb_mgmd" )
+    }
+    $command .= " --config-file=" . File::Spec->catfile( $full_data_dir, "config.ini" ) . " --nodaemon";
+    $logger->debug (   "command: $command [redirect to: "
+                     . $server->get_std_out_err_stream
+                     . " ].\n" );
+    return
+      My::Nuts::Interfaces::Process::spawn_proc_async (
+                      $command,
+                      {
+                        STDOUT => $server->get_std_out_err_stream->get_handler,
+                        STDERR => $server->get_std_out_err_stream->get_handler
+                      }
+      );
+
+}
+
+sub _start_ndbd_server
+{
+    my ( $self, $full_base_dir, $full_data_dir, $server ) = @_;
+    my $port      = $server->get_port;
+    my $test      = $server->get_test;
+    my $server_id = $server->get_my_properties->get_my_server_id;
+    my $params    = $server->get_parameters;
+    my $command   = File::Spec->catfile ( $full_base_dir, "libexec", "ndbd" );
+    $command = verify_file ( $command, My::CONTINUE );
+    if ( not defined $command )
+    {
+        $command =
+            File::Spec->catfile ( $full_base_dir, "storage", "ndb", "src", "kernel", "ndbd" )
+    }
+    $command .= "  --initial --nodaemon --connect-string=".$server->get_my_properties->get_my_connect_string;
+    $logger->debug (   "command: $command [redirect to: "
+                     . $server->get_std_out_err_stream
+                     . " ].\n" );
+    my $cur_dir= getcwd();
+    chdir $full_data_dir;
+    my $res= My::Nuts::Interfaces::Process::spawn_proc_async (
+                      $command,
+                      {
+                        STDOUT => $server->get_std_out_err_stream->get_handler,
+                        STDERR => $server->get_std_out_err_stream->get_handler
+                      }
+      );
+    chdir $cur_dir;
+    return $res;
+
+}
+
+sub _stop_mysql_server
 {
     my ( $self, $full_base_dir, $server ) = @_;
     my $server_id = $server->get_my_properties ()->get_my_server_id ();
@@ -560,6 +779,101 @@ sub _stop_server
          );
 }
 
+sub _cluster_shutdown
+{
+    my ( $self, $server ) = @_;
+    my $command = $self->_mgm_client($server) . " --execute=shutdown";
+    my $server_id= $server->get_my_properties->get_my_server_id();
+    $logger->debug ("stopping: $command \n");
+         spawn_proc_sync (
+                      $command,
+                      {
+                        STDOUT => $server->get_std_out_err_stream->get_handler,
+                        STDERR => $server->get_std_out_err_stream->get_handler
+                      }
+         );
+}
+
+sub _mgm_client
+{
+    my ( $self, $server ) = @_;
+    my ( $full_base_dir, $full_data_dir ) = $self->get_server_dirs ($server);
+    my $command = File::Spec->catfile ( $full_base_dir, "bin", "ndb_mgm" );
+    $command = verify_file ( $command, My::CONTINUE );
+    if ( not defined $command )
+    {
+        $command =
+          File::Spec->catfile ( $full_base_dir, "storage", "ndb", "src", "mgmclient", "ndb_mgm" );
+    }
+    my $type = $server->get_my_properties->get_my_server_type();
+    my $server_id= $server->get_my_properties->get_my_server_id();
+    my $server_ip= $server->get_ip_address();
+    my $connect_string= $server->get_my_properties->get_my_connect_string();
+    if ($type == My::NODE_NDB_MGMD)
+    {
+	$connect_string= $server_ip . ":" . $server->get_port();
+    }
+    $command .= " --connect-string=$connect_string";
+    return $command;
+}
+
+sub _get_cluster_node_status
+{
+    my ( $self, $server ) = @_;
+    my $command = $self->_mgm_client($server) . " --execute=SHOW";
+    my $server_id= $server->get_my_properties->get_my_server_id();
+    my $server_ip= $server->get_ip_address();
+    my $output= `$command`;
+    if ( $output =~ m/(id=$server_id[ |\t]+\@$server_ip)/i )
+    {
+	return My::NODE_CONNECTED;
+    }
+    return My::NODE_NOT_CONNECTED;
+}
+
+sub _group_cluster_dirs
+{
+    my ( $self, $server ) = @_;
+    my $ident = ident ($self);
+    my ( $full_base_dir, $full_data_dir ) = $self->get_server_dirs ($server);
+    my $server_id= $server->get_my_properties()->get_my_server_id();
+    my $server_type= lc $server->get_my_properties()->get_my_server_type();
+    switch ($server_type)
+    {
+	case (My::NODE_NDB_MGMD) { $server_type= "ndb_mgmd"}
+	case (My::NODE_NDBD) { $server_type= "ndbd"}
+	case (My::NODE_MYSQLD) { $server_type= "mysqld"}
+    }
+    my $cluster_id= $server->get_my_properties()->get_my_cluster_id();
+    my $cluster_dir= File::Spec->catfile( $directories{$ident}->get_data_dir_root, $server->get_test(), "cluster" );
+    if (! -e $cluster_dir)
+    {
+	$self->_mkdirs( $cluster_dir );
+    }
+    $cluster_dir= File::Spec->catfile( $cluster_dir, $cluster_id );    
+    if (! -e $cluster_dir)
+    {
+	$self->_mkdirs( $cluster_dir );
+    }
+    elsif (-e File::Spec->catfile($cluster_dir, $server_type . "_" . $server_id) && $server_type =~  /ndb_mgmd$/)
+    {
+	rmtree( $cluster_dir, 0, 1 );	
+	$self->_mkdirs( $cluster_dir );
+    }
+    my $node_symlink= File::Spec->catfile( $cluster_dir, $server_type . "_" . $server_id );
+    $logger->debug (
+    	"SYMLINKING: " . $full_data_dir . " TO " . $node_symlink );
+    if (!symlink( $full_data_dir, $node_symlink ))
+    {
+    	my $fh = new IO::File $node_symlink, "w";
+    	if (defined $fh)
+    	{
+    	    print $fh $full_data_dir;
+    	    $fh = undef;
+    	}	
+    }
+}
+
 sub _unzip
 {
     my ( $self, $build, $full_base_dir, $server ) = @_;

=== modified file 'lib/My/Nuts/Properties/MyProperties.pm'
--- a/lib/My/Nuts/Properties/MyProperties.pm	2009-10-26 18:36:47 +0000
+++ b/lib/My/Nuts/Properties/MyProperties.pm	2010-07-07 18:45:40 +0000
@@ -98,10 +98,32 @@ sub get_my_master_id
     return $instance_properties{$ident}{"my.master.id"};
 }
 
+sub get_my_server_type
+{
+    my $self = shift;
+    my $ident = ident ($self);
+    return $instance_properties{$ident}{"my.server.type"};
+}
+
+sub get_my_connect_string
+{
+    my $self = shift;
+    my $ident = ident ($self);
+    return $instance_properties{$ident}{"my.connect.string"};
+}
+
+sub get_my_cluster_id
+{
+    my $self = shift;
+    my $ident = ident ($self);
+    return $instance_properties{$ident}{"my.cluster.id"};
+}
+
+
 # overriden
 sub _get_internal_properties()
 {
-    return ( "my.server.id", "my.server.args" );
+    return ( "my.server.id", "my.server.args", "my.server.type", "my.connect.string",  "my.cluster.id");
 }
 
 sub set_default_properties

=== added file 'suites/samples/cluster.pm'
--- a/suites/samples/cluster.pm	1970-01-01 00:00:00 +0000
+++ b/suites/samples/cluster.pm	2010-07-07 18:45:40 +0000
@@ -0,0 +1,58 @@
+package samples::cluster;
+use Exporter;
+our @ISA = qw(Exporter My::Nuts::Library::Tests::SimpleTest);
+use My;
+use My::Nuts::Library::Requirement;
+use My::Nuts::Library::Kernel::Manager;
+use My::Nuts::Library::Kernel::Server;
+use My::Nuts::Library::Kernel::Result;
+use My::Nuts::Library::Kernel::ServerResult;
+use My::Nuts::Library::Kernel::Replication;
+use My::Nuts::Library::Tests::SimpleTest;
+use Test::More;
+
+sub fire
+{
+    my ($test) = @_;
+    # Start Cluster 
+    my $cluster = ok_cluster($test, { "mysqld_number" => 2 });
+    # Get the list of MySQL nodes
+    my ($server1, $server2) = get_cluster_nodes($cluster, My::NODE_MYSQLD);
+    # Set plan
+    plan tests => 7;
+    # Create DB, NDB table and put rows via first MySQL
+    ok_sql( $server1, "CREATE DATABASE IF NOT EXISTS test" );
+    ok_sql( $server1, "USE test" );
+    ok_sql( $server1, "DROP TABLE IF EXISTS ndb_t1" );
+    ok_sql( $server1, "CREATE TABLE ndb_t1 (a INT PRIMARY KEY, b VARCHAR(10)) ENGINE=NDBCLUSTER" );
+    ok_sql( $server1, "INSERT INTO ndb_t1 VALUES (1, 'test1'), (2, 'test2')" );
+    # Get rows from NDB table via second MySQL and check them
+    ok_sql( $server2, "USE test" );
+    ok_sql_result( 
+	$server2, 
+	"SELECT a,b FROM ndb_t1 ORDER BY a", 
+	    { 
+		1 => [1, "test1"], 
+		2 => [2, "test2"]
+	    } 
+    );	
+}
+1;
+__END__;
+
+=head1 NAME
+
+samples::cluster - sample of using MySQL cluster
+
+=head1 SYNOPSIS
+
+The test case starts the cluster with 2 SQL nodes (MySQL servers), creates NDB table, inserts a few rows via 1st server and checks them via 2nd server.
+
+=head1 AUTHOR
+
+Serge Kozlov S<< <Serge.Kozlov@stripped> >>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+


Attachment: [text/bzr-bundle] bzr/serge.kozlov@sun.com-20100707184540-ggfbvuf62s27km0u.bundle
Thread
bzr commit into nuts branch (Serge.Kozlov:372) WL#5333Serge Kozlov7 Jul