func GetProtectionBase(mitigationScopeId int64) (protection ProtectionBase, err error) {
	dbProtection := db_models.Protection{}
	engine, err := ConnectDB()
	if err != nil {
		log.WithFields(log.Fields{
			"Err": err,
		}).Error("database connect error")
		return
	}
	ok, err := engine.Where("mitigation_scope_id = ?", mitigationScopeId).Get(&dbProtection)
	if err != nil {
		log.WithFields(log.Fields{
			"MitigationScopeId": mitigationScopeId,
			"Err":          err,
		}).Error("select Protection error")
		return
	}
	if !ok {
		return ProtectionBase{}, nil
	}
	droppedInfo, err := loadProtectionStatus(engine, dbProtection.DroppedDataInfoId)
	if err != nil {
		log.WithFields(log.Fields{
			"MitigationScopeId": mitigationScopeId,
			"Err":          err,
		}).Error("load blocked_data_info error")
		return
	}
	var blocker Blocker
	if dbProtection.TargetBlockerId == 0 {
		blocker = nil
	} else {
		b, err := GetBlockerById(dbProtection.TargetBlockerId)
		if err != nil {
			return ProtectionBase{}, err
		}
		blockerConfig, err := GetBlockerConfiguration(dbProtection.CustomerId, string(messages.MITIGATION_REQUEST_ACL))
		if err != nil {
			return ProtectionBase{}, err
		}
		blocker, err = toBlocker(b, blockerConfig)
		if err != nil {
			return ProtectionBase{}, err
		}
	}
	protection = ProtectionBase{
		id:                dbProtection.Id,
		customerId:        dbProtection.CustomerId,
		targetId:          dbProtection.TargetId,
		targetBlocker:     blocker,
		isEnabled:         dbProtection.IsEnabled,
		startedAt:         dbProtection.StartedAt,
		finishedAt:        dbProtection.FinishedAt,
		recordTime:        dbProtection.RecordTime,
		droppedDataInfo:   droppedInfo,
	}
	return
}
/*
Obtains a Protection object by ID.

parameter:
mitigationId mitigation ID
return:
protection Protection
error error
package models
import (
	"errors"
	"fmt"
	"time"
	"github.com/go-xorm/xorm"
	"github.com/nttdots/go-dots/dots_server/db_models"
	"github.com/nttdots/go-dots/dots_common/messages"
	log "github.com/sirupsen/logrus"
)
func loadProtectionStatus(engine *xorm.Engine, id int64) (pps *ProtectionStatus, err error) {
	dps := db_models.ProtectionStatus{}
	ok, err := engine.Id(id).Get(&dps)
	if err != nil {
		return
	}
	if !ok {
		pps = nil
		return
	}
	pps = NewProtectionStatus(
		dps.Id, dps.BytesDropped, dps.PacketsDropped, dps.BpsDropped, dps.PpsDropped,
	)
	return
}
func storeProtectionStatus(session *xorm.Session, ps *ProtectionStatus) (err error) {
	if ps == nil {
		return
	}
	dps := db_models.ProtectionStatus{
		Id:              ps.Id(),
		BytesDropped:    ps.BytesDropped(),
		PacketsDropped:  ps.PacketDropped(),
		BpsDropped:      ps.BpsDropped(),
		PpsDropped:      ps.PpsDropped(),
	}
	if dps.Id == 0 {
		_, err = session.Insert(&dps)
		log.WithFields(log.Fields{
			"data": dps,
			"err":  err,
		}).Debug("insert ProtectionStatus")
		if err != nil {
			return
		}
		ps.SetId(dps.Id)
	} else {
		_, err = session.Id(dps.Id).Cols("total_bits", "total_packets", "peak_throughput_id", "averate_throughput_id").Update(&dps)
		log.WithFields(log.Fields{
			"data": dps,
			"err":  err,
		}).Debug("update ProtectionStatus")
		if err != nil {
			return
		}
	}
	return
}
func CreateProtection2(protection Protection) (newProtection db_models.Protection, err error) {
	var gobgpParameters []db_models.GoBgpParameter
	var aristaParameters     []db_models.AristaParameter
	var flowSpecParameters   []db_models.FlowSpecParameter
	var droppedDataInfo *db_models.ProtectionStatus
	var blockerId int64
	engine, err := ConnectDB()
	if err != nil {
		log.WithFields(log.Fields{
			"Err": err,
		}).Error("database connect error")
		return
	}
	session := engine.NewSession()
	defer session.Close()
	err = session.Begin()
	if err != nil {
		log.WithFields(log.Fields{
			"Err": err,
		}).Error("session create error")
		return
	}
	if protection.DroppedDataInfo() != nil {
		droppedDataInfo = &db_models.ProtectionStatus{
			BytesDropped:      protection.DroppedDataInfo().BytesDropped(),
			PacketsDropped:    protection.DroppedDataInfo().PacketDropped(),
			BpsDropped:        protection.DroppedDataInfo().BpsDropped(),
			PpsDropped:        protection.DroppedDataInfo().PpsDropped(),
		}
		_, err = session.Insert(droppedDataInfo)
		if err != nil {
			log.WithFields(log.Fields{
				"MitigationScopeId":              newProtection.TargetId,
				"DroppedDataInfoTotalBytes":      droppedDataInfo.BytesDropped,
				"DroppedDataInfoTotalPackets":    droppedDataInfo.PacketsDropped,
				"DroppedDataInfoBitPerSecond":    droppedDataInfo.BpsDropped,
				"DroppedDataInfoPacketPerSecond": droppedDataInfo.PpsDropped,
				"Err": err,
			}).Error("insert ProtectionStatus error")
			goto Rollback
		}
	}
	if protection.TargetBlocker() != nil {
		blockerId = protection.TargetBlocker().Id()
	}
	newProtection = db_models.Protection{
		CustomerId:          protection.CustomerId(),
		ProtectionType:      string(protection.Type()),
		TargetId:            protection.TargetId(),
		TargetType:          protection.TargetType(),
		AclName:             protection.AclName(),
		TargetBlockerId:     blockerId,
		IsEnabled:           protection.IsEnabled(),
		StartedAt:           protection.StartedAt(),
		FinishedAt:          protection.FinishedAt(),
		RecordTime:          protection.RecordTime(),
		DroppedDataInfoId:   droppedDataInfo.Id,
	}
	_, err = session.Insert(&newProtection)
	if err != nil {
		log.WithFields(log.Fields{
			"Err": err,
		}).Info("protection insert")
		goto Rollback
	}
	err = session.Commit()
	session = engine.NewSession()
	defer session.Close()
	log.WithFields(log.Fields{
		"protection": newProtection,
	}).Debug("create new protection")
	if string(protection.Type()) == PROTECTION_TYPE_RTBH {
		gobgpParameters = toGoBGPParameters(protection, newProtection.Id)
		if len(gobgpParameters) > 0 {
			_, err = session.InsertMulti(&gobgpParameters)
			if err != nil {
				log.WithFields(log.Fields{
					"MitigationScopeId": newProtection.TargetId,
					"Err":               err,
				}).Error("insert GoBgpParameter error")
				goto Rollback
			}
			log.WithFields(log.Fields{
				"goBGP_parameters": gobgpParameters,
			}).Debug("create new gobgp_parameter")
		}
	} else if string(protection.Type()) == PROTECTION_TYPE_ARISTA {
		aristaParameters = toAristaParameters(protection, newProtection.Id)
		if len(aristaParameters) > 0 {
			_, err = session.InsertMulti(&aristaParameters)
			if err != nil {
				log.WithFields(log.Fields{
					"TargetId": newProtection.TargetId,
					"Err":                err,
				}).Error("insert AristaParameter error")
				goto Rollback
			}
			log.WithFields(log.Fields{
				"arista_parameters": aristaParameters,
			}).Debug("create new arista_parameter")
		}
	} else if string(protection.Type()) == PROTECTION_TYPE_FLOWSPEC {
		flowSpecParameters = toFlowSpecParameters(protection, newProtection.Id)
		if len(flowSpecParameters) > 0 {
			_, err = session.InsertMulti(&flowSpecParameters)
			if err != nil {
				log.WithFields(log.Fields{
					"MitigationScopeId": newProtection.TargetId,
					"Err":               err,
				}).Error("insert flowSpecParameters error")
				goto Rollback
			}
			log.WithFields(log.Fields{
				"flow_spec_parameters": flowSpecParameters,
			}).Debug("create new flow_spec_parameter")
		}
	} else {
		log.WithFields(log.Fields{
			"type": protection.Type(),
		}).Panic("not implement")
	}
	err = session.Commit()
	return newProtection, nil
Rollback:
	session.Rollback()
	return
}
func UpdateProtection(protection Protection) (err error) {
	var protectionParameters []db_models.GoBgpParameter
	var updProtection *db_models.Protection
	var updDroppedDataInfo *db_models.ProtectionStatus
	var chk bool
	engine, err := ConnectDB()
	if err != nil {
		log.WithFields(log.Fields{
			"Err": err,
		}).Error("database connect error")
		return
	}
	session := engine.NewSession()
	defer session.Close()
	err = session.Begin()
	if err != nil {
		log.WithFields(log.Fields{
			"Err": err,
		}).Error("session create error")
		return
	}
	updProtection = &db_models.Protection{}
	chk, err = session.Id(protection.Id()).Get(updProtection)
	if err != nil {
		log.WithFields(log.Fields{
			"id":           protection.Id(),
			"MitigationScopeId": protection.TargetId(),
			"Err":          err,
		}).Error("select Protection error")
		goto Rollback
	}
	if !chk {
		log.WithFields(log.Fields{
			"id":           protection.Id(),
			"MitigationScopeId": protection.TargetId(),
		}).Info("update Protection data not exist.")
		goto Rollback
	}
	updProtection.IsEnabled = protection.IsEnabled()
	updProtection.StartedAt = protection.StartedAt()
	updProtection.FinishedAt = protection.FinishedAt()
	updProtection.RecordTime = protection.RecordTime()
	_, err = session.Id(updProtection.Id).Cols("is_enabled", "started_at", "finished_at", "record_time").Update(updProtection)
	if err != nil {
		log.WithFields(log.Fields{
			"ProtectionId": updProtection.Id,
			"Err":          err,
		}).Error("update Protection error")
		goto Rollback
	}
	if protection.DroppedDataInfo() != nil {
		err = storeProtectionStatus(session, protection.DroppedDataInfo())
		if err != nil {
			log.WithFields(log.Fields{
				"MitigationScopeId":              updProtection.TargetId,
				"DroppedDataInfoTotalBytes":      updDroppedDataInfo.BytesDropped,
				"DroppedDataInfoTotalPackets":    updDroppedDataInfo.PacketsDropped,
				"DroppedDataInfoBitPerSecond":    updDroppedDataInfo.BpsDropped,
				"DroppedDataInfoPacketPerSecond": updDroppedDataInfo.PpsDropped,
				"Err": err,
			}).Error("update ProtectionStatus error")
			goto Rollback
		}
	}
	_, err = session.Delete(&db_models.GoBgpParameter{ProtectionId: protection.Id()})
	if err != nil {
		log.WithFields(log.Fields{
			"ProtectionId": updProtection.Id,
			"MitigationScopeId": updProtection.TargetId,
			"Err":          err,
		}).Error("delete ParameterValue error")
		goto Rollback
	}
	protectionParameters = toGoBGPParameters(protection, protection.Id())
	if len(protectionParameters) > 0 {
		_, err = session.InsertMulti(&protectionParameters)
		if err != nil {
			log.WithFields(log.Fields{
				"ProtectionId": updProtection.Id,
				"MitigationScopeId": updProtection.TargetId,
				"Err":          err,
			}).Error("insert ParameterValue error")
			goto Rollback
		}
	}
	err = session.Commit()
	return
Rollback:
	session.Rollback()
	return
}
func GetActiveProtectionByTargetIDAndTargetType(targetID int64, targetType string) (p Protection, err error) {
	engine, err := ConnectDB()
	if err != nil {
		log.Errorf("database connect error: %s", err)
		return
	}
	var ps []db_models.Protection
	err = engine.Where("target_id = ? AND target_type = ? AND is_enabled = 1", targetID, targetType).Find(&ps)
	if err != nil {
		return nil, err
	}
	if len(ps) == 0 {
		return nil, nil
	}
	return toProtection(engine, ps[len(ps)-1])
}
func GetProtectionById(id int64) (p Protection, err error) {
	dbp := db_models.Protection{}
	engine, err := ConnectDB()
	if err != nil {
		log.Errorf("database connect error: %s", err)
		return
	}
	ok, err := engine.Id(id).Get(&dbp)
	if err != nil {
		log.WithField("id", id).Warnf("GetProtectionById: get error.", err)
		return nil, err
	}
	if !ok {
		log.WithField("id", id).Warnf("GetProtectionById: protection not found.", err)
		return nil, nil
	}
	p, err = toProtection(engine, dbp)
	return
}
func toProtection(engine *xorm.Engine, dbp db_models.Protection) (p Protection, err error) {
	droppedDataInfo, err := loadProtectionStatus(engine, dbp.DroppedDataInfoId)
	if err != nil {
		return
	}
	var blocker Blocker
	if dbp.TargetBlockerId == 0 {
		blocker = nil
	} else {
		var dbl db_models.Blocker
		ok, err := engine.Id(dbp.TargetBlockerId).Get(&dbl)
		if err != nil {
			return nil, err
		}
		if !ok {
			blocker = nil
		} else {
			blockerConfig, err := GetBlockerConfiguration(dbp.CustomerId, dbp.TargetType)
			if err != nil {
				return nil, err
			}
			blocker, err = toBlocker(dbl, blockerConfig)
			if err != nil {
				return nil, err
			}
		}
	}
	pb := ProtectionBase{
		dbp.Id,
		dbp.CustomerId,
		dbp.TargetId,
		dbp.TargetType,
		dbp.AclName,
		"",
		"",
		blocker,
		dbp.IsEnabled,
		dbp.StartedAt,
		dbp.FinishedAt,
		dbp.RecordTime,
		droppedDataInfo,
	}
	var params []db_models.GoBgpParameter
	err = engine.Where("protection_id = ?", dbp.Id).Find(&params)
	if err != nil {
		return nil, err
	}
	switch dbp.ProtectionType {
	case PROTECTION_TYPE_RTBH:
		p = NewRTBHProtection(pb, params)
	case PROTECTION_TYPE_FLOWSPEC:
		var flowSpecParams []db_models.FlowSpecParameter
	    err = engine.Where("protection_id = ?", dbp.Id).Find(&flowSpecParams)
	    if err != nil {
		    return nil, err
	    }
		p = NewFlowSpecProtection(pb, flowSpecParams)
	case PROTECTION_TYPE_ARISTA:
		var aristaParams []db_models.AristaParameter
	    err = engine.Where("protection_id = ?", dbp.Id).Find(&aristaParams)
	    if err != nil {
		    return nil, err
	    }
		p = NewAristaProtection(pb, aristaParams)
	default:
		p = nil
		err = errors.New(fmt.Sprintf("invalid protection type: %s", dbp.ProtectionType))
	}
	log.Infof("toProtection. found protection. p=%+v\n", p)
	return
}