[REV] optimize,merge new code

This commit is contained in:
bay1ts 2017-12-07 16:05:59 +08:00
commit c2269ac74d
34 changed files with 1064 additions and 54 deletions

View File

@ -161,6 +161,8 @@ class AppImage():
pass
self.log.info("云帮应用发布完毕", step="last", status="success")
else:
self.log.info("镜像不存在,发布失败", step="callback", status="failure")
elif dest == "ys":
# 当前有镜像并且云市的image数据中心开启
if self.region_registry.exist_image(image) and self.is_oss_image:
@ -229,7 +231,9 @@ class AppImage():
"云市应用发布失败 {}".format(e.message),
step="callback",
status="failure")
else:
self.log.info("镜像不存在,发布失败", step="callback", status="failure")
def download_and_deploy(self):
image = self.task['image']
namespace = self.task['namespace']

View File

@ -343,7 +343,10 @@ class RepoBuilder():
"path": build_image_name,
"event_id": self.event_id
}
self.region_client.update_version_region(json.dumps(version_body))
try:
self.region_client.update_version_region(json.dumps(version_body))
except Exception as e:
pass
return True
def build_code(self):
@ -417,7 +420,10 @@ class RepoBuilder():
"path": package_name,
"event_id": self.event_id
}
#self.region_client.update_version_region(json.dumps(version_body))
try:
self.region_client.update_version_region(json.dumps(version_body))
except Exception as e:
pass
return True
def feedback(self):
@ -474,7 +480,7 @@ class RepoBuilder():
self.log.error(
"升级部署应用错误", step="callback", status="failure")
else:
self.log.info("构建失败", step="callback", status="failure")
self.log.info("构建失败,请查看Debug构建日志", step="callback", status="failure")
else:
self.log.error("代码拉取失败。", step="callback", status="failure")
except Exception as e:

View File

@ -35,8 +35,8 @@ class UserConsoleAPI(BaseHttpClient):
return res, body
def service_publish_success(self, body):
# pass
url = self.base_url + '/api/tenants/services/publish'
pass
#url = self.base_url + '/api/tenants/services/publish'
# url = 'http://127.0.0.1:3228/api/publish'
res, body = self._post(url, self.default_headers, body)
return res, body
#res, body = self._post(url, self.default_headers, body)
#return res, body

View File

@ -139,12 +139,11 @@ class CodeCheck():
self.region_client.code_check_region(json.dumps(body))
def main():
body = ""
for line in fileinput.input(): # read task from stdin
body = line
code_check = CodeCheck(job=Job(body=body), config=load_dict, base_dir=sys.path[0])
code_check.do_work()

View File

@ -29,6 +29,9 @@ type TenantInterface interface {
TenantResources(w http.ResponseWriter, r *http.Request)
Tenant(w http.ResponseWriter, r *http.Request)
ServicesInfo(w http.ResponseWriter, r *http.Request)
TenantsWithResource(w http.ResponseWriter, r *http.Request)
TenantsQuery(w http.ResponseWriter, r *http.Request)
TenantsGetByName(w http.ResponseWriter, r *http.Request)
SumTenants(w http.ResponseWriter, r *http.Request)
SingleTenantResources(w http.ResponseWriter, r *http.Request)
}

View File

@ -185,6 +185,11 @@ func (v2 *V2) resourcesRouter() chi.Router {
r := chi.NewRouter()
r.Post("/tenants", controller.GetManager().TenantResources)
r.Get("/tenants/sum", controller.GetManager().SumTenants)
//tenants's resource
r.Get("/tenants/res", controller.GetManager().TenantsWithResource)
r.Get("/tenants/res/page/{curPage}/size/{pageLen}", controller.GetManager().TenantsWithResource)
r.Get("/tenants/query/{tenant_name}", controller.GetManager().TenantsQuery)
r.Get("/tenants/{tenant_name}/res", controller.GetManager().TenantsGetByName)
return r
}

View File

