aboutsummaryrefslogtreecommitdiff
path: root/weed/command/s3.go
diff options
context:
space:
mode:
Diffstat (limited to 'weed/command/s3.go')
-rw-r--r--weed/command/s3.go30
1 files changed, 20 insertions, 10 deletions
diff --git a/weed/command/s3.go b/weed/command/s3.go
index fa575b3db..995d15f8a 100644
--- a/weed/command/s3.go
+++ b/weed/command/s3.go
@@ -61,7 +61,7 @@ type S3Options struct {
func init() {
cmdS3.Run = runS3 // break init cycle
- s3StandaloneOptions.filer = cmdS3.Flag.String("filer", "localhost:8888", "filer server address")
+ s3StandaloneOptions.filer = cmdS3.Flag.String("filer", "localhost:8888", "comma-separated filer server addresses for high availability")
s3StandaloneOptions.bindIp = cmdS3.Flag.String("ip.bind", "", "ip address to bind to. Default to localhost.")
s3StandaloneOptions.port = cmdS3.Flag.Int("port", 8333, "s3 server http listen port")
s3StandaloneOptions.portHttps = cmdS3.Flag.Int("port.https", 0, "s3 server https listen port")
@@ -86,9 +86,12 @@ func init() {
}
var cmdS3 = &Command{
- UsageLine: "s3 [-port=8333] [-filer=<ip:port>] [-config=</path/to/config.json>]",
- Short: "start a s3 API compatible server that is backed by a filer",
- Long: `start a s3 API compatible server that is backed by a filer.
+ UsageLine: "s3 [-port=8333] [-filer=<ip:port>[,<ip:port>]...] [-config=</path/to/config.json>]",
+ Short: "start a s3 API compatible server that is backed by filer(s)",
+ Long: `start a s3 API compatible server that is backed by filer(s).
+
+ Multiple filer addresses can be specified for high availability, separated by commas.
+ The S3 server will automatically failover between filers if one becomes unavailable.
By default, you can use any access key and secret key to access the S3 APIs.
To enable credential based access, create a config.json file similar to this:
@@ -200,10 +203,11 @@ func (s3opt *S3Options) GetCertificateWithUpdate(*tls.ClientHelloInfo) (*tls.Cer
func (s3opt *S3Options) startS3Server() bool {
- filerAddress := pb.ServerAddress(*s3opt.filer)
+ filerAddresses := pb.ServerAddresses(*s3opt.filer).ToAddresses()
filerBucketsPath := "/buckets"
filerGroup := ""
+ var masterAddresses []pb.ServerAddress
grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")
@@ -212,22 +216,27 @@ func (s3opt *S3Options) startS3Server() bool {
var metricsIntervalSec int
for {
- err := pb.WithGrpcFilerClient(false, 0, filerAddress, grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
+ err := pb.WithOneOfGrpcFilerClients(false, filerAddresses, grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
resp, err := client.GetFilerConfiguration(context.Background(), &filer_pb.GetFilerConfigurationRequest{})
if err != nil {
- return fmt.Errorf("get filer %s configuration: %v", filerAddress, err)
+ return fmt.Errorf("get filer configuration: %v", err)
}
filerBucketsPath = resp.DirBuckets
filerGroup = resp.FilerGroup
+ // Get master addresses for filer discovery
+ masterAddresses = pb.ServerAddresses(strings.Join(resp.Masters, ",")).ToAddresses()
metricsAddress, metricsIntervalSec = resp.MetricsAddress, int(resp.MetricsIntervalSec)
glog.V(0).Infof("S3 read filer buckets dir: %s", filerBucketsPath)
+ if len(masterAddresses) > 0 {
+ glog.V(0).Infof("S3 read master addresses for discovery: %v", masterAddresses)
+ }
return nil
})
if err != nil {
- glog.V(0).Infof("wait to connect to filer %s grpc address %s", *s3opt.filer, filerAddress.ToGrpcAddress())
+ glog.V(0).Infof("wait to connect to filers %v grpc address", filerAddresses)
time.Sleep(time.Second)
} else {
- glog.V(0).Infof("connected to filer %s grpc address %s", *s3opt.filer, filerAddress.ToGrpcAddress())
+ glog.V(0).Infof("connected to filers %v", filerAddresses)
break
}
}
@@ -252,7 +261,8 @@ func (s3opt *S3Options) startS3Server() bool {
}
s3ApiServer, s3ApiServer_err = s3api.NewS3ApiServer(router, &s3api.S3ApiServerOption{
- Filer: filerAddress,
+ Filers: filerAddresses,
+ Masters: masterAddresses,
Port: *s3opt.port,
Config: *s3opt.config,
DomainName: *s3opt.domainName,