[SEBA-350] Returning BandwidthProfile information together with subscriber

Change-Id: Ia3f39f45ea414f6b54fbd4b2f3d651b8674e7508
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7ca1f34
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,28 @@
+# Copyright 2018 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.
+
+REGISTRY          ?=
+REPOSITORY        ?=
+DOCKER_BUILD_ARGS ?=
+TAG               ?= $(shell cat ${MAKEFILE_DIR}/VERSION)
+IMAGENAME         := ${REGISTRY}${REPOSITORY}sadis-server:${TAG}
+SHELL             := /bin/bash
+
+all: build push
+
+build:
+	docker build $(DOCKER_BUILD_ARGS) -t ${IMAGENAME} -f Dockerfile .
+
+push:
+	docker push ${IMAGENAME}
\ No newline at end of file
diff --git a/VERSION b/VERSION
index 7dea76e..336c367 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.1
+1.1.0-dev
diff --git a/handlers.go b/handlers.go
index fc28647..63f14f6 100644
--- a/handlers.go
+++ b/handlers.go
@@ -15,11 +15,12 @@
 
 import (
 	"encoding/json"
-	"github.com/sirupsen/logrus"
 	"net"
 	"net/http"
 	"strconv"
 
+	"github.com/sirupsen/logrus"
+
 	"github.com/gorilla/mux"
 )
 
@@ -57,6 +58,53 @@
 				RemoteID:  sub.RemoteID,
 			}
 
+			log.Debugf("Fetching bandwidth profiles for subscriber %s", sub.OnuSerialNumber)
+
+			dsBandwidthprofile := bandwidthprofile{}
+			err = c.getOneBandwidthProfileHandler(sub.DownstreamBandwidthProfile, &dsBandwidthprofile)
+			if err != nil {
+				log.Errorf("Cannot fetch downstream bandwidth profile %s for subscriber %s", strconv.Itoa(sub.DownstreamBandwidthProfile), sub.OnuSerialNumber)
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+				return
+			}
+			if (bandwidthprofile{}) == dsBandwidthprofile {
+				// it's empty
+				log.WithFields(logrus.Fields{
+					"DownstreamBandwidthProfile": sub.DownstreamBandwidthProfile,
+					"Subscriber":                 sub.OnuSerialNumber,
+					"sadisId":                    sadisRequestID,
+				}).Error("Downstream bandwidth profile not found in XOS")
+				http.Error(w, "Downstream bandwidth profile not found in XOS", http.StatusInternalServerError)
+				return
+			}
+			sadisSubscriber.DownstreamBandwidthProfile = dsBandwidthprofile.Name
+
+			usBandwidthprofile := bandwidthprofile{}
+			err = c.getOneBandwidthProfileHandler(sub.UpstreamBandwidthProfile, &usBandwidthprofile)
+			if err != nil {
+				log.Errorf("Cannot fetch upstream bandwidth profile %s for subscriber %s", strconv.Itoa(sub.UpstreamBandwidthProfile), sub.OnuSerialNumber)
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+				return
+			}
+			if (bandwidthprofile{}) == usBandwidthprofile {
+				// it's empty
+				log.WithFields(logrus.Fields{
+					"UpstreamBandwidthProfile": usBandwidthprofile.Name,
+					"Subscriber":               sub.OnuSerialNumber,
+					"sadisId":                  sadisRequestID,
+				}).Error("Upstream bandwidth profile not found in XOS")
+				http.Error(w, "Upstream bandwidth profile not found in XOS", http.StatusInternalServerError)
+				return
+			}
+			sadisSubscriber.UpstreamBandwidthProfile = usBandwidthprofile.Name
+
+			log.WithFields(logrus.Fields{
+				"UpstreamBandwidthProfile":   usBandwidthprofile.Name,
+				"DownstreamBandwidthProfile": dsBandwidthprofile.Name,
+				"Subscriber":                 sub.OnuSerialNumber,
+				"sadisId":                    sadisRequestID,
+			}).Debug("Bandwidth profiles for subscriber")
+
 			json, e := json.Marshal(&sadisSubscriber)
 			if e != nil {
 				log.Errorf("Unable to marshal JSON: %s", e)
@@ -122,6 +170,63 @@
 	http.NotFound(w, r)
 }
 
