diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index d4db5c2a3..bded0edcd 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -159,7 +159,7 @@ func (a adminAPIHandlers) ServerUpdateV2Handler(w http.ResponseWriter, r *http.R peerResults[nerr.Host.String()] = madmin.ServerPeerUpdateStatus{ Host: nerr.Host.String(), CurrentVersion: Version, - UpdatedVersion: lrTime.Format(minioReleaseTagTimeLayout), + UpdatedVersion: lrTime.Format(MinioReleaseTagTimeLayout), } } } @@ -176,7 +176,7 @@ func (a adminAPIHandlers) ServerUpdateV2Handler(w http.ResponseWriter, r *http.R peerResults[local] = madmin.ServerPeerUpdateStatus{ Host: local, CurrentVersion: Version, - UpdatedVersion: lrTime.Format(minioReleaseTagTimeLayout), + UpdatedVersion: lrTime.Format(MinioReleaseTagTimeLayout), } } } else { @@ -212,7 +212,7 @@ func (a adminAPIHandlers) ServerUpdateV2Handler(w http.ResponseWriter, r *http.R Host: nerr.Host.String(), Err: nerr.Err.Error(), CurrentVersion: Version, - UpdatedVersion: lrTime.Format(minioReleaseTagTimeLayout), + UpdatedVersion: lrTime.Format(MinioReleaseTagTimeLayout), } } } @@ -404,7 +404,7 @@ func (a adminAPIHandlers) ServerUpdateHandler(w http.ResponseWriter, r *http.Req updateStatus := madmin.ServerUpdateStatus{ CurrentVersion: Version, - UpdatedVersion: lrTime.Format(minioReleaseTagTimeLayout), + UpdatedVersion: lrTime.Format(MinioReleaseTagTimeLayout), } // Marshal API response diff --git a/cmd/api-headers.go b/cmd/api-headers.go index fa17cfad6..3936227a3 100644 --- a/cmd/api-headers.go +++ b/cmd/api-headers.go @@ -50,7 +50,7 @@ func setEventStreamHeaders(w http.ResponseWriter) { // Write http common headers func setCommonHeaders(w http.ResponseWriter) { // Set the "Server" http header. - w.Header().Set(xhttp.ServerInfo, "MinIO") + w.Header().Set(xhttp.ServerInfo, MinioStoreName) // Set `x-amz-bucket-region` only if region is set on the server // by default minio uses an empty region. diff --git a/cmd/build-constants.go b/cmd/build-constants.go index 221bcf134..8777fba05 100644 --- a/cmd/build-constants.go +++ b/cmd/build-constants.go @@ -17,6 +17,8 @@ package cmd +import "runtime" + // DO NOT EDIT THIS FILE DIRECTLY. These are build-time constants // set through ‘buildscripts/gen-ldflags.go’. var ( @@ -40,4 +42,25 @@ var ( // CopyrightYear - dynamic value of the copyright end year CopyrightYear = "0000" + + // MinioReleaseTagTimeLayout - release tag time layout. + MinioReleaseTagTimeLayout = "2006-01-02T15-04-05Z" + + // MinioOSARCH - OS and ARCH. + minioOSARCH = runtime.GOOS + "-" + runtime.GOARCH + + // MinioReleaseURL - release URL. + MinioReleaseURL = "https://dl.min.io/server/minio/release/" + minioOSARCH + SlashSeparator + + // MinioStoreName - MinIO store name. + MinioStoreName = "MinIO" + + // MinioUAName - MinIO user agent name. + MinioUAName = "MinIO" + + // MinioBannerName - MinIO banner name for startup message. + MinioBannerName = "MinIO Object Storage Server" + + // MinioLicense - MinIO server license. + MinioLicense = "GNU AGPLv3 " ) diff --git a/cmd/ftp-server.go b/cmd/ftp-server.go index debf8d431..179ce64c4 100644 --- a/cmd/ftp-server.go +++ b/cmd/ftp-server.go @@ -136,7 +136,7 @@ func startFTPServer(args []string) { ftpServer, err := ftp.NewServer(&ftp.Options{ Name: name, - WelcomeMessage: fmt.Sprintf("Welcome to MinIO FTP Server Version='%s' License='GNU AGPLv3'", Version), + WelcomeMessage: fmt.Sprintf("Welcome to '%s' FTP Server Version='%s' License='%s'", MinioStoreName, MinioLicense, Version), Driver: NewFTPDriver(), Port: port, Perm: ftp.NewSimplePerm("nobody", "nobody"), diff --git a/cmd/main.go b/cmd/main.go index 4d2e1d633..06f24ff39 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -25,7 +25,9 @@ import ( "runtime" "runtime/debug" "sort" + "strconv" "strings" + "time" "github.com/minio/cli" "github.com/minio/minio/internal/color" @@ -169,8 +171,9 @@ func newApp(name string) *cli.App { } func startupBanner(banner io.Writer) { + CopyrightYear = strconv.Itoa(time.Now().Year()) fmt.Fprintln(banner, color.Blue("Copyright:")+color.Bold(" 2015-%s MinIO, Inc.", CopyrightYear)) - fmt.Fprintln(banner, color.Blue("License:")+color.Bold(" GNU AGPLv3 ")) + fmt.Fprintln(banner, color.Blue("License:")+color.Bold(" "+MinioLicense)) fmt.Fprintln(banner, color.Blue("Version:")+color.Bold(" %s (%s %s/%s)", ReleaseTag, runtime.Version(), runtime.GOOS, runtime.GOARCH)) } diff --git a/cmd/server-main.go b/cmd/server-main.go index feaf084c9..b31eec738 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -652,6 +652,8 @@ func getServerListenAddrs() []string { // serverMain handler called for 'minio server' command. func serverMain(ctx *cli.Context) { + var warnings []string + signal.Notify(globalOSSignalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT) go handleSignals() @@ -733,13 +735,13 @@ func serverMain(ctx *cli.Context) { // Verify kernel release and version. if oldLinux() { - logger.Info(color.RedBold("WARNING: Detected Linux kernel version older than 4.0.0 release, there are some known potential performance problems with this kernel version. MinIO recommends a minimum of 4.x.x linux kernel version for best performance")) + warnings = append(warnings, color.RedBold("WARNING: Detected Linux kernel version older than 4.0.0 release, there are some known potential performance problems with this kernel version. MinIO recommends a minimum of 4.x.x linux kernel version for best performance")) } maxProcs := runtime.GOMAXPROCS(0) cpuProcs := runtime.NumCPU() if maxProcs < cpuProcs { - logger.Info(color.RedBoldf("WARNING: Detected GOMAXPROCS(%d) < NumCPU(%d), please make sure to provide all PROCS to MinIO for optimal performance", maxProcs, cpuProcs)) + warnings = append(warnings, color.RedBoldf("WARNING: Detected GOMAXPROCS(%d) < NumCPU(%d), please make sure to provide all PROCS to MinIO for optimal performance", maxProcs, cpuProcs)) } var getCert certs.GetCertificateFunc @@ -840,14 +842,13 @@ func serverMain(ctx *cli.Context) { } if !globalServerCtxt.StrictS3Compat { - logger.Info(color.RedBold("WARNING: Strict AWS S3 compatible incoming PUT, POST content payload validation is turned off, caution is advised do not use in production")) + warnings = append(warnings, color.RedBold("WARNING: Strict AWS S3 compatible incoming PUT, POST content payload validation is turned off, caution is advised do not use in production")) } }) - if globalActiveCred.Equal(auth.DefaultCredentials) { msg := fmt.Sprintf("WARNING: Detected default credentials '%s', we recommend that you change these values with 'MINIO_ROOT_USER' and 'MINIO_ROOT_PASSWORD' environment variables", globalActiveCred) - logger.Info(color.RedBold(msg)) + warnings = append(warnings, color.RedBold(msg)) } // Initialize users credentials and policies in background right after config has initialized. @@ -893,7 +894,7 @@ func serverMain(ctx *cli.Context) { if !globalDisableFreezeOnBoot { defer bootstrapTrace("unfreezeServices", unfreezeServices) t := time.AfterFunc(5*time.Minute, func() { - logger.Info(color.Yellow("WARNING: Initializing the config subsystem is taking longer than 5 minutes. Please set '_MINIO_DISABLE_API_FREEZE_ON_BOOT=true' to not freeze the APIs")) + warnings = append(warnings, color.Yellow("WARNING: Initializing the config subsystem is taking longer than 5 minutes. Please set '_MINIO_DISABLE_API_FREEZE_ON_BOOT=true' to not freeze the APIs")) }) defer t.Stop() } @@ -994,7 +995,17 @@ func serverMain(ctx *cli.Context) { // Print a warning at the end of the startup banner so it is more noticeable if newObject.BackendInfo().StandardSCParity == 0 { - logger.Error("Warning: The standard parity is set to 0. This can lead to data loss.") + warnings = append(warnings, ("Warning: The standard parity is set to 0. This can lead to data loss.")) + } + objAPI := newObjectLayerFn() + if objAPI != nil { + printStorageInfo(objAPI.StorageInfo(GlobalContext, true)) + } + if len(warnings) > 0 { + logger.Info(color.Yellow("STARTUP WARNINGS:")) + for _, warn := range warnings { + logger.Info(warn) + } } }() diff --git a/cmd/server-startup-msg.go b/cmd/server-startup-msg.go index bd3ab1a35..ee02b08a5 100644 --- a/cmd/server-startup-msg.go +++ b/cmd/server-startup-msg.go @@ -37,7 +37,7 @@ func getFormatStr(strLen int, padding int) string { // Prints the formatted startup message. func printStartupMessage(apiEndpoints []string, err error) { - logger.Info(color.Bold("MinIO Object Storage Server")) + logger.Info(color.Bold(MinioBannerName)) if err != nil { if globalConsoleSys != nil { globalConsoleSys.Send(GlobalContext, fmt.Sprintf("Server startup failed with '%v', some features may be missing", err)) @@ -52,12 +52,6 @@ func printStartupMessage(apiEndpoints []string, err error) { strippedAPIEndpoints := stripStandardPorts(apiEndpoints, globalMinioHost) - // Object layer is initialized then print StorageInfo. - objAPI := newObjectLayerFn() - if objAPI != nil { - printStorageInfo(objAPI.StorageInfo(GlobalContext, true)) - } - // Prints credential, region and browser access. printServerCommonMsg(strippedAPIEndpoints) @@ -117,24 +111,23 @@ func printServerCommonMsg(apiEndpoints []string) { // Get saved region. region := globalSite.Region - apiEndpointStr := strings.Join(apiEndpoints, " ") - + apiEndpointStr := strings.TrimSpace(strings.Join(apiEndpoints, " ")) // Colorize the message and print. - logger.Info(color.Blue("S3-API: ") + color.Bold(fmt.Sprintf("%s ", apiEndpointStr))) + logger.Info(color.Blue("API: ") + color.Bold(fmt.Sprintf("%s ", apiEndpointStr))) if color.IsTerminal() && (!globalServerCtxt.Anonymous && !globalServerCtxt.JSON && globalAPIConfig.permitRootAccess()) { - logger.Info(color.Blue("RootUser: ") + color.Bold("%s ", cred.AccessKey)) - logger.Info(color.Blue("RootPass: ") + color.Bold("%s \n", cred.SecretKey)) + logger.Info(color.Blue(" RootUser: ") + color.Bold("%s ", cred.AccessKey)) + logger.Info(color.Blue(" RootPass: ") + color.Bold("%s \n", cred.SecretKey)) if region != "" { - logger.Info(color.Blue("Region: ") + color.Bold("%s", fmt.Sprintf(getFormatStr(len(region), 2), region))) + logger.Info(color.Blue(" Region: ") + color.Bold("%s", fmt.Sprintf(getFormatStr(len(region), 2), region))) } } if globalBrowserEnabled { consoleEndpointStr := strings.Join(stripStandardPorts(getConsoleEndpoints(), globalMinioConsoleHost), " ") - logger.Info(color.Blue("Console: ") + color.Bold(fmt.Sprintf("%s ", consoleEndpointStr))) + logger.Info(color.Blue("WebUI: ") + color.Bold(fmt.Sprintf("%s ", consoleEndpointStr))) if color.IsTerminal() && (!globalServerCtxt.Anonymous && !globalServerCtxt.JSON && globalAPIConfig.permitRootAccess()) { - logger.Info(color.Blue("RootUser: ") + color.Bold("%s ", cred.AccessKey)) - logger.Info(color.Blue("RootPass: ") + color.Bold("%s ", cred.SecretKey)) + logger.Info(color.Blue(" RootUser: ") + color.Bold("%s ", cred.AccessKey)) + logger.Info(color.Blue(" RootPass: ") + color.Bold("%s ", cred.SecretKey)) } } @@ -144,7 +137,7 @@ func printServerCommonMsg(apiEndpoints []string) { // Prints startup message for Object API access, prints link to our SDK documentation. func printObjectAPIMsg() { - logger.Info(color.Blue("\nDocumentation: ") + "https://min.io/docs/minio/linux/index.html") + logger.Info(color.Blue("\nDocs: ") + "https://min.io/docs/minio/linux/index.html") } func printLambdaTargets() { @@ -188,7 +181,7 @@ func printCLIAccessMsg(endPoint string, alias string) { // Configure 'mc', following block prints platform specific information for minio client. if color.IsTerminal() && (!globalServerCtxt.Anonymous && globalAPIConfig.permitRootAccess()) { - logger.Info(color.Blue("\nCommand-line: ") + mcQuickStartGuide) + logger.Info(color.Blue("\nCLI: ") + mcQuickStartGuide) mcMessage := fmt.Sprintf("$ mc alias set '%s' '%s' '%s' '%s'", alias, endPoint, cred.AccessKey, cred.SecretKey) logger.Info(fmt.Sprintf(getFormatStr(len(mcMessage), 3), mcMessage)) diff --git a/cmd/update-notifier.go b/cmd/update-notifier.go index 2e8f5f8b7..20c169f9b 100644 --- a/cmd/update-notifier.go +++ b/cmd/update-notifier.go @@ -95,8 +95,8 @@ func colorizeUpdateMessage(updateString string, newerThan string) string { lines := []string{ color.YellowBold(topLeftChar + strings.Repeat(horizBarChar, maxContentWidth) + topRightChar), - vertBarChar + line1InColor + strings.Repeat(" ", maxContentWidth-line1Length) + vertBarChar, - vertBarChar + line2InColor + strings.Repeat(" ", maxContentWidth-line2Length) + vertBarChar, + color.YellowBold(vertBarChar) + line1InColor + strings.Repeat(" ", maxContentWidth-line1Length) + color.YellowBold(vertBarChar), + color.YellowBold(vertBarChar) + line2InColor + strings.Repeat(" ", maxContentWidth-line2Length) + color.YellowBold(vertBarChar), color.YellowBold(bottomLeftChar + strings.Repeat(horizBarChar, maxContentWidth) + bottomRightChar), } return "\n" + strings.Join(lines, "\n") + "\n" diff --git a/cmd/update.go b/cmd/update.go index 73c22141a..0d1fc03ad 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -46,16 +46,12 @@ import ( ) const ( - minioReleaseTagTimeLayout = "2006-01-02T15-04-05Z" - minioOSARCH = runtime.GOOS + "-" + runtime.GOARCH - minioReleaseURL = "https://dl.min.io/server/minio/release/" + minioOSARCH + SlashSeparator - envMinisignPubKey = "MINIO_UPDATE_MINISIGN_PUBKEY" updateTimeout = 10 * time.Second ) // For windows our files have .exe additionally. -var minioReleaseWindowsInfoURL = minioReleaseURL + "minio.exe.sha256sum" +var minioReleaseWindowsInfoURL = MinioReleaseURL + "minio.exe.sha256sum" // minioVersionToReleaseTime - parses a standard official release // MinIO version string. @@ -72,7 +68,7 @@ func minioVersionToReleaseTime(version string) (releaseTime time.Time, err error // An official minio release tag looks like: // `RELEASE.2017-09-29T19-16-56Z` func releaseTimeToReleaseTag(releaseTime time.Time) string { - return "RELEASE." + releaseTime.Format(minioReleaseTagTimeLayout) + return "RELEASE." + releaseTime.Format(MinioReleaseTagTimeLayout) } // releaseTagToReleaseTime - reverse of `releaseTimeToReleaseTag()` @@ -84,7 +80,7 @@ func releaseTagToReleaseTime(releaseTag string) (releaseTime time.Time, err erro if fields[0] != "RELEASE" { return releaseTime, fmt.Errorf("%s is not a valid release tag", releaseTag) } - return time.Parse(minioReleaseTagTimeLayout, fields[1]) + return time.Parse(MinioReleaseTagTimeLayout, fields[1]) } // getModTime - get the file modification time of `path` @@ -236,8 +232,8 @@ func getUserAgent(mode string) string { uaAppend := func(p, q string) { userAgentParts = append(userAgentParts, p, q) } - - uaAppend("MinIO (", runtime.GOOS) + uaAppend(MinioUAName, " (") + uaAppend("", runtime.GOOS) uaAppend("; ", runtime.GOARCH) if mode != "" { uaAppend("; ", mode) @@ -258,14 +254,14 @@ func getUserAgent(mode string) string { uaAppend("; ", "source") } - uaAppend(") MinIO/", Version) - uaAppend(" MinIO/", ReleaseTag) - uaAppend(" MinIO/", CommitID) + uaAppend(" ", Version) + uaAppend(" ", ReleaseTag) + uaAppend(" ", CommitID) if IsDCOS() { universePkgVersion := env.Get("MARATHON_APP_LABEL_DCOS_PACKAGE_VERSION", "") // On DC/OS environment try to the get universe package version. if universePkgVersion != "" { - uaAppend(" MinIO/universe-", universePkgVersion) + uaAppend(" universe-", universePkgVersion) } } @@ -273,25 +269,26 @@ func getUserAgent(mode string) string { // In Kubernetes environment, try to fetch the helm package version helmChartVersion := getHelmVersion("/podinfo/labels") if helmChartVersion != "" { - uaAppend(" MinIO/helm-", helmChartVersion) + uaAppend(" helm-", helmChartVersion) } // In Kubernetes environment, try to fetch the Operator, VSPHERE plugin version opVersion := env.Get("MINIO_OPERATOR_VERSION", "") if opVersion != "" { - uaAppend(" MinIO/operator-", opVersion) + uaAppend(" operator-", opVersion) } vsphereVersion := env.Get("MINIO_VSPHERE_PLUGIN_VERSION", "") if vsphereVersion != "" { - uaAppend(" MinIO/vsphere-plugin-", vsphereVersion) + uaAppend(" vsphere-plugin-", vsphereVersion) } } if IsPCFTile() { pcfTileVersion := env.Get("MINIO_PCF_TILE_VERSION", "") if pcfTileVersion != "" { - uaAppend(" MinIO/pcf-tile-", pcfTileVersion) + uaAppend(" pcf-tile-", pcfTileVersion) } } + uaAppend("; ", "") if cpus, err := gopsutilcpu.Info(); err == nil && len(cpus) > 0 { cpuMap := make(map[string]struct{}, len(cpus)) @@ -304,6 +301,7 @@ func getUserAgent(mode string) string { uaAppend(" CPU ", fmt.Sprintf("(total_cpus:%d, total_cores:%d; vendor:%s; family:%s; model:%s; stepping:%d; model_name:%s)", len(cpuMap), len(coreMap), cpu.VendorID, cpu.Family, cpu.Model, cpu.Stepping, cpu.ModelName)) } + uaAppend(")", "") return strings.Join(userAgentParts, "") } @@ -474,10 +472,10 @@ func getDownloadURL(releaseTag string) (downloadURL string) { // For binary only installations, we return link to the latest binary. if runtime.GOOS == "windows" { - return minioReleaseURL + "minio.exe" + return MinioReleaseURL + "minio.exe" } - return minioReleaseURL + "minio" + return MinioReleaseURL + "minio" } func getUpdateReaderFromURL(u *url.URL, transport http.RoundTripper, mode string) (io.ReadCloser, error) { diff --git a/cmd/update_fips.go b/cmd/update_fips.go index 8813c26a6..d14c1d5ce 100644 --- a/cmd/update_fips.go +++ b/cmd/update_fips.go @@ -21,4 +21,4 @@ package cmd // Newer official download info URLs appear earlier below. -var minioReleaseInfoURL = minioReleaseURL + "minio.fips.sha256sum" +var minioReleaseInfoURL = MinioReleaseURL + "minio.fips.sha256sum" diff --git a/cmd/update_nofips.go b/cmd/update_nofips.go index 5b1e0e639..baeabc6e3 100644 --- a/cmd/update_nofips.go +++ b/cmd/update_nofips.go @@ -21,4 +21,4 @@ package cmd // Newer official download info URLs appear earlier below. -var minioReleaseInfoURL = minioReleaseURL + "minio.sha256sum" +var minioReleaseInfoURL = MinioReleaseURL + "minio.sha256sum" diff --git a/cmd/update_test.go b/cmd/update_test.go index d0389d91a..d36dcd696 100644 --- a/cmd/update_test.go +++ b/cmd/update_test.go @@ -112,12 +112,12 @@ func TestDownloadURL(t *testing.T) { } } else { if runtime.GOOS == "windows" { - if durl != minioReleaseURL+"minio.exe" { - t.Errorf("Expected %s, got %s", minioReleaseURL+"minio.exe", durl) + if durl != MinioReleaseURL+"minio.exe" { + t.Errorf("Expected %s, got %s", MinioReleaseURL+"minio.exe", durl) } } else { - if durl != minioReleaseURL+"minio" { - t.Errorf("Expected %s, got %s", minioReleaseURL+"minio", durl) + if durl != MinioReleaseURL+"minio" { + t.Errorf("Expected %s, got %s", MinioReleaseURL+"minio", durl) } } } @@ -147,19 +147,19 @@ func TestUserAgent(t *testing.T) { envName: "", envValue: "", mode: globalMinioModeFS, - expectedStr: fmt.Sprintf("MinIO (%s; %s; %s; source) MinIO/DEVELOPMENT.GOGET MinIO/DEVELOPMENT.GOGET MinIO/DEVELOPMENT.GOGET", runtime.GOOS, runtime.GOARCH, globalMinioModeFS), + expectedStr: fmt.Sprintf("MinIO (%s; %s; %s; source DEVELOPMENT.GOGET DEVELOPMENT.GOGET DEVELOPMENT.GOGET", runtime.GOOS, runtime.GOARCH, globalMinioModeFS), }, { envName: "MESOS_CONTAINER_NAME", envValue: "mesos-11111", mode: globalMinioModeErasure, - expectedStr: fmt.Sprintf("MinIO (%s; %s; %s; %s; source) MinIO/DEVELOPMENT.GOGET MinIO/DEVELOPMENT.GOGET MinIO/DEVELOPMENT.GOGET MinIO/universe-%s", runtime.GOOS, runtime.GOARCH, globalMinioModeErasure, "dcos", "mesos-1111"), + expectedStr: fmt.Sprintf("MinIO (%s; %s; %s; %s; source DEVELOPMENT.GOGET DEVELOPMENT.GOGET DEVELOPMENT.GOGET universe-%s", runtime.GOOS, runtime.GOARCH, globalMinioModeErasure, "dcos", "mesos-1111"), }, { envName: "KUBERNETES_SERVICE_HOST", envValue: "10.11.148.5", mode: globalMinioModeErasure, - expectedStr: fmt.Sprintf("MinIO (%s; %s; %s; %s; source) MinIO/DEVELOPMENT.GOGET MinIO/DEVELOPMENT.GOGET MinIO/DEVELOPMENT.GOGET", runtime.GOOS, runtime.GOARCH, globalMinioModeErasure, "kubernetes"), + expectedStr: fmt.Sprintf("MinIO (%s; %s; %s; %s; source DEVELOPMENT.GOGET DEVELOPMENT.GOGET DEVELOPMENT.GOGET", runtime.GOOS, runtime.GOARCH, globalMinioModeErasure, "kubernetes"), }, }