support joint filter

This commit is contained in:
wanyaoqi
2018-08-25 18:58:24 +08:00
parent 08e834b470
commit d1607e7be6
6 changed files with 190 additions and 14 deletions
Generated
+10 -5
View File
@@ -666,13 +666,15 @@
version = "v1.2.0"
[[projects]]
digest = "1:d867dfa6751c8d7a435821ad3b736310c2ed68945d05b50fb9d23aee0540c8cc"
branch = "master"
digest = "1:c1f242537d2898c84fe9bfd8bd94b177cd5ff98a10c397dbbc494f4e2b173be6"
name = "github.com/serialx/hashring"
packages = ["."]
pruneopts = "UT"
revision = "49a4782e9908fe098c907022a1bd7519c79803d6"
[[projects]]
digest = "1:d867dfa6751c8d7a435821ad3b736310c2ed68945d05b50fb9d23aee0540c8cc"
name = "github.com/sirupsen/logrus"
packages = ["."]
pruneopts = "UT"
@@ -1040,18 +1042,18 @@
[[projects]]
branch = "master"
digest = "1:b707a5d591b21dad9ebdb264281632ed43d34e2b980dce967acb2c7adcc93ad3"
digest = "1:636db180d3fc734536a5437d93bb6fe937feb036c1ed062c25872a47c4283163"
name = "yunion.io/x/log"
packages = [
".",
"hooks",
]
pruneopts = "UT"
revision = "a10b94c5038480920262e0f344656328434955a2"
revision = "5185c49f6d361f61e561fbccba1bedcc7c62748b"
[[projects]]
branch = "master"
digest = "1:47670c70d0326f624de21c8f29d0f73850062f0752f27e146308db62fbb540d3"
digest = "1:8e2a4d71738e5e3bffc415b23f100b0a5033dbf88154783122f5147d4fc213b5"
name = "yunion.io/x/pkg"
packages = [
"gotypes",
@@ -1086,7 +1088,7 @@
"utils",
]
pruneopts = "UT"
revision = "6c349ecbdb90d5f6ecc9b86596428176c1937b32"
revision = "7348c84865abac3fcdec618591b7eee7c2e0669b"
[[projects]]
branch = "master"
@@ -1109,6 +1111,7 @@
analyzer-version = 1
input-imports = [
"github.com/aliyun/alibaba-cloud-sdk-go/sdk",
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors",
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests",
"github.com/aliyun/aliyun-oss-go-sdk/oss",
"github.com/aokoli/goutils",
@@ -1147,6 +1150,7 @@
"github.com/mholt/caddy/startupshutdown",
"github.com/miekg/dns",
"github.com/moul/http2curl",
"github.com/serialx/hashring",
"github.com/stretchr/testify/assert",
"github.com/vmware/govmomi",
"github.com/vmware/govmomi/object",
@@ -1158,6 +1162,7 @@
"golang.org/x/crypto/ssh",
"gopkg.in/gin-gonic/gin.v1",
"k8s.io/api/core/v1",
"k8s.io/apimachinery/pkg/api/errors",
"k8s.io/apimachinery/pkg/apis/meta/v1",
"k8s.io/apimachinery/pkg/fields",
"k8s.io/apimachinery/pkg/labels",
+29 -1
View File
@@ -251,6 +251,30 @@ func applyListItemsGeneralFilters(manager IModelManager, q *sqlchemy.SQuery,
return q, nil
}
func applyListItemsGeneralJointFilters(manager IModelManager, q *sqlchemy.SQuery,
userCred mcclient.TokenCredential, jointFilters []string, filterAny bool) (*sqlchemy.SQuery, error) {
for _, f := range jointFilters {
jfc := filterclause.ParseJointFilterClause(f)
if jfc != nil {
jointModelManager := GetModelManager(jfc.GetJointModelName())
schFields := searchFields(jointModelManager, userCred)
if ok, _ := utils.InStringArray(jfc.GetField(), schFields); ok {
sq := jointModelManager.Query(jfc.ReleatedKey)
cond := jfc.GetJointFilter(sq)
if cond != nil {
sq = sq.Filter(cond)
if filterAny {
q = q.Filter(sqlchemy.OR(sqlchemy.In(q.Field("id"), sq)))
} else {
q = q.Filter(sqlchemy.AND(sqlchemy.In(q.Field("id"), sq)))
}
}
}
}
}
return q, nil
}
func listItemQueryFilters(manager IModelManager, ctx context.Context, q *sqlchemy.SQuery,
userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
@@ -272,11 +296,15 @@ func listItemQueryFilters(manager IModelManager, ctx context.Context, q *sqlchem
return nil, err
}
}
filterAny, _ := query.Bool("filter_any")
filters := jsonutils.GetQueryStringArray(query, "filter")
if len(filters) > 0 {
filterAny, _ := query.Bool("filter_any")
q, err = applyListItemsGeneralFilters(manager, q, userCred, filters, filterAny)
}
jointFilter := jsonutils.GetQueryStringArray(query, "joint_filter")
if len(jointFilter) > 0 {
q, _ = applyListItemsGeneralJointFilters(manager, q, userCred, jointFilter, filterAny)
}
return q, nil
}
+108
View File
@@ -0,0 +1,108 @@
package hooks
import (
"fmt"
"os"
"path/filepath"
"github.com/sirupsen/logrus"
)
type LogFileHook struct {
FileDir string
FileName string
fullPath string
file *os.File
written int64
}
func (h *LogFileHook) Init() error {
if fi, err := os.Lstat(h.FileDir); err != nil {
if os.IsNotExist(err) {
os.MkdirAll(h.FileDir, 0755)
} else {
return fmt.Errorf("Lstat %s: %s", h.FileDir, err)
}
} else if !fi.Mode().IsDir() {
return fmt.Errorf("%s exists and it's not a directory", h.FileDir)
}
h.fullPath = filepath.Join(h.FileDir, h.FileName)
file, err := os.OpenFile(h.fullPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755)
if err != nil {
return fmt.Errorf("OpenFile %s: %s", h.fullPath, err)
}
h.file = file
h.written = 0
return nil
}
func (h *LogFileHook) DeInit() {
if h.file != nil {
h.file.Close()
}
}
func (h *LogFileHook) Levels() []logrus.Level {
return logrus.AllLevels
}
func (h *LogFileHook) Fire(e *logrus.Entry) error {
if b, err := e.Logger.Formatter.Format(e); err != nil {
return err
} else {
n, err := h.file.Write(b)
h.written += int64(n)
return err
}
return nil
}
func (h *LogFileHook) Written() int64 {
return h.written
}
// rotate by size
type LogFileRotateHook struct {
LogFileHook
RotateNum int
RotateSize int64
filePaths []string
}
func (h *LogFileRotateHook) Init() error {
if err := h.LogFileHook.Init(); err != nil {
return err
}
h.filePaths = make([]string, h.RotateNum)
for i := 1; i < h.RotateNum; i++ {
fileName := fmt.Sprintf("%s.%d", h.FileName, i)
filePath := filepath.Join(h.FileDir, fileName)
h.filePaths[i] = filePath
}
h.filePaths[0] = filepath.Join(h.FileDir, h.FileName)
return nil
}
func (h *LogFileRotateHook) rotate() {
for i := h.RotateNum - 1; i > 0; i-- {
filePath0 := h.filePaths[i-1]
if _, err := os.Lstat(filePath0); err != nil {
continue
}
filePath1 := h.filePaths[i]
os.Rename(filePath0, filePath1)
}
h.LogFileHook.DeInit()
h.LogFileHook.Init()
}
func (h *LogFileRotateHook) Fire(e *logrus.Entry) error {
if err := h.LogFileHook.Fire(e); err != nil {
return err
}
if h.LogFileHook.Written() >= h.RotateSize {
h.rotate()
}
return nil
}
+1 -6
View File
@@ -12,14 +12,9 @@ type StdioHook struct{}
func (hook *StdioHook) Fire(entry *logrus.Entry) error {
line, err := entry.String()
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
return err
}
if entry.Level >= logrus.ErrorLevel {
fmt.Fprintf(os.Stderr, line)
} else {
fmt.Fprintf(os.Stdout, line)
}
fmt.Fprintf(os.Stderr, line)
return nil
}
+35 -1
View File
@@ -16,6 +16,20 @@ type SFilterClause struct {
params []string
}
type SJointFilterClause struct {
SFilterClause
JointModel string
ReleatedKey string
}
func (jfc *SJointFilterClause) GetJointFilter(q *sqlchemy.SQuery) sqlchemy.ICondition {
return jfc.QueryCondition(q)
}
func (jfc *SJointFilterClause) GetJointModelName() string {
return jfc.JointModel[:len(jfc.JointModel)-1]
}
func (fc *SFilterClause) QueryCondition(q *sqlchemy.SQuery) sqlchemy.ICondition {
field := q.Field(fc.field)
if field == nil {
@@ -63,11 +77,13 @@ func (fc *SFilterClause) String() string {
}
var (
filterClausePattern *regexp.Regexp
filterClausePattern *regexp.Regexp
jointFilterClausePattern *regexp.Regexp
)
func init() {
filterClausePattern = regexp.MustCompile(`^(\w+)\.(\w+)\((.*)\)`)
jointFilterClausePattern = regexp.MustCompile(`^(\w+)\((\w+)\).(\w+)\.(\w+)\((.*)\)`)
}
func ParseFilterClause(filter string) *SFilterClause {
@@ -79,3 +95,21 @@ func ParseFilterClause(filter string) *SFilterClause {
fc := SFilterClause{field: matches[1], funcName: matches[2], params: params}
return &fc
}
func ParseJointFilterClause(jointFilter string) *SJointFilterClause {
matches := jointFilterClausePattern.FindStringSubmatch(jointFilter)
if matches == nil {
return nil
}
params := utils.FindWords([]byte(matches[5]), 0)
jfc := SJointFilterClause{
SFilterClause: SFilterClause{
field: matches[3],
funcName: matches[4],
params: params,
},
JointModel: matches[1],
ReleatedKey: matches[2],
}
return &jfc
}
+7 -1
View File
@@ -9,12 +9,18 @@ const (
STORAGE_NAS = "nas"
STORAGE_VSAN = "vsan"
STORAGE_CLOUD = "cloud"
STORAGE_CLOUD_SSD = "cloud_ssd"
STORAGE_CLOUD_EFFICIENCY = "cloud_efficiency"
STORAGE_STANDARD = "standard" //Azure hdd storage type
STORAGE_PREMIUM = "premium" //Azure ssd storage type
)
var STORAGE_TYPES = []string{STORAGE_LOCAL, STORAGE_BAREMETAL, STORAGE_SHEEPDOG,
STORAGE_RBD, STORAGE_DOCKER, STORAGE_NAS, STORAGE_VSAN, STORAGE_CLOUD_SSD, STORAGE_CLOUD_EFFICIENCY}
STORAGE_RBD, STORAGE_DOCKER, STORAGE_NAS, STORAGE_VSAN,
STORAGE_CLOUD, STORAGE_CLOUD_SSD, STORAGE_CLOUD_EFFICIENCY,
STORAGE_STANDARD, STORAGE_PREMIUM}
var LOCAL_STORAGE_TYPES = []string{STORAGE_LOCAL, STORAGE_BAREMETAL}