VOL-1585: Support OLT Disable/Enable when no ONUs are connected to OLT.
          'go fmt'ed the code.

Change-Id: I30bd7ae0c898aea27b075c23b96668980382209d
diff --git a/adaptercore/device_handler.go b/adaptercore/device_handler.go
index 3abb764..f077eef 100644
--- a/adaptercore/device_handler.go
+++ b/adaptercore/device_handler.go
@@ -42,6 +42,7 @@
 type DeviceHandler struct {
 	deviceId      string
 	deviceType    string
+	adminState    string
 	device        *voltha.Device
 	coreProxy     *com.CoreProxy
 	AdapterProxy  *com.AdapterProxy
@@ -65,6 +66,7 @@
 	cloned := (proto.Clone(device)).(*voltha.Device)
 	dh.deviceId = cloned.Id
 	dh.deviceType = cloned.Type
+	dh.adminState = "up"
 	dh.device = cloned
 	dh.openOLT = adapter
 	dh.exitChannel = make(chan int, 1)
@@ -158,6 +160,21 @@
 		log.Errorw("Indications is nil", log.Fields{})
 		return
 	}
+	/* get device state */
+	device, err := dh.coreProxy.GetDevice(nil, dh.device.Id, dh.device.Id)
+	if err != nil || device == nil {
+		/*TODO: needs to handle error scenarios */
+		log.Errorw("Failed to fetch device info", log.Fields{"err": err})
+
+	}
+	// When the device is in DISABLED and Adapter container restarts, we need to
+	// rebuild the locally maintained admin state.
+	if device.AdminState == voltha.AdminState_DISABLED {
+		dh.lockDevice.Lock()
+		dh.adminState = "down"
+		dh.lockDevice.Unlock()
+	}
+
 	for {
 		indication, err := indications.Recv()
 		if err == io.EOF {
@@ -167,6 +184,19 @@
 			log.Infow("Failed to read from indications", log.Fields{"err": err})
 			continue
 		}
+		// When OLT is admin down, allow only NNI operation status change indications.
+		if dh.adminState == "down" {
+			_, isIntfOperInd := indication.Data.(*oop.Indication_IntfOperInd)
+			if isIntfOperInd {
+				intfOperInd := indication.GetIntfOperInd()
+				if intfOperInd.GetType() == "nni" {
+					log.Infow("olt is admin down, allow nni ind", log.Fields{})
+				}
+			} else {
+				log.Infow("olt is admin down, ignore indication", log.Fields{})
+				continue
+			}
+		}
 		switch indication.Data.(type) {
 		case *oop.Indication_OltInd:
 			oltInd := indication.GetOltInd()
@@ -294,7 +324,7 @@
 	}
 	KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
 	// Instantiate resource manager
-	if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceId, KVStoreHostPort,  dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
+	if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceId, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
 		log.Error("Error while instantiating resource manager")
 		return errors.New("Instantiating resource manager failed")
 	}
@@ -589,3 +619,63 @@
 	}
 	return nil
 }
+
+func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
+	if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
+		log.Errorw("Failed to disable olt ", log.Fields{"err": err})
+		return err
+	}
+	dh.lockDevice.Lock()
+	dh.adminState = "down"
+	dh.lockDevice.Unlock()
+	log.Debug("olt-disabled")
+
+	cloned := proto.Clone(device).(*voltha.Device)
+	// Update the all ports state on that device to disable
+	if err := dh.coreProxy.PortsStateUpdate(nil, cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
+		log.Errorw("updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
+		return err
+	}
+
+	//Update the device oper state
+	cloned.OperStatus = voltha.OperStatus_UNKNOWN
+	dh.device = cloned
+
+	if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
+		log.Errorw("error-updating-device-state", log.Fields{"deviceId": device.Id, "error": err})
+		return err
+	}
+	log.Debugw("DisableDevice-end", log.Fields{"deviceId": device.Id})
+	return nil
+}
+
+func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
+	if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
+		log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
+		return err
+	}
+
+	dh.lockDevice.Lock()
+	dh.adminState = "up"
+	dh.lockDevice.Unlock()
+	log.Debug("olt-reenabled")
+
+	cloned := proto.Clone(device).(*voltha.Device)
+	// Update the all ports state on that device to enable
+	if err := dh.coreProxy.PortsStateUpdate(nil, cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
+		log.Errorw("updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
+		return err
+	}
+
+	//Update the device oper status as ACTIVE
+	cloned.OperStatus = voltha.OperStatus_ACTIVE
+	dh.device = cloned
+
+	if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
+		log.Errorw("error-updating-device-state", log.Fields{"deviceId": device.Id, "error": err})
+		return err
+	}
+	log.Debugw("ReEnableDevice-end", log.Fields{"deviceId": device.Id})
+
+	return nil
+}
diff --git a/adaptercore/openolt.go b/adaptercore/openolt.go
index 2678987..2e5174f 100644
--- a/adaptercore/openolt.go
+++ b/adaptercore/openolt.go
@@ -185,11 +185,21 @@
 }
 
 func (oo *OpenOLT) Disable_device(device *voltha.Device) error {
-	return errors.New("UnImplemented")
+	log.Infow("disable-device", log.Fields{"deviceId": device.Id})
+	if handler := oo.getDeviceHandler(device.Id); handler != nil {
+		return handler.DisableDevice(device)
+	}
+	log.Errorw("device-handler-not-set", log.Fields{"deviceId": device.Id})
+	return errors.New("device-handler-not-found")
 }
 
 func (oo *OpenOLT) Reenable_device(device *voltha.Device) error {
-	return errors.New("UnImplemented")
+	log.Infow("reenable-device", log.Fields{"deviceId": device.Id})
+	if handler := oo.getDeviceHandler(device.Id); handler != nil {
+		return handler.ReenableDevice(device)
+	}
+	log.Errorw("device-handler-not-set", log.Fields{"deviceId": device.Id})
+	return errors.New("device-handler-not-found")
 }
 
 func (oo *OpenOLT) Reboot_device(device *voltha.Device) error {