[SEBA-854] Add new API and modify existing

Change-Id: Iea9fd003d122f58a4d45c79d806a2011087d1740
diff --git a/main.go b/main.go
index c0d7346..bc0e3ba 100644
--- a/main.go
+++ b/main.go
@@ -15,22 +15,24 @@
 package main
 
 import (
+	importer "./proto"
+	"crypto/tls"
+	"encoding/json"
 	"fmt"
+	"github.com/Shopify/sarama"
+	log "github.com/Sirupsen/logrus"
+	empty "github.com/golang/protobuf/ptypes/empty"
+	"golang.org/x/net/context"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+	"io/ioutil"
 	"net"
 	"net/http"
 	"os"
 	"os/signal"
-	"io/ioutil"
-	"github.com/Shopify/sarama"
-	"google.golang.org/grpc"
-	"golang.org/x/net/context"
-	"crypto/tls"
-	empty "github.com/golang/protobuf/ptypes/empty"
-        importer "./proto"
-        log "github.com/Sirupsen/logrus"
-	"time"
-	"encoding/json"
 	"path"
+	"time"
 )
 
 //globals
@@ -43,83 +45,156 @@
 
 var DataProducer sarama.AsyncProducer
 
-var    vendor_default_events = map[string][]string{
-        "edgecore": {"ResourceAdded","ResourceRemoved","Alert"},
-    }
-var redfish_services = [...]string{"/Chassis", "/Systems","/EthernetSwitches"}
+var vendor_default_events = map[string][]string{
+	"edgecore": {"ResourceAdded", "ResourceRemoved", "Alert"},
+}
+var redfish_services = [...]string{"/Chassis", "/Systems", "/EthernetSwitches"}
 var pvmount = os.Getenv("DEVICE_MANAGEMENT_PVMOUNT")
 var subscriptionListPath string
 
