seba-343 - added preprovision api

Change-Id: I5760e059154e2966ea2545b48306fce78cbe4daf
diff --git a/api/abstract_olt_api.proto b/api/abstract_olt_api.proto
index 6c5304b..f592b38 100644
--- a/api/abstract_olt_api.proto
+++ b/api/abstract_olt_api.proto
@@ -78,16 +78,28 @@
    int32 OntNumber=4;
    string SerialNumber=5;
 }
+message PreProvisionOntMessage{
+   string CLLI=1;
+   int32 SlotNumber=2;
+   int32 PortNumber=3;
+   int32 OntNumber=4;
+   uint32 STag=5;
+   uint32 CTag=6;
+   string NasPortID=7;
+   string CircuitID=8;
+   string TechProfile=9;
+   string SpeedProfile=10;
+}
 message AddOntFullMessage{
    string CLLI=1;
    int32 SlotNumber=2;
    int32 PortNumber=3;
    int32 OntNumber=4;
    string SerialNumber=5;
-   uint32 STag=7;
-   uint32 CTag=8;
-   string NasPortID=9;
-   string CircuitID=10;
+   uint32 STag=6;
+   uint32 CTag=7;
+   string NasPortID=8;
+   string CircuitID=9;
 }
 message AddOntReturn{
    bool Success=1;
@@ -147,6 +159,18 @@
 	 body:"*"
       };
    }
+   rpc PreProvisionOnt(PreProvisionOntMessage) returns (AddOntReturn) {
+      option(google.api.http) = {
+         post:"/v1/PreProvsionOnt"
+	 body:"*"
+      };
+   }
+   rpc ActivateSerial(AddOntMessage) returns (AddOntReturn) {
+      option(google.api.http) = {
+         post:"/v1/ActivateSerial"
+	 body:"*"
+      };
+   }
    rpc ProvisionOnt(AddOntMessage) returns (AddOntReturn) {
       option(google.api.http) = {
          post:"/v1/ProvsionOnt"
diff --git a/api/handler.go b/api/handler.go
index 4e1ef61..76d637e 100644
--- a/api/handler.go
+++ b/api/handler.go
@@ -148,6 +148,37 @@
 }
 
 /*
+PreProvisionOnt - provisions ont using sTag,cTag,NasPortID, and CircuitID passed in
+*/
+func (s *Server) PreProvisionOnt(ctx context.Context, in *PreProvisionOntMessage) (*AddOntReturn, error) {
+	clli := in.GetCLLI()
+	slotNumber := int(in.GetSlotNumber())
+	portNumber := int(in.GetPortNumber())
+	ontNumber := int(in.GetOntNumber())
+	cTag := in.GetCTag()
+	sTag := in.GetSTag()
+	nasPortID := in.GetNasPortID()
+	circuitID := in.GetCircuitID()
+	techProfile := in.GetTechProfile()
+	speedProfile := in.GetSpeedProfile()
+	success, err := impl.PreProvisionOnt(clli, slotNumber, portNumber, ontNumber, cTag, sTag, nasPortID, circuitID, techProfile, speedProfile)
+	return &AddOntReturn{Success: success}, err
+}
+
+/*
+ActivateSerial provisions an ONT on a specific Chassis/LineCard/Port
+*/
+func (s *Server) ActivateSerial(ctx context.Context, in *AddOntMessage) (*AddOntReturn, error) {
+	clli := in.GetCLLI()
+	slotNumber := int(in.GetSlotNumber())
+	portNumber := int(in.GetPortNumber())
+	ontNumber := int(in.GetOntNumber())
+	serialNumber := in.GetSerialNumber()
+	success, err := impl.ActivateSerial(clli, slotNumber, portNumber, ontNumber, serialNumber)
+	return &AddOntReturn{Success: success}, err
+}
+
+/*
 DeleteOnt - deletes a previously provision ont
 */
 func (s *Server) DeleteOnt(ctx context.Context, in *DeleteOntMessage) (*DeleteOntReturn, error) {
diff --git a/client/main.go b/client/main.go
index 79b29c5..4f981bd 100644
--- a/client/main.go
+++ b/client/main.go
@@ -37,6 +37,8 @@
 	addOlt := flag.Bool("s", false, "addOlt?")
 	provOnt := flag.Bool("o", false, "provisionOnt?")
 	provOntFull := flag.Bool("f", false, "provsionOntFull?")
+	preProvOnt := flag.Bool("p", false, "preProvisionOnt?")
+	activateSerial := flag.Bool("a", false, "activateSerial?")
 	deleteOnt := flag.Bool("d", false, "deleteOnt")
 	output := flag.Bool("output", false, "dump output")
 	reflow := flag.Bool("reflow", false, "reflow provisioning tosca")
@@ -75,6 +77,11 @@
 	circuitID := flag.String("circuit_id", "", "CircuitID for ont")
 	/*END PROVISION ONT FULL EXTRA FLAGS*/
 
+	/*PREPROVISION ONT EXTRA FLAGS*/
+	techProfile := flag.String("tech_profile", "", "Tech Profile")
+	speedProfile := flag.String("speed_profile", "", "Speed Profile")
+	/*END PREPROVISION ONT EXTRA FLAGS*/
+
 	/* ECHO FLAGS */
 	message := flag.String("message", "ping", "message to be echoed back")
 	/*END ECHO FLAGS*/
@@ -97,7 +104,7 @@
 		}
 	}
 
