@@ -19,8 +19,8 @@ package sidecar
1919import (
2020 "fmt"
2121 "os"
22+ "os/exec"
2223 "strconv"
23- "text/template"
2424
2525 "github.com/blang/semver"
2626 "github.com/go-ini/ini"
@@ -543,30 +543,12 @@ curl -X PATCH -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/ser
543543 return utils .StringToBytes (str )
544544}
545545
546- // build S3 restore shell script
547- func (cfg * Config ) buildS3Restore (path string ) error {
548- if len (cfg .XRestoreFrom ) == 0 {
549- return fmt .Errorf ("do not have restore from" )
550- }
551- if len (cfg .XCloudS3EndPoint ) == 0 ||
552- len (cfg .XCloudS3AccessKey ) == 0 ||
553- len (cfg .XCloudS3SecretKey ) == 0 ||
554- len (cfg .XCloudS3Bucket ) == 0 {
555- return fmt .Errorf ("do not have S3 information" )
556- }
557- f , err := os .Create (path )
558- if err != nil {
559- return fmt .Errorf ("create restore.sh fail : %s" , err )
560- }
561- defer func () {
562- f .Close ()
563- }()
564-
565- restoresh := `#!/bin/sh
546+ /* The function is equivalent to the following shell script template:
547+ #!/bin/sh
566548if [ ! -d {{.DataDir}} ] ; then
567549 echo "is not exist the var lib mysql"
568- mkdir {{.DataDir}}
569- chown -R mysql.mysql {{.DataDir}}
550+ mkdir {{.DataDir}}
551+ chown -R mysql.mysql {{.DataDir}}
570552fi
571553mkdir /root/backup
572554xbcloud get --storage=S3 \
@@ -583,24 +565,93 @@ xtrabackup --defaults-file={{.MyCnfMountPath}} --use-memory=3072M --prepare --ta
583565chown -R mysql.mysql /root/backup
584566xtrabackup --defaults-file={{.MyCnfMountPath}} --datadir={{.DataDir}} --copy-back --target-dir=/root/backup
585567chown -R mysql.mysql {{.DataDir}}
586- rm -rf /root/backup
587- `
588- template_restore := template .New ("restore.sh" )
589- template_restore , err = template_restore .Parse (restoresh )
590- if err != nil {
591- return err
592- }
593- err2 := template_restore .Execute (f , struct {
594- Config
595- DataDir string
596- MyCnfMountPath string
597- }{
598- * cfg ,
599- utils .DataVolumeMountPath ,
600- utils .ConfVolumeMountPath + "/my.cnf" ,
601- })
602- if err2 != nil {
603- return err2
568+ rm -rf /root/backup
569+ */
570+ func (cfg * Config ) executeS3Restore (path string ) error {
571+ if len (cfg .XRestoreFrom ) == 0 {
572+ return fmt .Errorf ("do not have restore from" )
573+ }
574+ if len (cfg .XCloudS3EndPoint ) == 0 ||
575+ len (cfg .XCloudS3AccessKey ) == 0 ||
576+ len (cfg .XCloudS3SecretKey ) == 0 ||
577+ len (cfg .XCloudS3Bucket ) == 0 {
578+ return fmt .Errorf ("do not have S3 information" )
579+ }
580+ // Check has directory, and create it.
581+ if _ , err := os .Stat (utils .DataVolumeMountPath ); os .IsNotExist (err ) {
582+ if err := os .MkdirAll (utils .DataVolumeMountPath , 0755 ); err != nil {
583+ return fmt .Errorf ("failed to create data directory : %s" , err )
584+ }
585+ }
586+ // mkdir /root/backup.
587+ if err := os .MkdirAll ("/root/backup" , 0755 ); err != nil {
588+ return fmt .Errorf ("failed to create backup directory : %s" , err )
589+ }
590+ // Execute xbcloud get.
591+ args := []string {
592+ "get" ,
593+ "--storage=S3" ,
594+ "--s3-endpoint=" + cfg .XCloudS3EndPoint ,
595+ "--s3-access-key=" + cfg .XCloudS3AccessKey ,
596+ "--s3-secret-key=" + cfg .XCloudS3SecretKey ,
597+ "--s3-bucket=" + cfg .XCloudS3Bucket ,
598+ "--parallel=10" ,
599+ cfg .XRestoreFrom ,
600+ "--insecure" ,
601+ }
602+ xcloud := exec .Command (xcloudCommand , args ... ) //nolint
603+ xbstream := exec .Command ("xbstream" , "-xv" , "-C" , "/root/backup" ) //nolint
604+ var err error
605+ if xbstream .Stdin , err = xcloud .StdoutPipe (); err != nil {
606+ return fmt .Errorf ("failed to xbstream and xcloud piped" )
607+ }
608+ xbstream .Stderr = os .Stderr
609+ xcloud .Stderr = os .Stderr
610+ if err := xcloud .Start (); err != nil {
611+ return fmt .Errorf ("failed to xcloud start : %s" , err )
612+ }
613+ if err := xbstream .Start (); err != nil {
614+ return fmt .Errorf ("failed to xbstream start : %s" , err )
615+ }
616+ // Make error channels.
617+ errCh := make (chan error , 2 )
618+ go func () {
619+ errCh <- xcloud .Wait ()
620+ }()
621+ go func () {
622+ errCh <- xbstream .Wait ()
623+ }()
624+ // Wait for error.
625+ for i := 0 ; i < 2 ; i ++ {
626+ if err = <- errCh ; err != nil {
627+ return err
628+ }
629+ }
630+ // Xtrabackup prepare and apply-log-only.
631+ cmd := exec .Command (xtrabackupCommand , "--defaults-file=" + utils .ConfVolumeMountPath + "/my.cnf" , "--prepare" , "--apply-log-only" , "--target-dir=/root/backup" )
632+ cmd .Stderr = os .Stderr
633+ if err := cmd .Run (); err != nil {
634+ return fmt .Errorf ("failed to xtrabackup prepare and apply-log-only : %s" , err )
635+ }
636+ // Xtrabackup prepare.
637+ cmd = exec .Command (xtrabackupCommand , "--defaults-file=" + utils .ConfVolumeMountPath + "/my.cnf" , "--prepare" , "--target-dir=/root/backup" )
638+ cmd .Stderr = os .Stderr
639+ if err := cmd .Run (); err != nil {
640+ return fmt .Errorf ("failed to xtrabackup prepare : %s" , err )
641+ }
642+ // Xtrabackup copy-back to /var/lib/mysql.
643+ cmd = exec .Command (xtrabackupCommand , "--defaults-file=" + utils .ConfVolumeMountPath + "/my.cnf" , "--datadir=" + utils .DataVolumeMountPath , "--copy-back" , "--copy-back" , "--target-dir=/root/backup" )
644+ cmd .Stderr = os .Stderr
645+ if err := cmd .Run (); err != nil {
646+ return fmt .Errorf ("failed to xtrabackup copy-back : %s" , err )
647+ }
648+ // Execute chown -R mysql.mysql /var/lib/mysql.
649+ if err := exec .Command ("chown" , "-R" , "mysql.mysql" , utils .DataVolumeMountPath ).Run (); err != nil {
650+ return fmt .Errorf ("failed to chown mysql.mysql %s : %s" , utils .DataVolumeMountPath , err )
651+ }
652+ // Remove /root/backup.
653+ if err := os .RemoveAll ("/root/backup" ); err != nil {
654+ return fmt .Errorf ("failed to remove backup directory : %s" , err )
604655 }
605656 return nil
606657}
0 commit comments