+func (c *Config) getBandwidthProfileHandler(w http.ResponseWriter, r *http.Request) {
+	vars := mux.Vars(r)
+	sadisRequestID := vars["id"]
+
+	log.WithFields(logrus.Fields{
+		"sadisId": sadisRequestID,
+	}).Infof("Fetching BandwidthProfiles from XOS database")
+	defer r.Body.Close()
+
+	bandwidthprofiles := bandwidthprofiles{}
+
+	err := c.fetch("/xosapi/v1/rcord/bandwidthprofiles", &bandwidthprofiles)
+
+	if err != nil {
+		log.Errorf("Unable to retrieve bandwidth profiles information from XOS: %s", err)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	for _, profile := range bandwidthprofiles.Profiles {
+		profileID := profile.Name
+		if profileID == sadisRequestID {
+			sadisProfile := sadisBandwidthProfile{
+				ID:  profile.Name,
+				Cir: profile.Cir,
+				Cbs: profile.Cbs,
+				Eir: profile.Eir,
+				Ebs: profile.Ebs,
+				Air: profile.Air,
+			}
+			json, e := json.Marshal(&sadisProfile)
+			if e != nil {
+				log.Errorf("Unable to marshal JSON: %s", e)
+				http.Error(w, e.Error(), http.StatusInternalServerError)
+				return
+			}
+			w.Write(json)
+			return
+		}
+	}
+
+	log.WithFields(logrus.Fields{
+		"sadisId": sadisRequestID,
+	}).Infof("Couldn't find object %s in XOS database", sadisRequestID)
+
+	http.NotFound(w, r)
+}
+
+func (c *Config) getOneBandwidthProfileHandler(id int, data interface{}) error {
+	err := c.fetch("/xosapi/v1/rcord/bandwidthprofiles/"+strconv.Itoa(id), &data)
+	if err != nil {
+		log.Errorf("Unable to retrieve bandwidth profile information from XOS: %s", err)
+		return err
+	}
+	return nil
+}
+
 func toInt(value string) int {
 	r, _ := strconv.Atoi(value)
 	return r
@@ -129,6 +234,7 @@
 
 func (c *Config) fetch(path string, data interface{}) error {
 	resp, err := http.Get(c.connect + path)
+
 	if err != nil {
 		return err
 	}
@@ -136,5 +242,10 @@
 	defer resp.Body.Close()
 	decoder := json.NewDecoder(resp.Body)
 	err = decoder.Decode(data)
+	log.WithFields(logrus.Fields{
+		"path":   path,
+		"resp":   data,
+		"status": resp.Status,
+	}).Debug("Received data from XOS")
 	return err
 }
diff --git a/sadisServer.go b/sadisServer.go
index b2c56ec..fcb1cf4 100644
--- a/sadisServer.go
+++ b/sadisServer.go
@@ -21,21 +21,21 @@
 
 	"github.com/sirupsen/logrus"
 
+	lkh "github.com/gfremex/logrus-kafka-hook"
 	"github.com/gorilla/mux"
 	"github.com/kelseyhightower/envconfig"
-	lkh "github.com/gfremex/logrus-kafka-hook"
 )
 
 const appName = "SADISSERVER"
 
 type Config struct {
-	Port         int    `default:"8000" desc:"port on which to listen for requests"`
-	Xos		     string `default:"127.0.0.1:8181" desc:"connection string with which to connect to XOS"`
-	Username     string `default:"admin@opencord.org" desc:"username with which to connect to XOS"`
-	Password     string `default:"letmein" desc:"password with which to connect to XOS"`
-	LogLevel     string `default:"info" envconfig:"LOG_LEVEL" desc:"detail level for logging"`
-	LogFormat    string `default:"text" envconfig:"LOG_FORMAT" desc:"log output format, text or json"`
-	KafkaBroker  string `default:"" desc:"url of the kafka broker"`
+	Port        int    `default:"8000" desc:"port on which to listen for requests"`
+	Xos         string `default:"127.0.0.1:8181" desc:"connection string with which to connect to XOS"`
+	Username    string `default:"admin@opencord.org" desc:"username with which to connect to XOS"`
+	Password    string `default:"letmein" desc:"password with which to connect to XOS"`
+	LogLevel    string `default:"info" envconfig:"LOG_LEVEL" desc:"detail level for logging"`
+	LogFormat   string `default:"text" envconfig:"LOG_FORMAT" desc:"log output format, text or json"`
+	KafkaBroker string `default:"" desc:"url of the kafka broker"`
 
 	connect string
 }
@@ -45,7 +45,7 @@
 var appFlags = flag.NewFlagSet("", flag.ContinueOnError)
 var config Config
 
-func init()  {
+func init() {
 	config = Config{}
 	appFlags.Usage = func() {
 		envconfig.Usage(appName, &config)
@@ -106,20 +106,19 @@
 
 func main() {
 
-
-
 	log.WithFields(logrus.Fields{
-		"PORT": config.Port,
-		"XOS": config.Xos,
-		"USERNAME": config.Username,
-		"PASSWORD": config.Password,
-		"LOG_LEVEL": config.LogLevel,
-		"LOG_FORMAT": config.LogFormat,
+		"PORT":         config.Port,
+		"XOS":          config.Xos,
+		"USERNAME":     config.Username,
+		"PASSWORD":     config.Password,
+		"LOG_LEVEL":    config.LogLevel,
+		"LOG_FORMAT":   config.LogFormat,
 		"KAFKA_BROKER": config.KafkaBroker,
 	}).Infof(`Sadis-server started`)
 
 	router := mux.NewRouter()
 	router.HandleFunc("/subscriber/{id}", config.getSubscriberHandler)
+	router.HandleFunc("/bandwidthprofiles/{id}", config.getBandwidthProfileHandler)
 	http.Handle("/", router)
 
 	connectStringFormat := "http://%s:%s@%s"
diff --git a/sadisTypes.go b/sadisTypes.go
index b28c1f7..5bf1213 100644
--- a/sadisTypes.go
+++ b/sadisTypes.go
@@ -27,24 +27,29 @@
   ONOS SADIS subscriber format
 */
 type sadisSubscriber struct {
-	ID        string `json:"id"`
-	CTag      int16  `json:"cTag"`
-	STag      int16  `json:"sTag"`
-	NasPortID string `json:"nasPortId"`
-	CircuitID string `json:"circuitId"`
-	RemoteID  string `json:"remoteId"`
+	ID                         string `json:"id"`
+	CTag                       int16  `json:"cTag"`
+	STag                       int16  `json:"sTag"`
+	NasPortID                  string `json:"nasPortId"`
+	CircuitID                  string `json:"circuitId"`
+	RemoteID                   string `json:"remoteId"`
+	UpstreamBandwidthProfile   string `json:"upstreamBandwidthProfile"`
+	DownstreamBandwidthProfile string `json:"downstreamBandwidthProfile"`
 }
 
 /*
   XOS RCORD subscriber format
 */
 type subscriber struct {
-	CTag            int16  `json:"c_tag"`
-	STag            int16  `json:"s_tag"`
-	OnuSerialNumber string `json:"onu_device"`
-	NasPortID       string `json:"nas_port_id"`
-	CircuitID       string `json:"circuit_id"`
-	RemoteID        string `json:"remote_id"`
+	ID                         int    `json:"id"`
+	CTag                       int16  `json:"c_tag"`
+	STag                       int16  `json:"s_tag"`
+	OnuSerialNumber            string `json:"onu_device"`
+	NasPortID                  string `json:"nas_port_id"`
+	CircuitID                  string `json:"circuit_id"`
+	RemoteID                   string `json:"remote_id"`
+	UpstreamBandwidthProfile   int    `json:"upstream_bps_id"`
+	DownstreamBandwidthProfile int    `json:"downstream_bps_id"`
 }
 
 type subscribers struct {
@@ -52,6 +57,22 @@
 }
 
 /*
+  XOS BandwidthProfile format
+*/
+type bandwidthprofile struct {
+	Name string `json:"name"`
+	Cir  int    `json:"cir"`
+	Cbs  int    `json:"cbs"`
+	Eir  int    `json:"eir"`
+	Ebs  int    `json:"ebs"`
+	Air  int    `json:"air"`
+}
+
+type bandwidthprofiles struct {
+	Profiles []*bandwidthprofile `json:"items"`
+}
+
+/*
   {
     "id" : "10.1.1.1:9191",
     "hardwareIdentifier" : "de:ad:be:ef:ba:11",
@@ -83,3 +104,16 @@
 type oltDevices struct {
 	OltDevices []*oltDevice `json:"items"`
 }
+
+/*
+  ONOS SADIS bandwidth profile format
+*/
+
+type sadisBandwidthProfile struct {
+	ID  string `json:"id"`
+	Cir int    `json:"cir"`
+	Cbs int    `json:"cbs"`
+	Eir int    `json:"eir"`
+	Ebs int    `json:"ebs"`
+	Air int    `json:"air"`
+}