[VOL-2641] Returning errors for flows and groups from the open olt adapter to the core

Change-Id: I513c2d391ddfa99d82589ab974956b1f4359bb68
diff --git a/internal/pkg/olterrors/olterrors.go b/internal/pkg/olterrors/olterrors.go
index 175b948..33ef71e 100644
--- a/internal/pkg/olterrors/olterrors.go
+++ b/internal/pkg/olterrors/olterrors.go
@@ -281,6 +281,37 @@
 	return e
 }
 
+// ErrGroupOp represents an error condition when a group operation to a device did
+// not succeed
+type ErrGroupOp struct {
+	ErrAdapter
+}
+
+// NewErrGroupOp constructs a new error based on the given values
+func NewErrGroupOp(operation string, ID uint32, fields log.Fields, wrapped error) LoggableError {
+	return &ErrPersistence{
+		ErrAdapter{
+			name: "unable-to-perform-group-operation",
+			fields: merge(fields, log.Fields{
+				"operation": operation,
+				"id":        fmt.Sprintf("0x%x", ID)}),
+			wrapped: wrapped,
+		},
+	}
+}
+
+// Log logs the error at the default level for log and return
+func (e *ErrGroupOp) Log() error {
+	_ = e.ErrAdapter.Log()
+	return e
+}
+
+// LogAt logs the error at the specified level and then returns the error
+func (e *ErrGroupOp) LogAt(level log.LogLevel) error {
+	_ = e.ErrAdapter.LogAt(level)
+	return e
+}
+
 // ErrTimeout represents an error condition when the deadline for performing an
 // operation has been exceeded
 type ErrTimeout struct {