@ -40,6 +40,8 @@ import (
httputil "github.com/goodrain/rainbond/pkg/util/http"
"github.com/Sirupsen/logrus"
"sort"
"github.com/renstorm/fuzzysearch/fuzzy"
)
//V2Routes v2Routes
@ -132,6 +134,201 @@ func (t *TenantStruct) TenantResources(w http.ResponseWriter, r *http.Request) {
return
}
//TenantsQuery TenantsQuery
func (t *TenantStruct) TenantsQuery(w http.ResponseWriter, r *http.Request) {
// swagger:operation GET /v2/tenants/query/{tenant_name} v2 tenants
//
// 租户带资源列表
//
// get tenant resources
//
// ---
// produces:
// - application/json
// - application/xml
//
// parameters:
// - name: tenant_name
// in: path
// description: '123'
// required: true
// type: string
// format: string
//
// responses:
// default:
// schema:
// "$ref": "#/responses/commandResponse"
// description: 统一返回格式
tenantName := strings.TrimSpace(chi.URLParam(r, "tenant_name"))
rep, err := handler.GetTenantManager().GetTenantsName()
if err != nil {
httputil.ReturnError(r, w, 500, fmt.Sprintf("get tenants names error, %v", err))
return
}
result:=fuzzy.Find(tenantName, rep) // [cartwheel wheel]
httputil.ReturnSuccess(r, w, result)
return
}
//TenantsGetByName TenantsGetByName
func (t *TenantStruct) TenantsGetByName(w http.ResponseWriter, r *http.Request) {
// swagger:operation GET /v2/tenants/{tenant_name}/res v2 tenants
//
// 租户带资源单个
//
// get tenant resources
//
// ---
// produces:
// - application/json
// - application/xml
//
// parameters:
// - name: tenant_name
// in: path
// description: '123'
// required: true
// type: string
// format: string
//
// responses:
// default:
// schema:
// "$ref": "#/responses/commandResponse"
// description: 统一返回格式
tenantName := strings.TrimSpace(chi.URLParam(r, "tenant_name"))
v, err := handler.GetTenantManager().GetTenantsByName(tenantName)
if err != nil {
httputil.ReturnError(r, w, 500, fmt.Sprintf("get tenants names error, %v", err))
return
}
logrus.Infof("query tenant from db by name %s ,got %v",tenantName,v)
var res =&api_model.TenantResource{}
services, err := handler.GetServiceManager().GetService(v.UUID)
if err != nil {
httputil.ReturnError(r, w, 500, fmt.Sprintf("get services by tenantID %s error, %v",v.UUID, err))
return
}
totalResInfo, _ := handler.GetTenantManager().TotalMemCPU(services)
usedResInfo, _ := handler.GetTenantManager().StatsMemCPU(services)
res.UUID=v.UUID
res.Name=v.Name
res.EID=v.EID
res.AllocatedCPU=totalResInfo.CPU
res.AllocatedMEM=totalResInfo.MEM
res.UsedCPU=usedResInfo.CPU
res.UsedMEM=usedResInfo.MEM
httputil.ReturnSuccess(r, w, res)
return
}
//TenantsWithResource TenantsWithResource
func (t *TenantStruct) TenantsWithResource(w http.ResponseWriter, r *http.Request) {
// swagger:operation GET /v2/resources/tenants/res/page/{curPage}/size/{pageLen} v2 PagedTenantResList
//
// 租户带资源列表
//
// get paged tenant resources
//
// ---
// produces:
// - application/json
// - application/xml
//
// parameters:
// - name: curPage
// in: path
// description: '123'
// required: true
// type: string
// format: string
// - name: pageLen
// in: path
// description: '25'
// required: true
// type: string
// format: string
//
// responses:
// default:
// schema:
// "$ref": "#/responses/commandResponse"
// description: 统一返回格式
pageLenStr := strings.TrimSpace(chi.URLParam(r, "pageLen"))
curPageStr := strings.TrimSpace(chi.URLParam(r, "curPage"))
pageLen,err:=strconv.Atoi(pageLenStr)
if err != nil {
httputil.ReturnError(r, w, 400, fmt.Sprintf("bad request, %v", err))
return
}
curPage,err:=strconv.Atoi(curPageStr)
if err != nil {
httputil.ReturnError(r, w, 400, fmt.Sprintf("bad request, %v", err))
return
}
rep, err := handler.GetTenantManager().GetTenants()
if err != nil {
httputil.ReturnError(r, w, 500, fmt.Sprintf("get tenants error, %v", err))
return
}
var result []*api_model.TenantResource
for _,v:=range rep{
services, err := handler.GetServiceManager().GetService(v.UUID)
if err != nil {
httputil.ReturnError(r, w, 500, fmt.Sprintf("get services by tenantID %s error, %v",v.UUID, err))
return
}
totalResInfo, _ := handler.GetTenantManager().TotalMemCPU(services)
usedResInfo, _ := handler.GetTenantManager().StatsMemCPU(services)
var res api_model.TenantResource
res.UUID=v.UUID
res.Name=v.Name
res.EID=v.EID
res.AllocatedCPU=totalResInfo.CPU
res.AllocatedMEM=totalResInfo.MEM
res.UsedCPU=usedResInfo.CPU
res.UsedMEM=usedResInfo.MEM
result=append(result,&res)
}
pList := api_model.TenantResList(result)
sort.Sort(pList)
var resultList []*api_model.TenantResource
if curPage*pageLen<len(rep) {
resultList=pList[(curPage-1)*pageLen:curPage*pageLen]
}else{
resultList=pList[(curPage-1)*pageLen:len(rep)]
}
var ret api_model.PagedTenantResList
ret.List=resultList
ret.Length=len(resultList)
httputil.ReturnSuccess(r, w, ret)
return
}
//SumTenants 统计租户数量
func (t *TenantStruct) SumTenants(w http.ResponseWriter, r *http.Request) {
// swagger:operation GET /v2/resources/tenants/sum v2 sumTenants

View File

@ -503,30 +503,14 @@ func (t *TenantStruct) BuildService(w http.ResponseWriter, r *http.Request) {
sEvent, status, err := createEvent(build.Body.EventID, serviceID, "build", tenantID, build.Body.DeployVersion)
handleStatus(status, err, w, r)
//{\"tenant_name\":\"\",\"service_alias\":\"\",\"Body\":{\"event_id\":\"c19aa41c357a4d9e9ca38ab7f2a44961\",\"envs\":{},\"kind\":\"source\",\"action\":\"deploy\",\"image_url\":\"\",\"deploy_version\":\"20171122154417\",\"repo_url\":\"--branch master --depth 1 https://github.com/bay1ts/zk_cluster_mini.git\",\"operator\":\"bay1ts\",\"tenant_name\":\"bay1ts-test\",\"service_alias\":\"gr21ea6b\"}}
////createBuildInfo
version := dbmodel.VersionInfo{}
version.EventID = sEvent.EventID
version.ServiceID = serviceID
version.RepoURL = build.Body.RepoURL
version.Kind = build.Body.Kind
version.BuildVersion = build.Body.DeployVersion
db.GetManager().VersionInfoDao().AddModel(&version)
//save
//version.DeliveredPath
//version.FinalStatus
//need update
//EventID string `json:"event_id" validate:"event_id|required"`
//ENVS map[string]string `json:"envs" validate:"envs"`
//Kind string `json:"kind" validate:"kind|required"`
//Action string `json:"action" validate:"action"`
//ImageURL string `json:"image_url" validate:"image_url"`
//DeployVersion string `json:"deploy_version" validate:"deploy_version|required"`
//RepoURL string `json:"repo_url" validate:"repo_url"`
//Operator string `json:"operator" validate:"operator"`
//TenantName string `json:"tenant_name"`
//ServiceAlias string `json:"service_alias"`
build.Body.EventID = sEvent.EventID
if err := handler.GetServiceManager().ServiceBuild(tenantID, serviceID, &build); err != nil {
@ -535,6 +519,12 @@ func (t *TenantStruct) BuildService(w http.ResponseWriter, r *http.Request) {
return
}
logrus.Debugf("equeue mq build task success")
err=db.GetManager().VersionInfoDao().AddModel(&version)
if err != nil {
logrus.Infof("error add version %v ,details %s",version,err.Error())
}
httputil.ReturnSuccess(r, w, sEvent)
//w.WriteHeader(200)
}

View File

@ -1,19 +1,19 @@
// RAINBOND, Application Management Platform
// Copyright (C) 2014-2017 Goodrain Co., Ltd.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. For any non-GPL usage of Rainbond,
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
// must be obtained first.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
@ -28,7 +28,10 @@ import (
//TenantHandler tenant handler
type TenantHandler interface {
GetTenants() ([]*dbmodel.Tenants, error)
GetTenantsByName(name string) (*dbmodel.Tenants, error)
GetTenantsName() ([]string, error)
StatsMemCPU(services []*dbmodel.TenantServices) (*api_model.StatsInfo, error)
TotalMemCPU(services []*dbmodel.TenantServices) (*api_model.StatsInfo, error)
//QueryTsdb(md *api_model.MontiorData) (*tsdbClient.QueryResponse, error)
HTTPTsdb(md *api_model.MontiorData) ([]byte, error)
GetTenantsResources(tr *api_model.TenantResources) ([]*map[string]interface{}, error)

View File

@ -34,6 +34,7 @@ import (
"github.com/Sirupsen/logrus"
"k8s.io/client-go/kubernetes"
"strings"
)
//TenantAction tenant act
@ -91,6 +92,49 @@ func (t *TenantAction) GetTenants() ([]*dbmodel.Tenants, error) {
return tenants, err
}
//StatsMemCPU StatsMemCPU
func (t *TenantAction) TotalMemCPU(services []*dbmodel.TenantServices) (*api_model.StatsInfo, error){
cpus := 0
mem := 0
for _, service := range services {
logrus.Debugf("service is %s, cpus is %v, mem is %v", service.ID, service.ContainerCPU, service.ContainerMemory)
cpus += service.ContainerCPU
mem += service.ContainerMemory
}
si := &api_model.StatsInfo{
CPU: cpus,
MEM: mem,
}
return si, nil
}
//GetTenantsName get tenants name
func (t *TenantAction) GetTenantsName() ([]string, error) {
tenants, err := db.GetManager().TenantDao().GetALLTenants()
if err != nil {
return nil, err
}
var result []string
for _,v:=range tenants{
result=append(result,strings.ToLower(v.Name))
}
return result, err
}
//GetTenants get tenants
func (t *TenantAction) GetTenantsByName(name string) (*dbmodel.Tenants, error) {
tenant, err := db.GetManager().TenantDao().GetTenantIDByName(name)
if err != nil {
return nil, err
}
return tenant, err
}
//StatsMemCPU StatsMemCPU
func (t *TenantAction) StatsMemCPU(services []*dbmodel.TenantServices) (*api_model.StatsInfo, error) {
cpus := 0

View File

@ -25,6 +25,8 @@ import (
dbmodel "github.com/goodrain/rainbond/pkg/db/model"
)
//ServiceGetCommon path参数
//swagger:parameters getVolumes getDepVolumes
type ServiceGetCommon struct {

View File

@ -0,0 +1,58 @@
// RAINBOND, Application Management Platform
// Copyright (C) 2014-2017 Goodrain Co., Ltd.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. For any non-GPL usage of Rainbond,
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
// must be obtained first.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package model
type TenantResList []*TenantResource
type PagedTenantResList struct {
List []*TenantResource `json:"list"`
Length int `json:"length"`
}
//TenantResource path参数
//swagger:parameters getVolumes getDepVolumes
type TenantResource struct {
AllocatedCPU int `json:"alloc_cpu"`
AllocatedMEM int `json:"alloc_memory"`
UsedCPU int `json:"used_cpu"`
UsedMEM int `json:"used_memory"`
Name string `json:"name"`
UUID string `json:"uuid"`
EID string `json:"eid"`
}
func (list TenantResList) Len() int {
return len(list)
}
func (list TenantResList) Less(i, j int) bool {
if list[i].UsedMEM > list[j].UsedMEM {
return true
} else if list[i].UsedMEM < list[j].UsedMEM {
return false
} else {
return list[i].UsedCPU > list[j].UsedCPU
}
}
func (list TenantResList) Swap(i, j int) {
var temp *TenantResource = list[i]
list[i] = list[j]
list[j] = temp
}

View File

@ -62,6 +62,8 @@ type NodeInterface interface {
Label(label map[string]string)
}
func (t *Node)Label(label map[string]string) {
body,_:=json.Marshal(label)
_,_,err:=nodeServer.Request("/nodes/"+t.Id+"/labels","PUT",body)

View File

@ -37,6 +37,7 @@ type TenantDao interface {
GetTenantByUUID(uuid string) (*model.Tenants, error)
GetTenantIDByName(tenantName string) (*model.Tenants, error)
GetALLTenants() ([]*model.Tenants, error)
//GetTenantsOrderByUsedMemPaged(page,pagesize int) ([]*model.Tenants, error)
}
//LicenseDao LicenseDao

View File

@ -77,6 +77,15 @@ func (t *TenantDaoImpl) GetTenantIDByName(name string) (*model.Tenants, error) {
return &tenant, nil
}
//GetTenantsOrderByUsedMemPaged 获取租户分页
//func (t *TenantDaoImpl) GetTenantsOrderByUsedMemPaged(page,pagesize int) ([]*model.Tenants, error) {
// var tenant []*model.Tenants
// if err := t.DB.Select("sum(container_cpu), sum(container_memory)").Where("cur_status = ?", "running").Group("tenant_id").Find(&tenant).Error; err != nil {
// return nil, err
// }
// return tenant, nil
//}
//GetALLTenants GetALLTenants
func (t *TenantDaoImpl) GetALLTenants() ([]*model.Tenants, error) {
var tenants []*model.Tenants

View File

@ -312,8 +312,12 @@ func (h *handleMessageStore) handleBarrelEvent() {
event.EventID = eventID
event.CodeVersion = codeVersion
cdb.GetManager().ServiceEventDao().UpdateModel(&event)
version,_:=cdb.GetManager().VersionInfoDao().GetVersionByEventID(eventID)
version,err:=cdb.GetManager().VersionInfoDao().GetVersionByEventID(eventID)
//infos:=strings.Split(codeVersion,":")
if err!=nil {
logrus.Errorf("error get version by eventID %s",eventID)
continue
}
version.CodeVersion=codeVersion
//for k,v:=range infos{
// i:=strings.Split(v," ")

View File

@ -40,6 +40,7 @@ func GetCmds() []cli.Command {
cmds = append(cmds, NewCmdEvent())
cmds = append(cmds, NewCmdGet())
cmds = append(cmds, NewCmdInit())
cmds = append(cmds, NewCmdShow())
//cmds = append(cmds, NewCmdAddNode())
//cmds = append(cmds, NewCmdComputeGroup())

View File

@ -89,7 +89,6 @@ func NewCmdInstallStatus() cli.Command {
Status(v.ID)
return nil
}
}
}
}else {

View File

@ -35,7 +35,23 @@ import (
"bytes"
)
func NewCmdShow() cli.Command {
c:=cli.Command{
Name:"show",
Usage:"显示region安装完成后访问地址",
Action: func(c *cli.Context) error {
var urls []string
manageHosts:=clients.NodeClient.Nodes().Rule("manage")
for _,v:=range manageHosts{
url:=v.ExternalIP+":7070"
urls=append(urls,url)
}
fmt.Println(urls)
return nil
},
}
return c
}
func NewCmdNode() cli.Command {
c:=cli.Command{
@ -77,35 +93,35 @@ func NewCmdNode() cli.Command {
Name: "list",
Usage: "list",
Action: func(c *cli.Context) error {
list:=clients.NodeClient.Nodes().List()
list := clients.NodeClient.Nodes().List()
serviceTable := termtables.CreateTable()
serviceTable.AddHeaders("uid", "IP", "HostName","role","alived","unschedulable","ready")
serviceTable.AddHeaders("uid", "IP", "HostName", "role", "alived", "unschedulable", "ready")
var rest []*model.HostNode
for _,v:=range list{
var ready bool=false
for _,c:=range v.Conditions {
if string(c.Type)=="Ready"&&string(c.Status)=="True"{
ready=true
for _, v := range list {
var ready bool = false
for _, c := range v.Conditions {
if string(c.Type) == "Ready" && string(c.Status) == "True" {
ready = true
}
}
if v.Role.HasRule("manage") {
serviceTable.AddRow(v.ID, v.InternalIP,v.HostName, v.Role.String(),v.Alived,"N/A",ready)
serviceTable.AddRow(v.ID, v.InternalIP, v.HostName, v.Role.String(), v.Alived, "N/A", ready)
}else{
rest=append(rest,v)
} else {
rest = append(rest, v)
}
}
if len(rest)>0 {
if len(rest) > 0 {
serviceTable.AddSeparator()
}
for _,v:=range rest{
var ready bool=false
for _,c:=range v.Conditions {
if string(c.Type)=="Ready"&&string(c.Status)=="True"{
ready=true
for _, v := range rest {
var ready bool = false
for _, c := range v.Conditions {
if string(c.Type) == "Ready" && string(c.Status) == "True" {
ready = true
}
}
serviceTable.AddRow(v.ID, v.InternalIP,v.HostName, v.Role.String(),v.Alived,v.Unschedulable,ready)
serviceTable.AddRow(v.ID, v.InternalIP, v.HostName, v.Role.String(), v.Alived, v.Unschedulable, ready)
}
fmt.Println(serviceTable.Render())
return nil

View File

@ -23,7 +23,7 @@ import (
"github.com/goodrain/rainbond/pkg/node/core/job"
"github.com/goodrain/rainbond/pkg/node/core/k8s"
"github.com/goodrain/rainbond/pkg/node/core/store"
//httputil "github.com/goodrain/rainbond/pkg/util/http"
"encoding/json"
"fmt"
"net/http"
@ -543,7 +543,81 @@ func Resources(w http.ResponseWriter, r *http.Request) {
logrus.Infof("get cpu %v and mem %v", cpuR, memR)
api.ReturnSuccess(r, w, result)
}
func CapRes(w http.ResponseWriter, r *http.Request) {
nodes, err := nodeService.GetAllNode()
if err != nil {
err.Handle(r, w)
return
}
var capCpu int64
var capMem int64
for _,v:=range nodes{
if v.NodeStatus != nil {
capCpu+=v.NodeStatus.Capacity.Cpu().Value()
capMem+=v.NodeStatus.Capacity.Memory().Value()
}
}
result := new(model.Resource)
result.CpuR=int(capCpu)
result.MemR=int(capMem)
logrus.Infof("get cpu %v and mem %v", capCpu, capMem)
api.ReturnSuccess(r, w, result)
}
func RegionRes(w http.ResponseWriter, r *http.Request) {
nodes, err := nodeService.GetAllNode()
if err != nil {
err.Handle(r, w)
return
}
var capCpu int64
var capMem int64
for _,v:=range nodes{
if v.NodeStatus != nil {
capCpu+=v.NodeStatus.Capacity.Cpu().Value()
capMem+=v.NodeStatus.Capacity.Memory().Value()
}
}
//
//tenants, error := db.GetManager().TenantDao().GetALLTenants()
//if error != nil {
// logrus.Errorf("error get tenants ,details %s",error.Error())
//}
//s:=len(tenants)
nodeList, error := k8s.K8S.Core().Nodes().List(metav1.ListOptions{})
if error != nil {
logrus.Errorf("error get nodes from k8s ,details %s", error.Error())
api.ReturnError(r, w, 500, "failed,details "+error.Error())
return
}
cpuR := 0
memR := 0
for _, v := range nodeList.Items {
ps, _ := k8s.GetPodsByNodeName(v.Name)
for _, pv := range ps {
rc := pv.Spec.Containers[0].Resources.Requests.Cpu().String()
rm := pv.Spec.Containers[0].Resources.Requests.Memory().String()
cpuR += getCpuInt(rc)
memR += convertMemoryToMBInt(rm, true)
}
}
result := new(model.ClusterResource)
result.CapCpu=int(capCpu)
result.CapMem=int(capMem)/1024/1024
result.ReqCpu = float32(cpuR)/1000
result.ReqMem = memR
result.Node=len(nodes)
result.Tenant=0
logrus.Infof("get cpu %v and mem %v", capCpu, capMem)
api.ReturnSuccess(r, w, result)
}
func UpdateNode(w http.ResponseWriter, r *http.Request) {
nodeUID := strings.TrimSpace(chi.URLParam(r, "node"))

View File

@ -76,6 +76,15 @@ func GetNodes(w http.ResponseWriter, r *http.Request) {
err.Handle(r, w)
return
}
for _,v:=range nodes {
if v.NodeStatus!=nil{
for _,condiction:=range v.Conditions{
if condiction.Type=="Ready"&&condiction.Status=="True" {
v.Status="running"
}
}
}
}
httputil.ReturnSuccess(r, w, nodes)
}

View File

@ -78,11 +78,21 @@ func ExecTask(w http.ResponseWriter, r *http.Request) {
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &nodes, nil); !ok {
return
}
err := taskService.ExecTask(taskID, nodes.Nodes)
if err != nil {
err.Handle(r, w)
return
}
for _,v:=range nodes.Nodes {
node, err := nodeService.GetNode(v)
if err != nil {
err.Handle(r, w)
return
}
node.Status="install"
}
httputil.ReturnSuccess(r, w, nil)
}

View File

@ -31,6 +31,16 @@ type Resource struct {
MemR int `json:"mem"`
}
//Resource 资源
type ClusterResource struct {
Node int `json:"node"`
Tenant int `json:"tenant"`
CapCpu int `json:"cap_cpu"`
CapMem int `json:"cap_mem"`
ReqCpu float32 `json:"req_cpu"`
ReqMem int `json:"req_mem"`
}
type FirstConfig struct {
StorageMode string `json:"storage_mode"`
StorageHost string `json:"storage_host,omitempty"`

View File

@ -53,8 +53,11 @@ func Routers(mode string) *chi.Mux {
r.Get("/datacenter", controller.GetDatacenterConfig)
r.Put("/datacenter", controller.PutDatacenterConfig)
})
r.Route("/nodes", func(r chi.Router) {
r.Get("/fullres",controller.RegionRes)
r.Get("/resources", controller.Resources)
r.Get("/capres", controller.CapRes)
r.Get("/", controller.GetNodes)
r.Get("/{rule}", controller.GetRuleNodes)
r.Post("/", controller.NewNode) //增加一个节点

View File

@ -62,7 +62,10 @@ func (n *NodeService) AddNode(node *model.APIHostNode) *utils.APIHandleError {
}
}
rbnode := node.Clone()
rbnode.Status="init"
rbnode.CreateTime = time.Now()
rbnode.Status="create"
rbnode.Conditions = make([]model.NodeCondition, 0)
if _, err := rbnode.Update(); err != nil {
return utils.CreateAPIHandleErrorFromDBError("save node", err)
@ -120,9 +123,6 @@ func (n *NodeService) CordonNode(nodeID string, unschedulable bool) *utils.APIHa
}
//更新节点状态
hostNode.Unschedulable = unschedulable
if unschedulable {
hostNode.Status = "unschedulable"
}
//k8s节点存在
if hostNode.NodeStatus != nil {
//true表示drain不可调度
@ -163,6 +163,7 @@ func (n *NodeService) DownNode(nodeID string) (*model.HostNode, *utils.APIHandle
if !hostNode.Role.HasRule(model.ComputeNode) || hostNode.NodeStatus == nil {
return nil, utils.CreateAPIHandleError(400, fmt.Errorf("node is not k8s node or it not up"))
}
hostNode.Status="down"
err := k8s.DeleteNode(hostNode.ID)
if err != nil {
return nil, utils.CreateAPIHandleError(500, fmt.Errorf("k8s node down error,%s", err.Error()))

View File

@ -294,6 +294,7 @@ func (n *NodeCluster) checkNodeInstall(node *model.HostNode) {
node.UpdataCondition(initCondition)
n.UpdateNode(node)
}()
node.Status="init"
errorCondition := func(reason string, err error) {
initCondition.Status = model.ConditionFalse
initCondition.LastTransitionTime = time.Now()

10
vendor/github.com/renstorm/fuzzysearch/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,10 @@
language: go
go:
- 1.4
- 1.5
script:
make test
sudo: false

21
vendor/github.com/renstorm/fuzzysearch/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Peter Renström
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

10
vendor/github.com/renstorm/fuzzysearch/Makefile generated vendored Normal file
View File

@ -0,0 +1,10 @@
default: build
build:
go build
test:
go test -v ./...
benchmark:
go test -benchmem -bench=. ./...

43
vendor/github.com/renstorm/fuzzysearch/README.md generated vendored Normal file
View File

@ -0,0 +1,43 @@
# Fuzzy Search
[![Build Status](https://img.shields.io/travis/renstrom/fuzzysearch.svg?style=flat-square)](https://travis-ci.org/renstrom/fuzzysearch)
[![Godoc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](https://godoc.org/github.com/renstrom/fuzzysearch/fuzzy)
Inspired by _[bevacqua/fuzzysearch][1]_, a fuzzy matching library written in JavaScript. But contains some extras like ranking using _[Levenshtein distance][2]_ (see [`RankMatch()`](https://godoc.org/github.com/renstrom/fuzzysearch/fuzzy#RankMatch)) and finding matches in a list of words (see [`Find()`](https://godoc.org/github.com/renstrom/fuzzysearch/fuzzy#Find)).
Fuzzy searching allows for flexibly matching a string with partial input, useful for filtering data very quickly based on lightweight user input.
The current implementation uses the algorithm suggested by Mr. Aleph, a russian compiler engineer working at V8.
## Usage
```go
fuzzy.Match("twl", "cartwheel") // true
fuzzy.Match("cart", "cartwheel") // true
fuzzy.Match("cw", "cartwheel") // true
fuzzy.Match("ee", "cartwheel") // true
fuzzy.Match("art", "cartwheel") // true
fuzzy.Match("eeel", "cartwheel") // false
fuzzy.Match("dog", "cartwheel") // false
fuzzy.RankMatch("kitten", "sitting") // 3
words := []string{"cartwheel", "foobar", "wheel", "baz"}
fuzzy.Find("whl", words) // [cartwheel wheel]
fuzzy.RankFind("whl", words) // [{whl cartwheel 6} {whl wheel 2}]
```
You can sort the result of a `fuzzy.RankFind()` call using the [`sort`](https://golang.org/pkg/sort/) package in the standard library:
```go
matches := fuzzy.RankFind("whl", words) // [{whl cartwheel 6} {whl wheel 2}]
sort.Sort(matches) // [{whl wheel 2} {whl cartwheel 6}]
```
## License
MIT
[1]: https://github.com/bevacqua/fuzzysearch
[2]: http://en.wikipedia.org/wiki/Levenshtein_distance

167
vendor/github.com/renstorm/fuzzysearch/fuzzy/fuzzy.go generated vendored Normal file
View File

@ -0,0 +1,167 @@
// Fuzzy searching allows for flexibly matching a string with partial input,
// useful for filtering data very quickly based on lightweight user input.
package fuzzy
import (
"unicode"
"unicode/utf8"
)
var noop = func(r rune) rune { return r }
// Match returns true if source matches target using a fuzzy-searching
// algorithm. Note that it doesn't implement Levenshtein distance (see
// RankMatch instead), but rather a simplified version where there's no
// approximation. The method will return true only if each character in the
// source can be found in the target and occurs after the preceding matches.
func Match(source, target string) bool {
return match(source, target, noop)
}
// MatchFold is a case-insensitive version of Match.
func MatchFold(source, target string) bool {
return match(source, target, unicode.ToLower)
}
func match(source, target string, fn func(rune) rune) bool {
lenDiff := len(target) - len(source)
if lenDiff < 0 {
return false
}
if lenDiff == 0 && source == target {
return true
}
Outer:
for _, r1 := range source {
for i, r2 := range target {
if fn(r1) == fn(r2) {
target = target[i+utf8.RuneLen(r2):]
continue Outer
}
}
return false
}
return true
}
// Find will return a list of strings in targets that fuzzy matches source.
func Find(source string, targets []string) []string {
return find(source, targets, noop)
}
// FindFold is a case-insensitive version of Find.
func FindFold(source string, targets []string) []string {
return find(source, targets, unicode.ToLower)
}
func find(source string, targets []string, fn func(rune) rune) []string {
var matches []string
for _, target := range targets {
if match(source, target, fn) {
matches = append(matches, target)
}
}
return matches
}
// RankMatch is similar to Match except it will measure the Levenshtein
// distance between the source and the target and return its result. If there
// was no match, it will return -1.
// Given the requirements of match, RankMatch only needs to perform a subset of
// the Levenshtein calculation, only deletions need be considered, required
// additions and substitutions would fail the match test.
func RankMatch(source, target string) int {
return rank(source, target, noop)
}
// RankMatchFold is a case-insensitive version of RankMatch.
func RankMatchFold(source, target string) int {
return rank(source, target, unicode.ToLower)
}
func rank(source, target string, fn func(rune) rune) int {
lenDiff := len(target) - len(source)
if lenDiff < 0 {
return -1
}
if lenDiff == 0 && source == target {
return 0
}
runeDiff := 0
Outer:
for _, r1 := range source {
for i, r2 := range target {
if fn(r1) == fn(r2) {
target = target[i+utf8.RuneLen(r2):]
continue Outer
} else {
runeDiff++
}
}
return -1
}
// Count up remaining char
for len(target) > 0 {
target = target[utf8.RuneLen(rune(target[0])):]
runeDiff++
}
return runeDiff
}
// RankFind is similar to Find, except it will also rank all matches using
// Levenshtein distance.
func RankFind(source string, targets []string) Ranks {
var r Ranks
for _, target := range find(source, targets, noop) {
distance := LevenshteinDistance(source, target)
r = append(r, Rank{source, target, distance})
}
return r
}
// RankFindFold is a case-insensitive version of RankFind.
func RankFindFold(source string, targets []string) Ranks {
var r Ranks
for _, target := range find(source, targets, unicode.ToLower) {
distance := LevenshteinDistance(source, target)
r = append(r, Rank{source, target, distance})
}
return r
}
type Rank struct {
// Source is used as the source for matching.
Source string
// Target is the word matched against.
Target string
// Distance is the Levenshtein distance between Source and Target.
Distance int
}
type Ranks []Rank
func (r Ranks) Len() int {
return len(r)
}
func (r Ranks) Swap(i, j int) {
r[i], r[j] = r[j], r[i]
}
func (r Ranks) Less(i, j int) bool {
return r[i].Distance < r[j].Distance
}

View File

@ -0,0 +1,210 @@
package fuzzy
import (
"fmt"
"sort"
"strings"
"testing"
)
const deBelloGallico = `All Gaul is divided into three parts, one of which the Belgae inhabit,
the Aquitani another, those who in their own language are called Celts, in our Gauls, the third.
All these differ from each other in language, customs and laws. The river Garonne separates the
Gauls from the Aquitani; the Marne and the Seine separate them from the Belgae. Of all these,
the Belgae are the bravest, because they are furthest from the civilization and refinement of
[our] Province, and merchants least frequently resort to them, and import those things which tend
to effeminate the mind; and they are the nearest to the Germans, who dwell beyond the Rhine,
with whom they are continually waging war; for which reason the Helvetii also surpass the rest
of the Gauls in valor, as they contend with the Germans in almost daily battles, when they either
repel them from their own territories, or themselves wage war on their frontiers. One part of
these, which it has been said that the Gauls occupy, takes its beginning at the river Rhone;
it is bounded by the river Garonne, the ocean, and the territories of the Belgae; it borders,
too, on the side of the Sequani and the Helvetii, upon the river Rhine, and stretches toward the
north. The Belgae rises from the extreme frontier of Gaul, extend to the lower part of the river
Rhine; and look toward the north and the rising sun. Aquitania extends from the river Garonne to
the Pyrenaean mountains and to that part of the ocean which is near Spain: it looks between the
setting of the sun, and the north star.`
var fuzzyTests = []struct {
source string
target string
wanted bool
rank int
}{
{"zazz", deBelloGallico + " zazz", true, 1544},
{"zazz", "zazz " + deBelloGallico, true, 1544},
{"twl", "cartwheel", true, 6},
{"cart", "cartwheel", true, 5},
{"cw", "cartwheel", true, 7},
{"ee", "cartwheel", true, 7},
{"art", "cartwheel", true, 6},
{"eeel", "cartwheel", false, -1},
{"dog", "cartwheel", false, -1},
{"ёлка", "ёлочка", true, 2},
{"ветер", "ёлочка", false, -1},
{"中国", "中华人民共和国", true, 5},
{"日本", "中华人民共和国", false, -1},
}
func TestFuzzyMatch(t *testing.T) {
for _, val := range fuzzyTests {
match := Match(val.source, val.target)
if match != val.wanted {
t.Errorf("%s in %s expected match to be %t, got %t",
val.source, val.target, val.wanted, match)
}
}
}
func TestFuzzyMatchFold(t *testing.T) {
for _, val := range fuzzyTests {
match := MatchFold(val.source, strings.ToUpper(val.target))
if match != val.wanted {
t.Errorf("%s in %s expected match to be %t, got %t",
val.source, strings.ToUpper(val.target), val.wanted, match)
}
}
}
func TestFuzzyFind(t *testing.T) {
target := []string{"cartwheel", "foobar", "wheel", "baz"}
wanted := []string{"cartwheel", "wheel"}
matches := Find("whl", target)
if len(matches) != len(wanted) {
t.Errorf("expected %s, got %s", wanted, matches)
}
for i := range wanted {
if wanted[i] != matches[i] {
t.Errorf("expected %s, got %s", wanted, matches)
}
}
}
func TestRankMatch(t *testing.T) {
for _, val := range fuzzyTests {
rank := RankMatch(val.source, val.target)
if rank != val.rank {
t.Errorf("expected ranking %d, got %d for %s in %s",
val.rank, rank, val.source, val.target)
}
}
}
func TestRankFind(t *testing.T) {
target := []string{"cartwheel", "foobar", "wheel", "baz"}
wanted := []Rank{
{"whl", "cartwheel", 6},
{"whl", "wheel", 2},
}
ranks := RankFind("whl", target)
if len(ranks) != len(wanted) {
t.Errorf("expected %+v, got %+v", wanted, ranks)
}
for i := range wanted {
if wanted[i] != ranks[i] {
t.Errorf("expected %+v, got %+v", wanted, ranks)
}
}
}
func TestSortingRanks(t *testing.T) {
rs := Ranks{{"a", "b", 1}, {"a", "cc", 2}, {"a", "a", 0}}
wanted := Ranks{rs[2], rs[0], rs[1]}
sort.Sort(rs)
for i := range wanted {
if wanted[i] != rs[i] {
t.Errorf("expected %+v, got %+v", wanted, rs)
}
}
}
func BenchmarkMatch(b *testing.B) {
ft := fuzzyTests[2]
for i := 0; i < b.N; i++ {
Match(ft.source, ft.target)
}
}
func BenchmarkMatchBigLate(b *testing.B) {
ft := fuzzyTests[0]
for i := 0; i < b.N; i++ {
Match(ft.source, ft.target)
}
}
func BenchmarkMatchBigEarly(b *testing.B) {
ft := fuzzyTests[1]
for i := 0; i < b.N; i++ {
Match(ft.source, ft.target)
}
}
func BenchmarkMatchFold(b *testing.B) {
ft := fuzzyTests[2]
for i := 0; i < b.N; i++ {
MatchFold(ft.source, ft.target)
}
}
func BenchmarkMatchFoldBigLate(b *testing.B) {
ft := fuzzyTests[0]
for i := 0; i < b.N; i++ {
MatchFold(ft.source, ft.target)
}
}
func BenchmarkMatchFoldBigEarly(b *testing.B) {
ft := fuzzyTests[1]
for i := 0; i < b.N; i++ {
MatchFold(ft.source, ft.target)
}
}
func BenchmarkRankMatch(b *testing.B) {
ft := fuzzyTests[2]
for i := 0; i < b.N; i++ {
RankMatch(ft.source, ft.target)
}
}
func BenchmarkRankMatchBigLate(b *testing.B) {
ft := fuzzyTests[0]
for i := 0; i < b.N; i++ {
RankMatch(ft.source, ft.target)
}
}
func BenchmarkRankMatchBigEarly(b *testing.B) {
ft := fuzzyTests[1]
for i := 0; i < b.N; i++ {
RankMatch(ft.source, ft.target)
}
}
func ExampleMatch() {
fmt.Print(Match("twl", "cartwheel"))
// Output: true
}
func ExampleFind() {
fmt.Print(Find("whl", []string{"cartwheel", "foobar", "wheel", "baz"}))
// Output: [cartwheel wheel]
}
func ExampleRankMatch() {
fmt.Print(RankMatch("twl", "cartwheel"))
// Output: 6
}
func ExampleRankFind() {
fmt.Printf("%+v", RankFind("whl", []string{"cartwheel", "foobar", "wheel", "baz"}))
// Output: [{Source:whl Target:cartwheel Distance:6} {Source:whl Target:wheel Distance:2}]
}

View File

@ -0,0 +1,43 @@
package fuzzy
// LevenshteinDistance measures the difference between two strings.
// The Levenshtein distance between two words is the minimum number of
// single-character edits (i.e. insertions, deletions or substitutions)
// required to change one word into the other.
//
// This implemention is optimized to use O(min(m,n)) space and is based on the
// optimized C version found here:
// http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#C
func LevenshteinDistance(s, t string) int {
r1, r2 := []rune(s), []rune(t)
column := make([]int, len(r1)+1)
for y := 1; y <= len(r1); y++ {
column[y] = y
}
for x := 1; x <= len(r2); x++ {
column[0] = x
for y, lastDiag := 1, x-1; y <= len(r1); y++ {
oldDiag := column[y]
cost := 0
if r1[y-1] != r2[x-1] {
cost = 1
}
column[y] = min(column[y]+1, column[y-1]+1, lastDiag+cost)
lastDiag = oldDiag
}
}
return column[len(r1)]
}
func min(a, b, c int) int {
if a < b && a < c {
return a
} else if b < c {
return b
}
return c
}

View File

@ -0,0 +1,55 @@
package fuzzy
import "testing"
var levenshteinDistanceTests = []struct {
s, t string
wanted int
}{
{"zazz", deBelloGallico + " zazz", 1544},
{"zazz", "zazz " + deBelloGallico, 1544},
{"a", "a", 0},
{"ab", "ab", 0},
{"ab", "aa", 1},
{"ab", "aa", 1},
{"ab", "aaa", 2},
{"bbb", "a", 3},
{"kitten", "sitting", 3},
{"ёлка", "ёлочка", 2},
{"ветер", "ёлочка", 6},
{"中国", "中华人民共和国", 5},
{"日本", "中华人民共和国", 7},
}
func TestLevenshtein(t *testing.T) {
for _, test := range levenshteinDistanceTests {
distance := LevenshteinDistance(test.s, test.t)
if distance != test.wanted {
t.Errorf("got distance %d, expected %d for %s in %s",
distance, test.wanted, test.s, test.t)
}
}
}
func BenchmarkLevenshteinDistance(b *testing.B) {
ldt := levenshteinDistanceTests[2]
ldt2 := levenshteinDistanceTests[5]
for i := 0; i < b.N; i++ {
LevenshteinDistance(ldt.s, ldt.t)
LevenshteinDistance(ldt2.s, ldt2.t)
}
}
func BenchmarkLevenshteinDistanceBigLate(b *testing.B) {
ldt := levenshteinDistanceTests[0]
for i := 0; i < b.N; i++ {
LevenshteinDistance(ldt.s, ldt.t)
}
}
func BenchmarkLevenshteinDistanceBigEarly(b *testing.B) {
ldt := levenshteinDistanceTests[1]
for i := 0; i < b.N; i++ {
LevenshteinDistance(ldt.s, ldt.t)
}
}