|
|
|
@ -18,6 +18,7 @@ package cmd |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"fmt" |
|
|
|
|
"net" |
|
|
|
|
"net/url" |
|
|
|
|
"sync" |
|
|
|
|
|
|
|
|
@ -49,21 +50,55 @@ func printOnceFn() printOnceFunc { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Prints custom message when healing is required for XL and Distributed XL backend.
|
|
|
|
|
func printHealMsg(firstEndpoint string, storageDisks []StorageAPI, fn printOnceFunc) { |
|
|
|
|
msg := getHealMsg(firstEndpoint, storageDisks) |
|
|
|
|
func printHealMsg(endpoints []*url.URL, storageDisks []StorageAPI, fn printOnceFunc) { |
|
|
|
|
msg := getHealMsg(endpoints, storageDisks) |
|
|
|
|
fn(msg) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Heal endpoint constructs the final endpoint URL for control heal command.
|
|
|
|
|
// Disk heal endpoint needs to be just a URL and no special paths.
|
|
|
|
|
// This function constructs the right endpoint under various conditions
|
|
|
|
|
// for single node XL, distributed XL and when minio server is bound
|
|
|
|
|
// to a specific ip:port.
|
|
|
|
|
func getHealEndpoint(tls bool, firstEndpoint *url.URL) (cEndpoint *url.URL) { |
|
|
|
|
scheme := "http" |
|
|
|
|
if tls { |
|
|
|
|
scheme = "https" |
|
|
|
|
} |
|
|
|
|
cEndpoint = &url.URL{ |
|
|
|
|
Scheme: scheme, |
|
|
|
|
} |
|
|
|
|
// Bind to `--address host:port` was specified.
|
|
|
|
|
if globalMinioHost != "" { |
|
|
|
|
cEndpoint.Host = net.JoinHostPort(globalMinioHost, globalMinioPort) |
|
|
|
|
return cEndpoint |
|
|
|
|
} |
|
|
|
|
// For distributed XL setup.
|
|
|
|
|
if firstEndpoint.Host != "" { |
|
|
|
|
cEndpoint.Host = firstEndpoint.Host |
|
|
|
|
return cEndpoint |
|
|
|
|
} |
|
|
|
|
// For single node XL setup, we need to find the endpoint.
|
|
|
|
|
cEndpoint.Host = globalMinioAddr |
|
|
|
|
// Fetch all the listening ips. For single node XL we
|
|
|
|
|
// just use the first host.
|
|
|
|
|
hosts, _, err := getListenIPs(cEndpoint.Host) |
|
|
|
|
if err == nil { |
|
|
|
|
cEndpoint.Host = net.JoinHostPort(hosts[0], globalMinioPort) |
|
|
|
|
} |
|
|
|
|
return cEndpoint |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Constructs a formatted heal message, when cluster is found to be in state where it requires healing.
|
|
|
|
|
// healing is optional, server continues to initialize object layer after printing this message.
|
|
|
|
|
// it is upto the end user to perform a heal if needed.
|
|
|
|
|
func getHealMsg(firstEndpoint string, storageDisks []StorageAPI) string { |
|
|
|
|
func getHealMsg(endpoints []*url.URL, storageDisks []StorageAPI) string { |
|
|
|
|
msg := fmt.Sprintln("\nData volume requires HEALING. Please run the following command:") |
|
|
|
|
msg += "MINIO_ACCESS_KEY=%s " |
|
|
|
|
msg += "MINIO_SECRET_KEY=%s " |
|
|
|
|
msg += "minio control heal %s" |
|
|
|
|
creds := serverConfig.GetCredential() |
|
|
|
|
msg = fmt.Sprintf(msg, creds.AccessKeyID, creds.SecretAccessKey, firstEndpoint) |
|
|
|
|
msg = fmt.Sprintf(msg, creds.AccessKeyID, creds.SecretAccessKey, getHealEndpoint(isSSL(), endpoints[0])) |
|
|
|
|
disksInfo, _, _ := getDisksInfo(storageDisks) |
|
|
|
|
for i, info := range disksInfo { |
|
|
|
|
if storageDisks[i] == nil { |
|
|
|
@ -72,7 +107,7 @@ func getHealMsg(firstEndpoint string, storageDisks []StorageAPI) string { |
|
|
|
|
msg += fmt.Sprintf( |
|
|
|
|
"\n[%s] %s - %s %s", |
|
|
|
|
int2Str(i+1, len(storageDisks)), |
|
|
|
|
storageDisks[i], |
|
|
|
|
endpoints[i], |
|
|
|
|
humanize.IBytes(uint64(info.Total)), |
|
|
|
|
func() string { |
|
|
|
|
if info.Total > 0 { |
|
|
|
|