-type scheduler struct  {
-	getdata time.Ticker
-	quit chan bool
+type scheduler struct {
+	getdata *time.Ticker
+	quit    chan bool
 }
 
-type device struct  {
-	Subscriptions	map[string]string	`json:"ss"`
-	Freq		uint32			`json:"freq"`
-	Datacollector	scheduler		`json:"-"`
-	Freqchan	chan uint32		`json:"-"`
-	Vendor		string			`json:"vendor"`
-	Protocol	string			`json:"protocol"`
+type device struct {
+	Subscriptions map[string]string `json:"ss"`
+	Freq          uint32            `json:"freq"`
+	Datacollector scheduler         `json:"-"`
+	Freqchan      chan uint32       `json:"-"`
+	Vendor        string            `json:"vendor"`
+	Protocol      string            `json:"protocol"`
 }
 
 type Server struct {
-	devicemap	map[string]*device
-	gRPCserver	*grpc.Server
-	dataproducer	sarama.AsyncProducer
-	httpclient	*http.Client
-	devicechan	chan *importer.DeviceInfo
+	devicemap    map[string]*device
+	gRPCserver   *grpc.Server
+	dataproducer sarama.AsyncProducer
+	httpclient   *http.Client
+	devicechan   chan *importer.DeviceInfo
 }
 
-func (s *Server) GetEventList(c context.Context, info *importer.DeviceInfo) (*importer.SupportedEventList, error) {
+func (s *Server) ClearCurrentEventList(c context.Context, info *importer.Device) (*empty.Empty, error) {
+	fmt.Println("Received GetCurrentEventList\n")
+	ip_address := info.IpAddress
+	_, found := s.devicemap[ip_address]
+	if !found {
+		return nil, status.Errorf(codes.NotFound, "Device not registered")
+	}
+	f := get_subscription_list(ip_address)
+	for event, _ := range s.devicemap[ip_address].Subscriptions {
+		rtn := s.remove_subscription(ip_address, event, f)
+		if !rtn {
+			log.WithFields(log.Fields{
+				"Event": event,
+			}).Info("Error removing event")
+		}
+	}
+	if f != nil {
+		f.Close()
+	}
+	return &empty.Empty{}, nil
+}
+
+func (s *Server) GetCurrentEventList(c context.Context, info *importer.Device) (*importer.EventList, error) {
+	fmt.Println("Received ClearCurrentEventList\n")
+	_, found := s.devicemap[info.IpAddress]
+	if !found {
+		return nil, status.Errorf(codes.NotFound, "Device not registered")
+	}
+	currentevents := new(importer.EventList)
+	for event, _ := range s.devicemap[info.IpAddress].Subscriptions {
+		currentevents.Events = append(currentevents.Events, event)
+	}
+	return currentevents, nil
+}
+
+func (s *Server) GetEventList(c context.Context, info *importer.VendorInfo) (*importer.EventList, error) {
 	fmt.Println("Received GetEventList\n")
-	eventstobesubscribed:= new(importer.SupportedEventList)
+	_, found := vendor_default_events[info.Vendor]
+	if !found {
+		return nil, status.Errorf(codes.NotFound, "Invalid Vendor Provided")
+	}
+	eventstobesubscribed := new(importer.EventList)
 	eventstobesubscribed.Events = vendor_default_events[info.Vendor]
 	return eventstobesubscribed, nil
 }
 
-func (s *Server) SetFrequency(c context.Context,  info *importer.DeviceInfo) (*empty.Empty, error) {
+func (s *Server) SetFrequency(c context.Context, info *importer.FreqInfo) (*empty.Empty, error) {
 	fmt.Println("Received SetFrequency")
+	_, found := s.devicemap[info.IpAddress]
+	if !found {
+		return nil, status.Errorf(codes.NotFound, "Device not registered")
+	}
+
 	s.devicemap[info.IpAddress].Freqchan <- info.Frequency
 	return &empty.Empty{}, nil
 }
 
-func (s *Server) SubsrcribeGivenEvents(c context.Context,  subeventlist *importer.EventList) (*empty.Empty, error) {
+func (s *Server) SubsrcribeGivenEvents(c context.Context, subeventlist *importer.GivenEventList) (*empty.Empty, error) {
 	fmt.Println("Received SubsrcribeEvents\n")
 	//Call API to subscribe events
 	ip_address := subeventlist.EventIpAddress
+	_, found := s.devicemap[ip_address]
+	if !found {
+		return nil, status.Errorf(codes.NotFound, "Device not registered")
+	}
+	if len(subeventlist.Events) <= 0 {
+		return nil, status.Errorf(codes.InvalidArgument, "Event list is empty")
+	}
 	f := get_subscription_list(ip_address)
 	for _, event := range subeventlist.Events {
 		if _, ok := s.devicemap[ip_address].Subscriptions[event]; !ok {
-			s.add_subscription(ip_address, event, f)
+			rtn := s.add_subscription(ip_address, event, f)
+			if !rtn {
+				log.WithFields(log.Fields{
+					"Event": event,
+				}).Info("Error adding  event")
+			}
 		} else {
 			log.WithFields(log.Fields{
 				"Event": event,
-				}).Info("Already Subscribed")
+			}).Info("Already Subscribed")
 		}
 	}
-	if f != nil { f.Close() }
+	if f != nil {
+		f.Close()
+	}
 	return &empty.Empty{}, nil
 }
 
-func (s *Server) UnSubsrcribeGivenEvents(c context.Context,  unsubeventlist *importer.EventList) (*empty.Empty, error) {
+func (s *Server) UnSubsrcribeGivenEvents(c context.Context, unsubeventlist *importer.GivenEventList) (*empty.Empty, error) {
 	fmt.Println("Received UnSubsrcribeEvents\n")
 	ip_address := unsubeventlist.EventIpAddress
+	_, found := s.devicemap[ip_address]
+	if !found {
+		return nil, status.Errorf(codes.NotFound, "Device not registered")
+	}
+
+	if len(unsubeventlist.Events) <= 0 {
+		return nil, status.Errorf(codes.InvalidArgument, "Event list is empty")
+	}
 	//Call API to unsubscribe events
 	f := get_subscription_list(ip_address)
 	for _, event := range unsubeventlist.Events {
 		if _, ok := s.devicemap[ip_address].Subscriptions[event]; ok {
-			s.remove_subscription(ip_address, event, f)
-                } else {
-                                log.WithFields(log.Fields{
-                                  "Event": event,
-                                }).Info("was not Subscribed")
-                        }
-        }
-	if f != nil { f.Close() }
+			rtn := s.remove_subscription(ip_address, event, f)
+			if !rtn {
+				log.WithFields(log.Fields{
+					"Event": event,
+				}).Info("Error removing event")
+			}
+		} else {
+			log.WithFields(log.Fields{
+				"Event": event,
+			}).Info("was not Subscribed")
+		}
+	}
+	if f != nil {
+		f.Close()
+	}
 
-       return &empty.Empty{}, nil
+	return &empty.Empty{}, nil
 }
 
 func (s *Server) collect_data(ip_address string) {
@@ -130,8 +205,10 @@
 		select {
 		case freq := <-freqchan:
 			ticker.Stop()
-			ticker = *time.NewTicker(time.Duration(freq) * time.Second)
-		case  err := <-s.dataproducer.Errors():
+			if freq > 0 {
+				ticker = time.NewTicker(time.Duration(freq) * time.Second)
+			}
+		case err := <-s.dataproducer.Errors():
 			fmt.Println("Failed to produce message:", err)
 		case <-ticker.C:
 			for _, service := range redfish_services {
@@ -143,9 +220,9 @@
 						b := []byte(str)
 						msg := &sarama.ProducerMessage{Topic: importerTopic, Value: sarama.StringEncoder(b)}
 						select {
-						// TODO: this is blocking, maybe a timer?
-						case  s.dataproducer.Input() <- msg:
+						case s.dataproducer.Input() <- msg:
 							fmt.Println("Produce message")
+						default:
 						}
 					}
 				}
@@ -158,22 +235,32 @@
 	}
 }
 
-func (s *Server) SendDeviceInfo(c context.Context,  info *importer.DeviceInfo) (*empty.Empty, error) {
-	d := device {
+func (s *Server) SendDeviceInfo(c context.Context, info *importer.DeviceInfo) (*empty.Empty, error) {
+	d := device{
 		Subscriptions: make(map[string]string),
-		Freq: info.Frequency,
+		Freq:          info.Frequency,
 		Datacollector: scheduler{
-			getdata: *time.NewTicker(time.Duration(info.Frequency) * time.Second),
-			quit: make(chan bool),
+			getdata: time.NewTicker(time.Duration(info.Frequency) * time.Second),
+			quit:    make(chan bool),
 		},
 		Freqchan: make(chan uint32),
-		Vendor: info.Vendor,
+		Vendor:   info.Vendor,
 		Protocol: info.Protocol,
 	}
-        //default_events := [...]string{}
+	_, found := s.devicemap[info.IpAddress]
+	if found {
+		return nil, status.Errorf(codes.AlreadyExists, "Device Already registered")
+	}
+
+	_, vendorfound := vendor_default_events[info.Vendor]
+	if !vendorfound {
+		return nil, status.Errorf(codes.NotFound, "Vendor Not Found")
+	}
+
+	//default_events := [...]string{}
 	s.devicemap[info.IpAddress] = &d
 	fmt.Printf("size of devicemap %d\n", len(s.devicemap))
-	ip_address:= info.IpAddress
+	ip_address := info.IpAddress
 	fmt.Printf("Configuring  %s\n", ip_address)
 	// call subscription function with info.IpAddress
 
@@ -183,18 +270,20 @@
 	for _, event := range default_events {
 		s.add_subscription(ip_address, event, f)
 	}
-	if f != nil { f.Close() }
+	if f != nil {
+		f.Close()
+	}
 	go s.collect_data(ip_address)
 	return &empty.Empty{}, nil
 }
 
 func NewGrpcServer(grpcport string) (l net.Listener, g *grpc.Server, e error) {
-        fmt.Printf("Listening %s\n", grpcport)
-        g = grpc.NewServer()
-        l, e = net.Listen("tcp", grpcport)
-        return
+	fmt.Printf("Listening %s\n", grpcport)
+	g = grpc.NewServer()
+	l, e = net.Listen("tcp", grpcport)
+	return
 }
-func (s *Server) startgrpcserver()error {
+func (s *Server) startgrpcserver() error {
 	fmt.Println("starting gRPC Server")
 	grpcport := ":50051"
 	listener, gserver, err := NewGrpcServer(grpcport)
@@ -211,8 +300,8 @@
 	return nil
 
 }
-func (s *Server) kafkaCloseProducer(){
-	if err :=s.dataproducer.Close(); err != nil {
+func (s *Server) kafkaCloseProducer() {
+	if err := s.dataproducer.Close(); err != nil {
 		panic(err)
 	}
 
@@ -220,7 +309,7 @@
 func (s *Server) kafkaInit() {
 	fmt.Println("Starting kafka init to Connect to broker: ")
 	config := sarama.NewConfig()
-        config.Producer.RequiredAcks = sarama.WaitForAll
+	config.Producer.RequiredAcks = sarama.WaitForAll
 	config.Producer.Retry.Max = 10
 	producer, err := sarama.NewAsyncProducer([]string{"cord-kafka.default.svc.cluster.local:9092"}, config)
 	if err != nil {
@@ -233,19 +322,19 @@
 	signals := make(chan os.Signal, 1)
 	signal.Notify(signals, os.Interrupt)
 
-        fmt.Println(" IN Handle Event  ")
-	if(r.Method ==  "POST"){
+	fmt.Println(" IN Handle Event  ")
+	if r.Method == "POST" {
 		Body, err := ioutil.ReadAll(r.Body)
 		if err != nil {
-			fmt.Println("Error getting HTTP data",err)
+			fmt.Println("Error getting HTTP data", err)
 		}
-		defer  r.Body.Close()
+		defer r.Body.Close()
 		fmt.Println("Received Event Message ")
-		fmt.Printf("%s\n",Body)
-		message :=&sarama.ProducerMessage{
-                        Topic: importerTopic,
-                        Value: sarama.StringEncoder(Body),
-                }
+		fmt.Printf("%s\n", Body)
+		message := &sarama.ProducerMessage{
+			Topic: importerTopic,
+			Value: sarama.StringEncoder(Body),
+		}
 		s.dataproducer.Input() <- message
 	}
 }
@@ -274,7 +363,7 @@
 					d := device{}
 					json.Unmarshal(b, &d)
 					s.devicemap[ip] = &d
-					s.devicemap[ip].Datacollector.getdata = *time.NewTicker(time.Duration(s.devicemap[ip].Freq) * time.Second)
+					s.devicemap[ip].Datacollector.getdata = time.NewTicker(time.Duration(s.devicemap[ip].Freq) * time.Second)
 					s.devicemap[ip].Datacollector.quit = make(chan bool)
 					s.devicemap[ip].Freqchan = make(chan uint32)
 					go s.collect_data(ip)
@@ -285,14 +374,14 @@
 }
 
 func init() {
-        Formatter := new(log.TextFormatter)
-        Formatter.TimestampFormat = "02-01-2006 15:04:05"
-        Formatter.FullTimestamp = true
-        log.SetFormatter(Formatter)
+	Formatter := new(log.TextFormatter)
+	Formatter.TimestampFormat = "02-01-2006 15:04:05"
+	Formatter.FullTimestamp = true
+	log.SetFormatter(Formatter)
 	fmt.Println("Connecting to broker: ")
 	fmt.Println("Listening to  http server")
-        log.Info("log Connecting to broker:")
-        log.Info("log Listening to  http server ")
+	log.Info("log Connecting to broker:")
+	log.Info("log Listening to  http server ")
 	//sarama.Logger = log.New()
 }
 
@@ -300,7 +389,7 @@
 	if pvmount == "" {
 		return nil
 	}
-	f, err := os.OpenFile(subscriptionListPath + "/" + ip, os.O_CREATE|os.O_RDWR, 0664)
+	f, err := os.OpenFile(subscriptionListPath+"/"+ip, os.O_CREATE|os.O_RDWR, 0664)
 	if err != nil {
 		fmt.Println(err)
 	}
@@ -313,16 +402,15 @@
 	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
 	client := &http.Client{
 		Timeout: 10 * time.Second,
-		}
+	}
 
-	s := Server {
-		devicemap:	make(map[string]*device),
-		devicechan:	make(chan *importer.DeviceInfo),
-		httpclient:	client,
+	s := Server{
+		devicemap:  make(map[string]*device),
+		devicechan: make(chan *importer.DeviceInfo),
+		httpclient: client,
 	}
 
 	s.kafkaInit()
-//TODO: check if we should keep this as goroutines?
 	go s.runServer()
 	go s.startgrpcserver()