-	cmdFlags := []*bool{echo, addOlt, update, create, provOnt, provOntFull, deleteOnt, output, reflow, fullInventory, inventory}
+	cmdFlags := []*bool{echo, addOlt, update, create, provOnt, preProvOnt, activateSerial, provOntFull, deleteOnt, output, reflow, fullInventory, inventory}
 	cmdCount := 0
 	for _, flag := range cmdFlags {
 		if *flag {
@@ -157,10 +164,14 @@
 		provisionONT(c, clli, slot, port, ont, serial)
 	} else if *provOntFull {
 		provisionONTFull(c, clli, slot, port, ont, serial, stag, ctag, nasPort, circuitID)
+	} else if *preProvOnt {
+		preProvisionOnt(c, clli, slot, port, ont, stag, ctag, nasPort, circuitID, techProfile, speedProfile)
+	} else if *activateSerial {
+		activateSerialNumber(c, clli, slot, port, ont, serial)
 	} else if *echo {
 		ping(c, *message)
 	} else if *output {
-		Output(c)
+		doOutput(c)
 	} else if *deleteOnt {
 		deleteONT(c, clli, slot, port, ont, serial)
 	} else if *reflow {
@@ -191,7 +202,7 @@
 func (a *Authentication) RequireTransportSecurity() bool {
 	return true
 }
-func Output(c api.AbstractOLTClient) error {
+func doOutput(c api.AbstractOLTClient) error {
 	response, err := c.Output(context.Background(), &api.OutputMessage{Something: "wtf"})
 	if err != nil {
 		fmt.Printf("Error when calling Echo: %s", err)
@@ -287,6 +298,42 @@
 	log.Printf("Response from server: %t", res.GetSuccess())
 	return nil
 }
+func preProvisionOnt(c api.AbstractOLTClient, clli *string, slot *uint, port *uint, ont *uint, stag *uint, ctag *uint, nasPort *string, circuitID *string, techProfile *string, speedProfile *string) error {
+	fmt.Println("clli", *clli)
+	fmt.Println("slot", *slot)
+	fmt.Println("port", *port)
+	fmt.Println("ont", *ont)
+	fmt.Println("stag", *stag)
+	fmt.Println("ctag", *ctag)
+	fmt.Println("nasPort", *nasPort)
+	fmt.Println("circuitID", *circuitID)
+	fmt.Println("tech_profile", *techProfile)
+	fmt.Println("speed_profile", *speedProfile)
+	res, err := c.PreProvisionOnt(context.Background(), &api.PreProvisionOntMessage{CLLI: *clli, SlotNumber: int32(*slot), PortNumber: int32(*port),
+		OntNumber: int32(*ont), STag: uint32(*stag), CTag: uint32(*ctag), TechProfile: *techProfile, SpeedProfile: *speedProfile})
+	if err != nil {
+		debug.PrintStack()
+		fmt.Printf("Error when calling ProvsionOnt %s", err)
+		return err
+	}
+	log.Printf("Response from server: %t", res.GetSuccess())
+	return nil
+}
+func activateSerialNumber(c api.AbstractOLTClient, clli *string, slot *uint, port *uint, ont *uint, serial *string) error {
+	fmt.Println("clli", *clli)
+	fmt.Println("slot", *slot)
+	fmt.Println("port", *port)
+	fmt.Println("ont", *ont)
+	fmt.Println("serial", *serial)
+	res, err := c.ActivateSerial(context.Background(), &api.AddOntMessage{CLLI: *clli, SlotNumber: int32(*slot), PortNumber: int32(*port), OntNumber: int32(*ont), SerialNumber: *serial})
+	if err != nil {
+		debug.PrintStack()
+		fmt.Printf("Error when calling ActivateSerial %s", err)
+		return err
+	}
+	log.Printf("Response from server: %t", res.GetSuccess())
+	return nil
+}
 func provisionONTFull(c api.AbstractOLTClient, clli *string, slot *uint, port *uint, ont *uint, serial *string, stag *uint, ctag *uint, nasPort *string, circuitID *string) error {
 	fmt.Println("clli", *clli)
 	fmt.Println("slot", *slot)
@@ -413,6 +460,28 @@
 	 -circuit_id CIRCUIT_ID
 	 e.g. ./client -server=localhost:7777 -f -clli=MY_CLLI -slot=1 -port=1 -ont=22 -serial=aer900jasdf -stag=33 -ctag=104 -nas_port="pon 1/1/1/3:1.1" -circuit_id="CLLI 1/1/1/13:1.1"
 
+   -p pre-provision ont - same as -o above but allows explicit set of s/c vlans , NasPortID and CircuitID and NO serial number
+      params:
+	 -clli CLLI_NAME
+	 -slot SLOT_NUMBER [1-16]
+	 -port OLT_PORT_NUMBER [1-16]
+	 -ont ONT_NUMBER [1-64]
+	 -stag S_TAG
+	 -ctag C_TAG
+	 -nas_port NAS_PORT_ID
+	 -circuit_id CIRCUIT_ID
+	 -tech_profile TECH_PROFILE
+	 -speed_profile SPEED_PROFILE
+	 e.g. ./client -server=localhost:7777 -p -clli=MY_CLLI -slot=1 -port=1 -ont=22  -stag=33 -ctag=104 -nas_port="pon 1/1/1/3:1.1" -circuit_id="CLLI 1/1/1/13:1.1 -tech_profile=Business -speed_profile=1GB
+   -a activate serial  - adds ont to whitelist in XOS  on a specific port on a specific olt chassis based on abstract -> phyisical mapping - must be preProvisioned
+      params:
+	 -clli CLLI_NAME
+	 -slot SLOT_NUMBER [1-16]
+	 -port OLT_PORT_NUMBER [1-16]
+	 -ont ONT_NUMBER [1-64]
+	 -serial ONT_SERIAL_NUM
+	 e.g. ./client -server=localhost:7777 -a -clli=MY_CLLI -slot=1 -port=1 -ont=22 -serial=aer900jasdf
+
    -d delete ont - removes ont from service
       params:
 	 -clli CLLI_NAME
@@ -435,7 +504,7 @@
 
     -full_inventory - returns a json document that describes all currently provisioned pods
          e.g. ./client -full_inventory
-        
+
 	 `
 
 	fmt.Println(output)
diff --git a/internal/pkg/impl/ont.go b/internal/pkg/impl/ont.go
index 932ee5e..71094cd 100644
--- a/internal/pkg/impl/ont.go
+++ b/internal/pkg/impl/ont.go
@@ -24,7 +24,7 @@
 )
 
 /*
-ProvsionOnt - provisions ont using sTag,cTag,NasPortID, and CircuitID generated internally
+ProvisionOnt - provisions ont using sTag,cTag,NasPortID, and CircuitID generated internally
 */
 func ProvisionOnt(clli string, slotNumber int, portNumber int, ontNumber int, serialNumber string) (bool, error) {
 	myChan := getSyncChannel()
@@ -42,7 +42,43 @@
 }
 
 /*
-ProvsionOntFull - provisions ont using sTag,cTag,NasPortID, and CircuitID passed in
+ActivateSerial - provisions ont using sTag,cTag,NasPortID, and CircuitID generated internally
+*/
+func ActivateSerial(clli string, slotNumber int, portNumber int, ontNumber int, serialNumber string) (bool, error) {
+	myChan := getSyncChannel()
+	<-myChan
+	defer done(myChan, true)
+	chassisMap := models.GetChassisMap()
+	chassisHolder := (*chassisMap)[clli]
+	if chassisHolder == nil {
+		errString := fmt.Sprintf("There is no chassis with CLLI of %s", clli)
+		return false, errors.New(errString)
+	}
+	err := chassisHolder.AbstractChassis.ActivateSerial(slotNumber, portNumber, ontNumber, serialNumber)
+	isDirty = true
+	return true, err
+}
+
+/*
+PreProvisionOnt - provisions ont using sTag,cTag,NasPortID, and CircuitID passed in
+*/
+func PreProvisionOnt(clli string, slotNumber int, portNumber int, ontNumber int, cTag uint32, sTag uint32, nasPortID string, circuitID string, techProfile string, speedProfile string) (bool, error) {
+	myChan := getSyncChannel()
+	<-myChan
+	defer done(myChan, true)
+	chassisMap := models.GetChassisMap()
+	chassisHolder := (*chassisMap)[clli]
+	if chassisHolder == nil {
+		errString := fmt.Sprintf("There is no chassis with CLLI of %s", clli)
+		return false, errors.New(errString)
+	}
+	err := chassisHolder.AbstractChassis.PreProvisonONT(slotNumber, portNumber, ontNumber, cTag, sTag, nasPortID, circuitID, techProfile, speedProfile)
+	isDirty = true
+	return true, err
+}
+
+/*
+ProvisionOntFull - provisions ont using sTag,cTag,NasPortID, and CircuitID passed in
 */
 func ProvisionOntFull(clli string, slotNumber int, portNumber int, ontNumber int, serialNumber string, cTag uint32, sTag uint32, nasPortID string, circuitID string) (bool, error) {
 	myChan := getSyncChannel()
diff --git a/models/abstract/chassis.go b/models/abstract/chassis.go
index 2b3231b..929f247 100644
--- a/models/abstract/chassis.go
+++ b/models/abstract/chassis.go
@@ -63,6 +63,41 @@
 
 	return nextPort, nil
 }
+func (chassis *Chassis) PreProvisonONT(slotNumber int, portNumber int, ontNumber int, cTag uint32, sTag uint32, nasPortID string, circuitID string, techProfile string, speedProfile string) error {
+	if slotNumber > len(chassis.Slots) {
+		errorMsg := fmt.Sprintf("Invalid slot Number %d ", slotNumber)
+		return errors.New(errorMsg)
+	}
+	if portNumber > 16 {
+		errorMsg := fmt.Sprintf("Invalid port Number %d ", portNumber)
+		return errors.New(errorMsg)
+	}
+	if ontNumber > 64 {
+		errorMsg := fmt.Sprintf("Invalid ont Number %d ", ontNumber)
+		return errors.New(errorMsg)
+	}
+
+	err := chassis.Slots[slotNumber-1].Ports[portNumber-1].preProvisionOnt(ontNumber, cTag, sTag, nasPortID, circuitID, techProfile, speedProfile)
+	return err
+}
+func (chassis *Chassis) ActivateSerial(slotNumber int, portNumber int, ontNumber int, serialNumber string) error {
+	if slotNumber > len(chassis.Slots) {
+		errorMsg := fmt.Sprintf("Invalid slot Number %d ", slotNumber)
+		return errors.New(errorMsg)
+	}
+	if portNumber > 16 {
+		errorMsg := fmt.Sprintf("Invalid port Number %d ", portNumber)
+		return errors.New(errorMsg)
+	}
+	if ontNumber > 64 {
+		errorMsg := fmt.Sprintf("Invalid ont Number %d ", ontNumber)
+		return errors.New(errorMsg)
+	}
+
+	err := chassis.Slots[slotNumber-1].Ports[portNumber-1].activateSerial(ontNumber, serialNumber)
+	return err
+
+}
 func (chassis *Chassis) ActivateONTFull(slotNumber int, portNumber int, ontNumber int, serialNumber string, cTag uint32, sTag uint32, nasPortID string, circuitID string) error {
 	if slotNumber > len(chassis.Slots) {
 		errorMsg := fmt.Sprintf("Invalid slot Number %d ", slotNumber)
diff --git a/models/abstract/port.go b/models/abstract/port.go
index efb3054..da1e966 100644
--- a/models/abstract/port.go
+++ b/models/abstract/port.go
@@ -65,6 +65,30 @@
 	err := phyPort.ActivateOnt(ontNumber, ont.Svlan, ont.Cvlan, serialNumber, nasPortID, circuitID)
 	return err
 }
+func (port *Port) preProvisionOnt(ontNumber int, cTag uint32, sTag uint32, nasPortID string, circuitID string, techProfile string, speedProfile string) error {
+	slot := port.Parent
+
+	if port.PhysPort == nil {
+		chassis := slot.Parent
+		err := UnprovisonedPortError{oltNum: slot.Number, clli: chassis.CLLI, portNum: port.Number}
+		return &err
+	}
+	phyPort := port.PhysPort
+	err := phyPort.PreProvisionOnt(ontNumber, sTag, cTag, nasPortID, circuitID, techProfile, speedProfile)
+	return err
+}
+func (port *Port) activateSerial(ontNumber int, serialNumber string) error {
+	slot := port.Parent
+
+	if port.PhysPort == nil {
+		chassis := slot.Parent
+		err := UnprovisonedPortError{oltNum: slot.Number, clli: chassis.CLLI, portNum: port.Number}
+		return &err
+	}
+	phyPort := port.PhysPort
+	err := phyPort.ActivateSerial(ontNumber, serialNumber)
+	return err
+}
 func (port *Port) provisionOntFull(ontNumber int, serialNumber string, cTag uint32, sTag uint32, nasPortID string, circuitID string) error {
 	slot := port.Parent
 
diff --git a/models/physical/ont.go b/models/physical/ont.go
index 8c8949b..b262962 100644
--- a/models/physical/ont.go
+++ b/models/physical/ont.go
@@ -28,4 +28,6 @@
 	Active       bool     `json:",omitempty"`
 	NasPortID    string   `json:",omitempty"`
 	CircuitID    string   `json:",omitempty"`
+	TechProfile  string   `json:",omitempty"`
+	SpeedProfile string   `json:",omitempty"`
 }
diff --git a/models/physical/ponport.go b/models/physical/ponport.go
index 1064992..738d65e 100644
--- a/models/physical/ponport.go
+++ b/models/physical/ponport.go
@@ -65,6 +65,49 @@
 }
 
 /*
+PreProvisionOnt - passes ont information to chassis to make call to NEM to activate (whitelist) ont
+*/
+func (port *PONPort) PreProvisionOnt(number int, sVlan uint32, cVlan uint32, nasPortID string, circuitID string, techProfile string, speedProfile string) error {
+	slot := port.Parent
+	chassis := slot.Parent
+
+	if port.Onts[number-1].Active {
+		e := AllReadyActiveError{ontNumber: number, slotNum: slot.Number, ponportNum: port.Number, clli: chassis.CLLI}
+		return &e
+	}
+	ont := &port.Onts[number-1]
+	ont.Number = number
+	ont.Svlan = sVlan
+	ont.Cvlan = cVlan
+	ont.Parent = port
+	ont.NasPortID = nasPortID
+	ont.CircuitID = circuitID
+	ont.TechProfile = techProfile
+	ont.SpeedProfile = speedProfile
+	return nil
+}
+
+/*
+ActivateSerial - passes ont information to chassis to make call to NEM to activate (whitelist) ont assumes pre provisioned ont
+*/
+func (port *PONPort) ActivateSerial(number int, serialNumber string) error {
+	slot := port.Parent
+	chassis := slot.Parent
+
+	if port.Onts[number-1].Active {
+		e := AllReadyActiveError{ontNumber: number, slotNum: slot.Number, ponportNum: port.Number, clli: chassis.CLLI}
+		return &e
+	}
+	ont := port.Onts[number-1]
+	ont.SerialNumber = serialNumber
+	fmt.Println(ont)
+	port.Parent.Parent.provisionONT(ont)
+	port.Onts[number-1].Active = true
+	return nil
+
+}
+
+/*
 ActivateOnt - passes ont information to chassis to make call to NEM to activate (whitelist) ont
 */
 func (port *PONPort) ActivateOnt(number int, sVlan uint32, cVlan uint32, serialNumber string, nasPortID string, circuitID string) error {