VOL-1674 - add version reporting information

Change-Id: Ie6cc244c66077467d371ffb3506ea0f4e817c197
diff --git a/afrouter/afrouter/config.go b/afrouter/afrouter/config.go
index 044fdd7..1f0be7b 100644
--- a/afrouter/afrouter/config.go
+++ b/afrouter/afrouter/config.go
@@ -34,6 +34,7 @@
 	config.ConfigFile = cmdParse.String("config", "arouter.json", "The configuration file for the affinity router")
 	config.LogLevel = cmdParse.Int("logLevel", 0, "The log level for the affinity router")
 	config.GrpcLog = cmdParse.Bool("grpclog", false, "Enable GRPC logging")
+	config.DisplayVersionOnly = cmdParse.Bool("version", false, "Print version information and exit")
 
 	err := cmdParse.Parse(os.Args[1:])
 	if err != nil {
@@ -50,6 +51,7 @@
 	ConfigFile         *string
 	LogLevel           *int
 	GrpcLog            *bool
+	DisplayVersionOnly *bool
 	Servers            []ServerConfig         `json:"servers"`
 	Ports              PortConfig             `json:"ports"`
 	ServerCertificates ServerCertConfig       `json:"serverCertificates"`
diff --git a/afrouter/arouter.go b/afrouter/arouter.go
index 4342f68..10ee873 100644
--- a/afrouter/arouter.go
+++ b/afrouter/arouter.go
@@ -20,6 +20,7 @@
 	"fmt"
 	"github.com/opencord/voltha-go/afrouter/afrouter"
 	"github.com/opencord/voltha-go/common/log"
+	"github.com/opencord/voltha-go/common/version"
 	"google.golang.org/grpc/grpclog"
 	slog "log"
 	"os"
@@ -40,6 +41,12 @@
 
 	defer log.CleanUp()
 
+	if *conf.DisplayVersionOnly {
+		fmt.Println("VOLTHA API Server (afrouter)")
+		fmt.Println(version.VersionInfo.String("  "))
+		return
+	}
+
 	// Parse the config file
 	err = conf.LoadConfig()
 	if err != nil {
diff --git a/arouterd/arouterd.go b/arouterd/arouterd.go
index f5f2453..47445ac 100644
--- a/arouterd/arouterd.go
+++ b/arouterd/arouterd.go
@@ -18,9 +18,11 @@
 
 import (
 	"errors"
+	"flag"
 	"fmt"
 	"math"
 	"os"
+	"path"
 	"regexp"
 	"strconv"
 	"time"
@@ -28,6 +30,7 @@
 	"github.com/golang/protobuf/ptypes"
 	"github.com/golang/protobuf/ptypes/empty"
 	"github.com/opencord/voltha-go/common/log"
+	"github.com/opencord/voltha-go/common/version"
 	"github.com/opencord/voltha-go/kafka"
 	pb "github.com/opencord/voltha-protos/go/afrouter"
 	cmn "github.com/opencord/voltha-protos/go/common"
@@ -55,6 +58,10 @@
 	dn  bool
 }
 
+type Configuration struct {
+	DisplayVersionOnly *bool
+}
+
 var (
 	podNamespace = getStrEnv("POD_NAMESPACE", "voltha")
 	podGrpcPort  = uint64(getIntEnv("POD_GRPC_PORT", 0, math.MaxUint16, 50057))
@@ -784,6 +791,22 @@
 	var err error
 	var conn *grpc.ClientConn
 
+	config := &Configuration{}
+	cmdParse := flag.NewFlagSet(path.Base(os.Args[0]), flag.ContinueOnError)
+	config.DisplayVersionOnly = cmdParse.Bool("version", false, "Print version information and exit")
+
+	err = cmdParse.Parse(os.Args[1:])
+	if err != nil {
+		fmt.Printf("Error: %v\n", err)
+		os.Exit(1)
+	}
+
+	if *config.DisplayVersionOnly {
+		fmt.Println("VOLTHA API Server (afrouterd)")
+		fmt.Println(version.VersionInfo.String("  "))
+		return
+	}
+
 	// Set up the regular expression to identify the voltha cores
 	rwCoreFltr := regexp.MustCompile(`rw-core[0-9]-`)
 	roCoreFltr := regexp.MustCompile(`ro-core-`)
diff --git a/common/version/version.go b/common/version/version.go
new file mode 100644
index 0000000..49c0b10
--- /dev/null
+++ b/common/version/version.go
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package version
+
+import (
+	"fmt"
+	"strings"
+)
+
+// Default build-time variable.
+// These values can (should) be overridden via ldflags when built with
+// `make`
+var (
+	version   = "unknown-version"
+	goVersion = "unknown-goversion"
+	vcsRef    = "unknown-vcsref"
+	vcsDirty  = "unknown-vcsdirty"
+	buildTime = "unknown-buildtime"
+	os        = "unknown-os"
+	arch      = "unknown-arch"
+)
+
+type VersionInfoType struct {
+	Version   string `json:"version"`
+	GoVersion string `json:"goversion"`
+	VcsRef    string `json:"vcsref"`
+	VcsDirty  string `json:"vcsdirty"`
+	BuildTime string `json:"buildtime"`
+	Os        string `json:"os"`
+	Arch      string `json:"arch"`
+}
+
+var VersionInfo VersionInfoType
+
+func init() {
+	VersionInfo = VersionInfoType{
+		Version:   version,
+		VcsRef:    vcsRef,
+		VcsDirty:  vcsDirty,
+		GoVersion: goVersion,
+		Os:        os,
+		Arch:      arch,
+		BuildTime: buildTime,
+	}
+}
+
+func (v VersionInfoType) String(indent string) string {
+	builder := strings.Builder{}
+
+	builder.WriteString(fmt.Sprintf("%sVersion:      %s\n", indent, VersionInfo.Version))
+	builder.WriteString(fmt.Sprintf("%sGoVersion:    %s\n", indent, VersionInfo.GoVersion))
+	builder.WriteString(fmt.Sprintf("%sVCS Ref:      %s\n", indent, VersionInfo.VcsRef))
+	builder.WriteString(fmt.Sprintf("%sVCS Dirty:    %s\n", indent, VersionInfo.VcsDirty))
+	builder.WriteString(fmt.Sprintf("%sBuilt:        %s\n", indent, VersionInfo.BuildTime))
+	builder.WriteString(fmt.Sprintf("%sOS/Arch:      %s/%s\n", indent, VersionInfo.Os, VersionInfo.Arch))
+	return builder.String()
+}
diff --git a/docker/Dockerfile.afrouter b/docker/Dockerfile.afrouter
index e604e2c..04cbf4c 100644
--- a/docker/Dockerfile.afrouter
+++ b/docker/Dockerfile.afrouter
@@ -17,6 +17,13 @@
 
 FROM golang:1.12-alpine3.9 AS build-env
 
+ARG org_label_schema_version=unknown
+ARG org_label_schema_vcs_url=unknown
+ARG org_label_schema_vcs_ref=unknown
+ARG org_label_schema_build_date=unknown
+ARG org_opencord_vcs_commit_date=unknown
+ARG org_opencord_vcs_dirty=unknown
+
 # Install required packages
 RUN apk add --no-cache wget git make build-base protobuf protobuf-dev
 
@@ -43,7 +50,15 @@
 RUN cp vendor/github.com/opencord/voltha-protos/go/voltha.pb /build
 
 # Build
-RUN cd afrouter && go build -o /build/afrouter
+RUN cd afrouter && go build -o /build/afrouter \
+	-ldflags \
+	"-X github.com/opencord/voltha-go/common/version.version=$org_label_schema_version \
+	 -X github.com/opencord/voltha-go/common/version.vcsRef=$org_label_schema_vcs_ref  \
+	 -X github.com/opencord/voltha-go/common/version.vcsDirty=$org_opencord_vcs_dirty \
+	 -X github.com/opencord/voltha-go/common/version.goVersion=$(go version 2>&1 | sed -E  's/.*go([0-9]+\.[0-9]+\.[0-9]+).*/\1/g') \
+	 -X github.com/opencord/voltha-go/common/version.os=$(go env GOHOSTOS) \
+	 -X github.com/opencord/voltha-go/common/version.arch=$(go env GOHOSTARCH) \
+	 -X github.com/opencord/voltha-go/common/version.buildTime=$org_label_schema_build_date"
 
 # -------------
 # Image creation stage
diff --git a/docker/Dockerfile.afrouterTest b/docker/Dockerfile.afrouterTest
index c93570e..33c6d46 100644
--- a/docker/Dockerfile.afrouterTest
+++ b/docker/Dockerfile.afrouterTest
@@ -17,6 +17,13 @@
 
 FROM golang:1.12-alpine3.9 AS build-env
 
+ARG org_label_schema_version=unknown
+ARG org_label_schema_vcs_url=unknown
+ARG org_label_schema_vcs_ref=unknown
+ARG org_label_schema_build_date=unknown
+ARG org_opencord_vcs_commit_date=unknown
+ARG org_opencord_vcs_dirty=unknown
+
 # Install required packages
 RUN apk add --no-cache wget git make build-base protobuf protobuf-dev
 
@@ -48,8 +55,25 @@
 RUN cp vendor/github.com/opencord/voltha-protos/go/voltha.pb /build/tests/suites/
 
 # Build
-RUN cd afrouter && go build --tags integration -o /build/afrouter
-RUN cd tests/afrouter && go build --tags integration -o /build/afrouterTest
+RUN cd afrouter && go build --tags integration -o /build/afrouter \
+	-ldflags \
+	"-X github.com/opencord/voltha-go/common/version.version=$org_label_schema_version \
+	 -X github.com/opencord/voltha-go/common/version.vcsRef=$org_label_schema_vcs_ref  \
+	 -X github.com/opencord/voltha-go/common/version.vcsDirty=$org_opencord_vcs_dirty \
+	 -X github.com/opencord/voltha-go/common/version.goVersion=$(go version 2>&1 | sed -E  's/.*go([0-9]+\.[0-9]+\.[0-9]+).*/\1/g') \
+	 -X github.com/opencord/voltha-go/common/version.os=$(go env GOHOSTOS) \
+	 -X github.com/opencord/voltha-go/common/version.arch=$(go env GOHOSTARCH) \
+	 -X github.com/opencord/voltha-go/common/version.buildTime=$org_label_schema_build_date"
+
+RUN cd tests/afrouter && go build --tags integration -o /build/afrouterTest \
+	-ldflags \
+	"-X github.com/opencord/voltha-go/common/version.version=$org_label_schema_version \
+	 -X github.com/opencord/voltha-go/common/version.vcsRef=$org_label_schema_vcs_ref  \
+	 -X github.com/opencord/voltha-go/common/version.vcsDirty=$org_opencord_vcs_dirty \
+	 -X github.com/opencord/voltha-go/common/version.goVersion=$(go version 2>&1 | sed -E  's/.*go([0-9]+\.[0-9]+\.[0-9]+).*/\1/g') \
+	 -X github.com/opencord/voltha-go/common/version.os=$(uname -s | tr A-Z a-z) \
+	 -X github.com/opencord/voltha-go/common/version.arch=$(uname -m | tr A-Z a-z) \
+	 -X github.com/opencord/voltha-go/common/version.buildTime=$org_label_schema_build_date"
 
 # Run tests
 RUN cd /build/tests/suites && /build/afrouterTest -config main.json -logLevel 1
diff --git a/docker/Dockerfile.afrouterd b/docker/Dockerfile.afrouterd
index 123a5dc..6778b7b 100644
--- a/docker/Dockerfile.afrouterd
+++ b/docker/Dockerfile.afrouterd
@@ -17,6 +17,13 @@
 
 FROM golang:1.12-alpine3.9 AS build-env
 
+ARG org_label_schema_version=unknown
+ARG org_label_schema_vcs_url=unknown
+ARG org_label_schema_vcs_ref=unknown
+ARG org_label_schema_build_date=unknown
+ARG org_opencord_vcs_commit_date=unknown
+ARG org_opencord_vcs_dirty=unknown
+
 # Install required packages
 RUN apk add --no-cache wget git make build-base protobuf protobuf-dev
 
@@ -43,7 +50,15 @@
 RUN cp afrouter/arouter.json /build
 
 # Build
-RUN cd arouterd && go build -o /build/arouterd
+RUN cd arouterd && go build -o /build/arouterd \
+	-ldflags \
+	"-X github.com/opencord/voltha-go/common/version.version=$org_label_schema_version \
+	 -X github.com/opencord/voltha-go/common/version.vcsRef=$org_label_schema_vcs_ref  \
+	 -X github.com/opencord/voltha-go/common/version.vcsDirty=$org_opencord_vcs_dirty \
+	 -X github.com/opencord/voltha-go/common/version.goVersion=$(go version 2>&1 | sed -E  's/.*go([0-9]+\.[0-9]+\.[0-9]+).*/\1/g') \
+	 -X github.com/opencord/voltha-go/common/version.os=$(go env GOHOSTOS) \
+	 -X github.com/opencord/voltha-go/common/version.arch=$(go env GOHOSTARCH) \
+	 -X github.com/opencord/voltha-go/common/version.buildTime=$org_label_schema_build_date"
 
 # -------------
 # Image creation stage
diff --git a/docker/Dockerfile.ro_core b/docker/Dockerfile.ro_core
index 27dd34d..5b41c89 100644
--- a/docker/Dockerfile.ro_core
+++ b/docker/Dockerfile.ro_core
@@ -17,6 +17,13 @@
 
 FROM golang:1.12-alpine3.9 AS build-env
 
+ARG org_label_schema_version=unknown
+ARG org_label_schema_vcs_url=unknown
+ARG org_label_schema_vcs_ref=unknown
+ARG org_label_schema_build_date=unknown
+ARG org_opencord_vcs_commit_date=unknown
+ARG org_opencord_vcs_dirty=unknown
+
 # Install required packages
 RUN apk add --no-cache wget git make build-base protobuf protobuf-dev
 
@@ -38,7 +45,15 @@
 COPY ro_core ./ro_core
 
 # Build
-RUN cd ro_core && go build -o /build/ro_core
+RUN cd ro_core && go build -o /build/ro_core \
+	-ldflags \
+	"-X github.com/opencord/voltha-go/common/version.version=$org_label_schema_version \
+	 -X github.com/opencord/voltha-go/common/version.vcsRef=$org_label_schema_vcs_ref  \
+	 -X github.com/opencord/voltha-go/common/version.vcsDirty=$org_opencord_vcs_dirty \
+	 -X github.com/opencord/voltha-go/common/version.goVersion=$(go version 2>&1 | sed -E  's/.*go([0-9]+\.[0-9]+\.[0-9]+).*/\1/g') \
+	 -X github.com/opencord/voltha-go/common/version.os=$(go env GOHOSTOS) \
+	 -X github.com/opencord/voltha-go/common/version.arch=$(go env GOHOSTARCH) \
+	 -X github.com/opencord/voltha-go/common/version.buildTime=$org_label_schema_build_date"
 
 # -------------
 # Image creation stage
diff --git a/docker/Dockerfile.rw_core b/docker/Dockerfile.rw_core
index 6bd4f89..71996be 100644
--- a/docker/Dockerfile.rw_core
+++ b/docker/Dockerfile.rw_core
@@ -17,6 +17,13 @@
 
 FROM golang:1.12-alpine3.9 AS build-env
 
+ARG org_label_schema_version=unknown
+ARG org_label_schema_vcs_url=unknown
+ARG org_label_schema_vcs_ref=unknown
+ARG org_label_schema_build_date=unknown
+ARG org_opencord_vcs_commit_date=unknown
+ARG org_opencord_vcs_dirty=unknown
+
 # Install required packages
 RUN apk add --no-cache wget git make build-base protobuf protobuf-dev
 
@@ -38,7 +45,15 @@
 COPY rw_core ./rw_core
 
 # Build
-RUN cd rw_core && go build -o /build/rw_core
+RUN cd rw_core && go build -o /build/rw_core \
+	-ldflags \
+	"-X github.com/opencord/voltha-go/common/version.version=$org_label_schema_version \
+	 -X github.com/opencord/voltha-go/common/version.vcsRef=$org_label_schema_vcs_ref  \
+	 -X github.com/opencord/voltha-go/common/version.vcsDirty=$org_opencord_vcs_dirty \
+	 -X github.com/opencord/voltha-go/common/version.goVersion=$(go version 2>&1 | sed -E  's/.*go([0-9]+\.[0-9]+\.[0-9]+).*/\1/g') \
+	 -X github.com/opencord/voltha-go/common/version.os=$(go env GOHOSTOS) \
+	 -X github.com/opencord/voltha-go/common/version.arch=$(go env GOHOSTARCH) \
+	 -X github.com/opencord/voltha-go/common/version.buildTime=$org_label_schema_build_date"
 
 # -------------
 # Image creation stage
diff --git a/docker/Dockerfile.simulated_olt b/docker/Dockerfile.simulated_olt
index 0a14ac9..6904318 100644
--- a/docker/Dockerfile.simulated_olt
+++ b/docker/Dockerfile.simulated_olt
@@ -17,6 +17,13 @@
 
 FROM golang:1.12-alpine3.9 AS build-env
 
+ARG org_label_schema_version=unknown
+ARG org_label_schema_vcs_url=unknown
+ARG org_label_schema_vcs_ref=unknown
+ARG org_label_schema_build_date=unknown
+ARG org_opencord_vcs_commit_date=unknown
+ARG org_opencord_vcs_dirty=unknown
+
 # Install required packages
 RUN apk add --no-cache wget git make build-base protobuf protobuf-dev
 
@@ -40,7 +47,15 @@
 COPY adapters/*.go ./adapters/
 
 # Build
-RUN cd adapters/simulated_olt && go build -o /build/simulated_olt
+RUN cd adapters/simulated_olt && go build -o /build/simulated_olt \
+	-ldflags \
+	"-X github.com/opencord/voltha-go/common/version.version=$org_label_schema_version \
+	 -X github.com/opencord/voltha-go/common/version.vcsRef=$org_label_schema_vcs_ref  \
+	 -X github.com/opencord/voltha-go/common/version.vcsDirty=$org_opencord_vcs_dirty \
+	 -X github.com/opencord/voltha-go/common/version.goVersion=$(go version 2>&1 | sed -E  's/.*go([0-9]+\.[0-9]+\.[0-9]+).*/\1/g') \
+	 -X github.com/opencord/voltha-go/common/version.os=$(go env GOHOSTOS) \
+	 -X github.com/opencord/voltha-go/common/version.arch=$(go env GOHOSTARCH) \
+	 -X github.com/opencord/voltha-go/common/version.buildTime=$org_label_schema_build_date"
 
 # -------------
 # Image creation stage
diff --git a/docker/Dockerfile.simulated_onu b/docker/Dockerfile.simulated_onu
index b9d01cc..921fc2a 100644
--- a/docker/Dockerfile.simulated_onu
+++ b/docker/Dockerfile.simulated_onu
@@ -17,6 +17,13 @@
 
 FROM golang:1.12-alpine3.9 AS build-env
 
+ARG org_label_schema_version=unknown
+ARG org_label_schema_vcs_url=unknown
+ARG org_label_schema_vcs_ref=unknown
+ARG org_label_schema_build_date=unknown
+ARG org_opencord_vcs_commit_date=unknown
+ARG org_opencord_vcs_dirty=unknown
+
 # Install required packages
 RUN apk add --no-cache wget git make build-base protobuf protobuf-dev
 
@@ -40,7 +47,15 @@
 COPY adapters/*.go ./adapters/
 
 # Build
-RUN cd adapters/simulated_onu && go build -o /build/simulated_onu
+RUN cd adapters/simulated_onu && go build -o /build/simulated_onu \
+	-ldflags \
+	"-X github.com/opencord/voltha-go/common/version.version=$org_label_schema_version \
+	 -X github.com/opencord/voltha-go/common/version.vcsRef=$org_label_schema_vcs_ref  \
+	 -X github.com/opencord/voltha-go/common/version.vcsDirty=$org_opencord_vcs_dirty \
+	 -X github.com/opencord/voltha-go/common/version.goVersion=$(go version 2>&1 | sed -E  's/.*go([0-9]+\.[0-9]+\.[0-9]+).*/\1/g') \
+	 -X github.com/opencord/voltha-go/common/version.os=$(go env GOHOSTOS) \
+	 -X github.com/opencord/voltha-go/common/version.arch=$(go env GOHOSTARCH) \
+	 -X github.com/opencord/voltha-go/common/version.buildTime=$org_label_schema_build_date"
 
 # -------------
 # Image creation stage
diff --git a/ro_core/config/config.go b/ro_core/config/config.go
index b7906f2..030134b 100644
--- a/ro_core/config/config.go
+++ b/ro_core/config/config.go
@@ -36,6 +36,7 @@
 	default_KVTxnKeyDelTime       = 60
 	default_LogLevel              = 0
 	default_Banner                = false
+	default_DisplayVersionOnly    = false
 	default_CoreTopic             = "rocore"
 	default_ROCoreEndpoint        = "rocore"
 	default_ROCoreKey             = "pki/voltha.key"
@@ -59,6 +60,7 @@
 	CoreTopic           string
 	LogLevel            int
 	Banner              bool
+	DisplayVersionOnly  bool
 	ROCoreKey           string
 	ROCoreCert          string
 	ROCoreCA            string
@@ -84,6 +86,7 @@
 		CoreTopic:           default_CoreTopic,
 		LogLevel:            default_LogLevel,
 		Banner:              default_Banner,
+		DisplayVersionOnly:  default_DisplayVersionOnly,
 		ROCoreKey:           default_ROCoreKey,
 		ROCoreCert:          default_ROCoreCert,
 		ROCoreCA:            default_ROCoreCA,
@@ -133,6 +136,9 @@
 	help = fmt.Sprintf("Show startup banner log lines")
 	flag.BoolVar(&cf.Banner, "banner", default_Banner, help)
 
+	help = fmt.Sprintf("Show version information and exit")
+	flag.BoolVar(&cf.DisplayVersionOnly, "version", default_DisplayVersionOnly, help)
+
 	flag.Parse()
 
 	containerName := getContainerInfo()
diff --git a/ro_core/core/model_proxy_manager.go b/ro_core/core/model_proxy_manager.go
index 60295c0..5613475 100644
--- a/ro_core/core/model_proxy_manager.go
+++ b/ro_core/core/model_proxy_manager.go
@@ -17,7 +17,9 @@
 
 import (
 	"context"
+	"encoding/json"
 	"github.com/opencord/voltha-go/common/log"
+	"github.com/opencord/voltha-go/common/version"
 	"github.com/opencord/voltha-go/db/model"
 	"github.com/opencord/voltha-protos/go/voltha"
 	"google.golang.org/grpc/codes"
@@ -73,11 +75,22 @@
 func (mpMgr *ModelProxyManager) GetVoltha(ctx context.Context) (*voltha.Voltha, error) {
 	log.Debug("GetVoltha")
 
-	// TODO: Need to retrieve VOLTHA core information, for now return empty
-	// value
+	/*
+	 * For now, encode all the version information into a JSON object and
+	 * pass that back as "version" so the client can get all the
+	 * information associated with the version. Long term the API should
+	 * better accomidate this, but for now this will work.
+	 */
+	data, err := json.Marshal(&version.VersionInfo)
+	info := version.VersionInfo.Version
+	if err != nil {
+		log.Warnf("Unable to encode version information as JSON: %s", err.Error())
+	} else {
+		info = string(data)
+	}
+
 	return &voltha.Voltha{
-		// TODO: hardcoded for now until ldflags are supported
-		Version: "2.1.0-dev",
+		Version: info,
 	}, nil
 }
 
diff --git a/ro_core/main.go b/ro_core/main.go
index 97015d4..2313fd3 100644
--- a/ro_core/main.go
+++ b/ro_core/main.go
@@ -21,6 +21,7 @@
 	"fmt"
 	grpcserver "github.com/opencord/voltha-go/common/grpc"
 	"github.com/opencord/voltha-go/common/log"
+	"github.com/opencord/voltha-go/common/version"
 	"github.com/opencord/voltha-go/db/kvstore"
 	"github.com/opencord/voltha-go/ro_core/config"
 	c "github.com/opencord/voltha-go/ro_core/core"
@@ -159,13 +160,19 @@
 }
 
 func printBanner() {
-	fmt.Println("                                            ")
-	fmt.Println(" ______        ______                       ")
-	fmt.Println("|  _ \\ \\      / / ___|___  _ __ ___       ")
-	fmt.Println("| |_) \\ \\ /\\ / / |   / _ \\| '__/ _ \\   ")
-	fmt.Println("|  _ < \\ V  V /| |__| (_) | | |  __/       ")
-	fmt.Println("|_| \\_\\ \\_/\\_/  \\____\\___/|_|  \\___| ")
-	fmt.Println("                                            ")
+	fmt.Println()
+	fmt.Println(" ____   ___   ____               ")
+	fmt.Println("|  _ \\ / _ \\ / ___|___  _ __ ___ ")
+	fmt.Println("| |_) | | | | |   / _ \\| '__/ _ \\")
+	fmt.Println("|  _ <| |_| | |__| (_) | | |  __/")
+	fmt.Println("|_| \\_\\\\___/ \\____\\___/|_|  \\___|")
+	fmt.Println()
+
+}
+
+func printVersion() {
+	fmt.Println("VOLTHA Read-Only Core")
+	fmt.Println(version.VersionInfo.String("  "))
 }
 
 func main() {
@@ -190,6 +197,12 @@
 
 	defer log.CleanUp()
 
+	// Print verison / build information and exit
+	if cf.DisplayVersionOnly {
+		printVersion()
+		return
+	}
+
 	// Print banner if specified
 	if cf.Banner {
 		printBanner()
diff --git a/rw_core/config/config.go b/rw_core/config/config.go
index a282b9b..34b5867 100644
--- a/rw_core/config/config.go
+++ b/rw_core/config/config.go
@@ -41,6 +41,7 @@
 	default_KVStoreDataPrefix         = "service/voltha"
 	default_LogLevel                  = 0
 	default_Banner                    = false
+	default_DisplayVersionOnly        = false
 	default_CoreTopic                 = "rwcore"
 	default_RWCoreEndpoint            = "rwcore"
 	default_RWCoreKey                 = "pki/voltha.key"
@@ -74,6 +75,7 @@
 	CoreTopic                 string
 	LogLevel                  int
 	Banner                    bool
+	DisplayVersionOnly        bool
 	RWCoreKey                 string
 	RWCoreCert                string
 	RWCoreCA                  string
@@ -109,6 +111,7 @@
 		CoreTopic:                 default_CoreTopic,
 		LogLevel:                  default_LogLevel,
 		Banner:                    default_Banner,
+		DisplayVersionOnly:        default_DisplayVersionOnly,
 		RWCoreKey:                 default_RWCoreKey,
 		RWCoreCert:                default_RWCoreCert,
 		RWCoreCA:                  default_RWCoreCA,
@@ -193,6 +196,9 @@
 	help = fmt.Sprintf("Show startup banner log lines")
 	flag.BoolVar(&cf.Banner, "banner", default_Banner, help)
 
+	help = fmt.Sprintf("Show version information and exit")
+	flag.BoolVar(&cf.DisplayVersionOnly, "version", default_DisplayVersionOnly, help)
+
 	help = fmt.Sprintf("The name of the meta-key whose value is the rw-core group to which the ofagent is bound")
 	flag.StringVar(&(cf.CoreBindingKey), "core_binding_key", default_CoreBindingKey, help)
 
diff --git a/rw_core/main.go b/rw_core/main.go
index 084e339..fc135f6 100644
--- a/rw_core/main.go
+++ b/rw_core/main.go
@@ -21,6 +21,7 @@
 	"fmt"
 	grpcserver "github.com/opencord/voltha-go/common/grpc"
 	"github.com/opencord/voltha-go/common/log"
+	"github.com/opencord/voltha-go/common/version"
 	"github.com/opencord/voltha-go/db/kvstore"
 	"github.com/opencord/voltha-go/kafka"
 	"github.com/opencord/voltha-go/rw_core/config"
@@ -210,6 +211,11 @@
 	fmt.Println("                                            ")
 }
 
+func printVersion() {
+	fmt.Println("VOLTHA Read-Write Core")
+	fmt.Println(version.VersionInfo.String("  "))
+}
+
 func main() {
 	start := time.Now()
 
@@ -238,6 +244,12 @@
 
 	defer log.CleanUp()
 
+	// Print verison / build information and exit
+	if cf.DisplayVersionOnly {
+		printVersion()
+		return
+	}
+
 	// Print banner if specified
 	if cf.Banner {
 		printBanner()