Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GetFullStatus RPC to vtctld #10905

Merged
merged 6 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions go/cmd/vtctldclient/command/tablets.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ Note: hook names may not contain slash (/) characters.
Args: cobra.MinimumNArgs(2),
RunE: commandExecuteHook,
}
// GetFullStatus makes a FullStatus gRPC call to a vttablet.
GetFullStatus = &cobra.Command{
Use: "GetFullStatus <alias>",
Short: "Outputs a JSON structure that contains full status of MySQL including the replication information, semi-sync information, GTID information among others.",
DisableFlagsInUseLine: true,
Args: cobra.ExactArgs(1),
RunE: commandGetFullStatus,
}
// GetPermissions makes a GetPermissions gRPC call to a vtctld.
GetPermissions = &cobra.Command{
Use: "GetPermissions <tablet_alias>",
Expand Down Expand Up @@ -299,6 +307,30 @@ func commandExecuteHook(cmd *cobra.Command, args []string) error {
return nil
}

func commandGetFullStatus(cmd *cobra.Command, args []string) error {
aliasStr := cmd.Flags().Arg(0)
alias, err := topoproto.ParseTabletAlias(aliasStr)
if err != nil {
return err
}

cli.FinishedParsing(cmd)

resp, err := client.GetFullStatus(commandCtx, &vtctldatapb.GetFullStatusRequest{TabletAlias: alias})
if err != nil {
return err
}

data, err := cli.MarshalJSON(resp.Status)
if err != nil {
return err
}

fmt.Printf("%s\n", data)

return nil
}

func commandGetPermissions(cmd *cobra.Command, args []string) error {
alias, err := topoproto.ParseTabletAlias(cmd.Flags().Arg(0))
if err != nil {
Expand Down Expand Up @@ -596,6 +628,7 @@ func init() {
Root.AddCommand(DeleteTablets)

Root.AddCommand(ExecuteHook)
Root.AddCommand(GetFullStatus)
Root.AddCommand(GetPermissions)
Root.AddCommand(GetTablet)

Expand Down
5 changes: 3 additions & 2 deletions go/test/endtoend/cluster/cluster_process.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,9 @@ type LocalProcessCluster struct {
VtctlMajorVersion int

// standalone executable
VtctlclientProcess VtctlClientProcess
VtctlProcess VtctlProcess
VtctlclientProcess VtctlClientProcess
VtctldClientProcess VtctldClientProcess
VtctlProcess VtctlProcess

// background executable processes
TopoProcess TopoProcess
Expand Down
103 changes: 103 additions & 0 deletions go/test/endtoend/reparent/newfeaturetest/reparent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ limitations under the License.
package newfeaturetest

import (
"strconv"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"google.golang.org/protobuf/encoding/protojson"

"vitess.io/vitess/go/mysql"
"vitess.io/vitess/go/test/endtoend/cluster"
"vitess.io/vitess/go/test/endtoend/reparent/utils"
replicationdatapb "vitess.io/vitess/go/vt/proto/replicationdata"
)

// TestCrossCellDurability tests 2 things -
Expand Down Expand Up @@ -66,3 +72,100 @@ func TestCrossCellDurability(t *testing.T) {
utils.CheckSemiSyncSetupCorrectly(t, newReplica, "ON")
}
}

// TestFullStatus tests that the RPC FullStatus works as intended.
func TestFullStatus(t *testing.T) {
defer cluster.PanicHandler(t)
clusterInstance := utils.SetupReparentCluster(t, "semi_sync")
defer utils.TeardownCluster(clusterInstance)
tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets
utils.ConfirmReplication(t, tablets[0], []*cluster.Vttablet{tablets[1], tablets[2], tablets[3]})

// Check that full status gives the correct result for a primary tablet
primaryStatusString, err := clusterInstance.VtctldClientProcess.ExecuteCommandWithOutput("GetFullStatus", tablets[0].Alias)
require.NoError(t, err)
primaryStatus := &replicationdatapb.FullStatus{}
err = protojson.Unmarshal([]byte(primaryStatusString), primaryStatus)
require.NoError(t, err)
assert.NotEmpty(t, primaryStatus.ServerUuid)
assert.NotEmpty(t, primaryStatus.ServerId)
// For a primary tablet there is no replication status
assert.Nil(t, primaryStatus.ReplicationStatus)
assert.Contains(t, primaryStatus.PrimaryStatus.String(), "vt-0000000101-bin")
assert.Equal(t, primaryStatus.GtidPurged, "MySQL56/")
assert.False(t, primaryStatus.ReadOnly)
assert.True(t, primaryStatus.SemiSyncPrimaryEnabled)
assert.True(t, primaryStatus.SemiSyncReplicaEnabled)
assert.True(t, primaryStatus.SemiSyncPrimaryStatus)
assert.False(t, primaryStatus.SemiSyncReplicaStatus)
assert.EqualValues(t, 3, primaryStatus.SemiSyncPrimaryClients)
assert.EqualValues(t, 1000000000000000000, primaryStatus.SemiSyncPrimaryTimeout)
assert.EqualValues(t, 1, primaryStatus.SemiSyncWaitForReplicaCount)
assert.Equal(t, "ROW", primaryStatus.BinlogFormat)
assert.Equal(t, "FULL", primaryStatus.BinlogRowImage)
assert.Equal(t, "ON", primaryStatus.GtidMode)
assert.True(t, primaryStatus.LogReplicaUpdates)
assert.True(t, primaryStatus.LogBinEnabled)
assert.Regexp(t, `[58]\.[07].*`, primaryStatus.Version)
assert.NotEmpty(t, primaryStatus.VersionComment)

// Check that full status gives the correct result for a replica tablet
replicaStatusString, err := clusterInstance.VtctldClientProcess.ExecuteCommandWithOutput("GetFullStatus", tablets[1].Alias)
require.NoError(t, err)
replicaStatus := &replicationdatapb.FullStatus{}
err = protojson.Unmarshal([]byte(replicaStatusString), replicaStatus)
require.NoError(t, err)
assert.NotEmpty(t, replicaStatus.ServerUuid)
assert.NotEmpty(t, replicaStatus.ServerId)
assert.Contains(t, replicaStatus.ReplicationStatus.Position, "MySQL56/"+replicaStatus.ReplicationStatus.SourceUuid)
assert.EqualValues(t, mysql.ReplicationStateRunning, replicaStatus.ReplicationStatus.IoState)
assert.EqualValues(t, mysql.ReplicationStateRunning, replicaStatus.ReplicationStatus.SqlState)
assert.Equal(t, fileNameFromPosition(replicaStatus.ReplicationStatus.FilePosition), fileNameFromPosition(primaryStatus.PrimaryStatus.FilePosition))
assert.LessOrEqual(t, rowNumberFromPosition(replicaStatus.ReplicationStatus.FilePosition), rowNumberFromPosition(primaryStatus.PrimaryStatus.FilePosition))
assert.Equal(t, replicaStatus.ReplicationStatus.RelayLogSourceBinlogEquivalentPosition, primaryStatus.PrimaryStatus.FilePosition)
assert.Contains(t, replicaStatus.ReplicationStatus.RelayLogFilePosition, "vt-0000000102-relay")
assert.Equal(t, replicaStatus.ReplicationStatus.Position, primaryStatus.PrimaryStatus.Position)
assert.Equal(t, replicaStatus.ReplicationStatus.RelayLogPosition, primaryStatus.PrimaryStatus.Position)
assert.Empty(t, replicaStatus.ReplicationStatus.LastIoError)
assert.Empty(t, replicaStatus.ReplicationStatus.LastSqlError)
assert.Equal(t, replicaStatus.ReplicationStatus.SourceUuid, primaryStatus.ServerUuid)
assert.LessOrEqual(t, int(replicaStatus.ReplicationStatus.ReplicationLagSeconds), 1)
assert.False(t, replicaStatus.ReplicationStatus.ReplicationLagUnknown)
assert.EqualValues(t, 0, replicaStatus.ReplicationStatus.SqlDelay)
assert.False(t, replicaStatus.ReplicationStatus.SslAllowed)
assert.False(t, replicaStatus.ReplicationStatus.HasReplicationFilters)
assert.False(t, replicaStatus.ReplicationStatus.UsingGtid)
assert.True(t, replicaStatus.ReplicationStatus.AutoPosition)
assert.Equal(t, replicaStatus.ReplicationStatus.SourceHost, utils.Hostname)
assert.EqualValues(t, replicaStatus.ReplicationStatus.SourcePort, tablets[0].MySQLPort)
assert.Equal(t, replicaStatus.ReplicationStatus.SourceUser, "vt_repl")
assert.Contains(t, replicaStatus.PrimaryStatus.String(), "vt-0000000102-bin")
assert.Equal(t, replicaStatus.GtidPurged, "MySQL56/")
assert.True(t, replicaStatus.ReadOnly)
assert.False(t, replicaStatus.SemiSyncPrimaryEnabled)
assert.True(t, replicaStatus.SemiSyncReplicaEnabled)
assert.False(t, replicaStatus.SemiSyncPrimaryStatus)
assert.True(t, replicaStatus.SemiSyncReplicaStatus)
assert.EqualValues(t, 0, replicaStatus.SemiSyncPrimaryClients)
assert.EqualValues(t, 1000000000000000000, replicaStatus.SemiSyncPrimaryTimeout)
assert.EqualValues(t, 1, replicaStatus.SemiSyncWaitForReplicaCount)
assert.Equal(t, "ROW", replicaStatus.BinlogFormat)
assert.Equal(t, "FULL", replicaStatus.BinlogRowImage)
assert.Equal(t, "ON", replicaStatus.GtidMode)
assert.True(t, replicaStatus.LogReplicaUpdates)
assert.True(t, replicaStatus.LogBinEnabled)
assert.Regexp(t, `[58]\.[07].*`, replicaStatus.Version)
assert.NotEmpty(t, replicaStatus.VersionComment)
}

// fileNameFromPosition gets the file name from the position
func fileNameFromPosition(pos string) string {
return pos[0 : len(pos)-4]
}

// rowNumberFromPosition gets the row number from the position
func rowNumberFromPosition(pos string) int {
rowNumStr := pos[len(pos)-4:]
rowNum, _ := strconv.Atoi(rowNumStr)
return rowNum
}
93 changes: 0 additions & 93 deletions go/test/endtoend/reparent/plannedreparent/reparent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@ package plannedreparent
import (
"context"
"fmt"
"strconv"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"vitess.io/vitess/go/mysql"
"vitess.io/vitess/go/test/endtoend/cluster"
"vitess.io/vitess/go/test/endtoend/reparent/utils"
"vitess.io/vitess/go/vt/log"
Expand Down Expand Up @@ -439,94 +437,3 @@ func TestReplicationStatus(t *testing.T) {
assert.NotEmpty(t, replicationStatus.Position)
assert.NotEmpty(t, replicationStatus.RelayLogPosition)
}

// TestFullStatus tests that the RPC FullStatus works as intended.
func TestFullStatus(t *testing.T) {
defer cluster.PanicHandler(t)
clusterInstance := utils.SetupReparentCluster(t, "semi_sync")
defer utils.TeardownCluster(clusterInstance)
tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets
utils.ConfirmReplication(t, tablets[0], []*cluster.Vttablet{tablets[1], tablets[2], tablets[3]})

// Check that full status gives the correct result for a primary tablet
primaryStatus, err := utils.TmcFullStatus(context.Background(), tablets[0])
require.NoError(t, err)
assert.NotEmpty(t, primaryStatus.ServerUuid)
assert.NotEmpty(t, primaryStatus.ServerId)
// For a primary tablet there is no replication status
assert.Nil(t, primaryStatus.ReplicationStatus)
assert.Contains(t, primaryStatus.PrimaryStatus.String(), "vt-0000000101-bin")
assert.Equal(t, primaryStatus.GtidPurged, "MySQL56/")
assert.False(t, primaryStatus.ReadOnly)
assert.True(t, primaryStatus.SemiSyncPrimaryEnabled)
assert.True(t, primaryStatus.SemiSyncReplicaEnabled)
assert.True(t, primaryStatus.SemiSyncPrimaryStatus)
assert.False(t, primaryStatus.SemiSyncReplicaStatus)
assert.EqualValues(t, 3, primaryStatus.SemiSyncPrimaryClients)
assert.EqualValues(t, 1000000000000000000, primaryStatus.SemiSyncPrimaryTimeout)
assert.EqualValues(t, 1, primaryStatus.SemiSyncWaitForReplicaCount)
assert.Equal(t, "ROW", primaryStatus.BinlogFormat)
assert.Equal(t, "FULL", primaryStatus.BinlogRowImage)
assert.Equal(t, "ON", primaryStatus.GtidMode)
assert.True(t, primaryStatus.LogReplicaUpdates)
assert.True(t, primaryStatus.LogBinEnabled)
assert.Regexp(t, `[58]\.[07].*`, primaryStatus.Version)
assert.NotEmpty(t, primaryStatus.VersionComment)

// Check that full status gives the correct result for a replica tablet
replicaStatus, err := utils.TmcFullStatus(context.Background(), tablets[1])
require.NoError(t, err)
assert.NotEmpty(t, replicaStatus.ServerUuid)
assert.NotEmpty(t, replicaStatus.ServerId)
assert.Contains(t, replicaStatus.ReplicationStatus.Position, "MySQL56/"+replicaStatus.ReplicationStatus.SourceUuid)
assert.EqualValues(t, mysql.ReplicationStateRunning, replicaStatus.ReplicationStatus.IoState)
assert.EqualValues(t, mysql.ReplicationStateRunning, replicaStatus.ReplicationStatus.SqlState)
assert.Equal(t, fileNameFromPosition(replicaStatus.ReplicationStatus.FilePosition), fileNameFromPosition(primaryStatus.PrimaryStatus.FilePosition))
assert.LessOrEqual(t, rowNumberFromPosition(replicaStatus.ReplicationStatus.FilePosition), rowNumberFromPosition(primaryStatus.PrimaryStatus.FilePosition))
assert.Equal(t, replicaStatus.ReplicationStatus.RelayLogSourceBinlogEquivalentPosition, primaryStatus.PrimaryStatus.FilePosition)
assert.Contains(t, replicaStatus.ReplicationStatus.RelayLogFilePosition, "vt-0000000102-relay")
assert.Equal(t, replicaStatus.ReplicationStatus.Position, primaryStatus.PrimaryStatus.Position)
assert.Equal(t, replicaStatus.ReplicationStatus.RelayLogPosition, primaryStatus.PrimaryStatus.Position)
assert.Empty(t, replicaStatus.ReplicationStatus.LastIoError)
assert.Empty(t, replicaStatus.ReplicationStatus.LastSqlError)
assert.Equal(t, replicaStatus.ReplicationStatus.SourceUuid, primaryStatus.ServerUuid)
assert.LessOrEqual(t, int(replicaStatus.ReplicationStatus.ReplicationLagSeconds), 1)
assert.False(t, replicaStatus.ReplicationStatus.ReplicationLagUnknown)
assert.EqualValues(t, 0, replicaStatus.ReplicationStatus.SqlDelay)
assert.False(t, replicaStatus.ReplicationStatus.SslAllowed)
assert.False(t, replicaStatus.ReplicationStatus.HasReplicationFilters)
assert.False(t, replicaStatus.ReplicationStatus.UsingGtid)
assert.True(t, replicaStatus.ReplicationStatus.AutoPosition)
assert.Equal(t, replicaStatus.ReplicationStatus.SourceHost, utils.Hostname)
assert.EqualValues(t, replicaStatus.ReplicationStatus.SourcePort, tablets[0].MySQLPort)
assert.Equal(t, replicaStatus.ReplicationStatus.SourceUser, "vt_repl")
assert.Contains(t, replicaStatus.PrimaryStatus.String(), "vt-0000000102-bin")
assert.Equal(t, replicaStatus.GtidPurged, "MySQL56/")
assert.True(t, replicaStatus.ReadOnly)
assert.False(t, replicaStatus.SemiSyncPrimaryEnabled)
assert.True(t, replicaStatus.SemiSyncReplicaEnabled)
assert.False(t, replicaStatus.SemiSyncPrimaryStatus)
assert.True(t, replicaStatus.SemiSyncReplicaStatus)
assert.EqualValues(t, 0, replicaStatus.SemiSyncPrimaryClients)
assert.EqualValues(t, 1000000000000000000, replicaStatus.SemiSyncPrimaryTimeout)
assert.EqualValues(t, 1, replicaStatus.SemiSyncWaitForReplicaCount)
assert.Equal(t, "ROW", replicaStatus.BinlogFormat)
assert.Equal(t, "FULL", replicaStatus.BinlogRowImage)
assert.Equal(t, "ON", replicaStatus.GtidMode)
assert.True(t, replicaStatus.LogReplicaUpdates)
assert.True(t, replicaStatus.LogBinEnabled)
assert.Regexp(t, `[58]\.[07].*`, replicaStatus.Version)
assert.NotEmpty(t, replicaStatus.VersionComment)
}

// fileNameFromPosition gets the file name from the position
func fileNameFromPosition(pos string) string {
return pos[0 : len(pos)-4]
}

// rowNumberFromPosition gets the row number from the position
func rowNumberFromPosition(pos string) int {
rowNumStr := pos[len(pos)-4:]
rowNum, _ := strconv.Atoi(rowNumStr)
return rowNum
}
21 changes: 2 additions & 19 deletions go/test/endtoend/reparent/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ import (
"vitess.io/vitess/go/sqltypes"
"vitess.io/vitess/go/test/endtoend/cluster"
"vitess.io/vitess/go/vt/log"
tmc "vitess.io/vitess/go/vt/vttablet/grpctmclient"

replicationdatapb "vitess.io/vitess/go/vt/proto/replicationdata"
topodatapb "vitess.io/vitess/go/vt/proto/topodata"
)
Expand Down Expand Up @@ -157,8 +155,8 @@ func setupCluster(ctx context.Context, t *testing.T, shardName string, cells []s
}
}
if clusterInstance.VtctlMajorVersion >= 14 {
vtctldClientProcess := cluster.VtctldClientProcessInstance("localhost", clusterInstance.VtctldProcess.GrpcPort, clusterInstance.TmpDirectory)
out, err := vtctldClientProcess.ExecuteCommandWithOutput("SetKeyspaceDurabilityPolicy", KeyspaceName, fmt.Sprintf("--durability-policy=%s", durability))
clusterInstance.VtctldClientProcess = *cluster.VtctldClientProcessInstance("localhost", clusterInstance.VtctldProcess.GrpcPort, clusterInstance.TmpDirectory)
out, err := clusterInstance.VtctldClientProcess.ExecuteCommandWithOutput("SetKeyspaceDurabilityPolicy", KeyspaceName, fmt.Sprintf("--durability-policy=%s", durability))
require.NoError(t, err, out)
}

Expand Down Expand Up @@ -736,18 +734,3 @@ func ReplicationThreadsStatus(t *testing.T, status *replicationdatapb.Status, vt
}
return ioThread, sqlThread
}

// TmcFullStatus retuns the result of the TabletManagerClient RPC FullStatus
func TmcFullStatus(ctx context.Context, tablet *cluster.Vttablet) (*replicationdatapb.FullStatus, error) {
// create tablet manager client
tmClient := tmc.NewClient()

vttablet := getTablet(tablet.GrpcPort)
return tmClient.FullStatus(ctx, vttablet)
}

func getTablet(tabletGrpcPort int) *topodatapb.Tablet {
portMap := make(map[string]int32)
portMap["grpc"] = int32(tabletGrpcPort)
return &topodatapb.Tablet{Hostname: Hostname, PortMap: portMap}
}
Loading