add host iso&pxe register

This commit is contained in:
TangBin
2019-12-19 16:01:46 +08:00
parent 083c8465cd
commit 256b62997a
2 changed files with 98 additions and 50 deletions
+90 -19
View File
@@ -23,14 +23,13 @@ import (
"strings"
"time"
"golang.org/x/sync/errgroup"
"yunion.io/x/onecloud/pkg/apigateway/options"
"github.com/360EntSecGroup-Skylar/excelize"
"golang.org/x/sync/errgroup"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/apigateway/options"
"yunion.io/x/onecloud/pkg/appctx"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/httperrors"
@@ -39,6 +38,19 @@ import (
"yunion.io/x/onecloud/pkg/mcclient/modules"
)
const (
HOST_MAC = "*MAC地址"
HOST_NAME = "*名称"
HOST_IPMI_ADDR = "*IPMI地址"
HOST_IPMI_USERNAME = "*IPMI用户名"
HOST_IPMI_PASSWORD = "*IPMI密码"
HOST_MNG_IP_ADDR = "*管理口IP地址"
HOST_IPMI_ADDR_OPTIONAL = "IPMI地址"
HOST_IPMI_USERNAME_OPTIONAL = "IPMI用户名"
HOST_IPMI_PASSWORD_OPTIONAL = "IPMI密码"
HOST_MNG_IP_ADDR_OPTIONAL = "管理口IP地址"
)
func FetchSession(ctx context.Context, r *http.Request, apiVersion string) *mcclient.ClientSession {
token := AppContextToken(ctx)
session := auth.GetSession(ctx, token, FetchRegion(r), apiVersion)
@@ -142,22 +154,48 @@ func (mh *MiscHandler) DoBatchHostRegister(ctx context.Context, w http.ResponseW
log.Errorf(err.Error())
e := httperrors.NewInternalServerError("can't parse file")
httperrors.JsonClientError(w, e)
return
}
rows := xlsx.GetRows("hosts")
if len(rows) == 0 {
e := httperrors.NewGeneralError(fmt.Errorf("empty file content"))
httperrors.JsonClientError(w, e)
return
}
h := ""
paramKeys := []string{}
for _, title := range rows[0] {
switch title {
case HOST_MAC:
paramKeys = append(paramKeys, "access_mac")
case HOST_NAME:
paramKeys = append(paramKeys, "name")
case HOST_IPMI_ADDR, HOST_IPMI_ADDR_OPTIONAL:
paramKeys = append(paramKeys, "ipmi_ip_addr")
case HOST_IPMI_USERNAME, HOST_IPMI_USERNAME_OPTIONAL:
paramKeys = append(paramKeys, "ipmi_username")
case HOST_IPMI_PASSWORD, HOST_IPMI_PASSWORD_OPTIONAL:
paramKeys = append(paramKeys, "ipmi_password")
case HOST_MNG_IP_ADDR, HOST_MNG_IP_ADDR_OPTIONAL:
paramKeys = append(paramKeys, "access_ip")
default:
e := httperrors.NewInternalServerError("empty file content")
httperrors.JsonClientError(w, e)
return
}
}
// skipped header row
for _, row := range xlsx.GetRows("hosts")[1:] {
if len(row) < 4 {
log.Debugf("batchHostRegister row length too short (less than 4) %s", row)
}
h = h + strings.Join(row, ",") + "\n"
}
s := FetchSession(ctx, req, "")
params := jsonutils.NewDict()
params.Set("hosts", jsonutils.NewString(h))
resp, err := modules.Hosts.DoBatchRegister(s, params)
resp, err := modules.Hosts.DoBatchRegister(s, paramKeys, params)
if err != nil {
e := httperrors.NewGeneralError(err)
httperrors.JsonClientError(w, e)
@@ -200,21 +238,38 @@ func (mh *MiscHandler) DoBatchUserRegister(ctx context.Context, w http.ResponseW
log.Errorf(err.Error())
e := httperrors.NewInternalServerError("can't parse file")
httperrors.JsonClientError(w, e)
return
}
// skipped header row
names := map[string]string{}
rows := xlsx.GetRows("users")
if len(rows) <= 1 {
e := httperrors.NewInputParameterError("empty file")
httperrors.JsonClientError(w, e)
return
}
users := []jsonutils.JSONObject{}
names := map[string]bool{}
domains := map[string]string{}
users := []jsonutils.JSONDict{}
for _, row := range xlsx.GetRows("users")[1:] {
if len(row) < 3 {
log.Debugf("batchHostRegister row length too short (less than 3) %s", row)
for i, row := range rows[1:] {
name := row[0]
if len(name) == 0 {
e := httperrors.NewClientError("row %d name is empty", i+2)
httperrors.JsonClientError(w, e)
return
}
if _, ok := names[row[0]]; ok {
if _, ok := names[name]; ok {
e := httperrors.NewClientError("duplicate name %s", row[0])
httperrors.JsonClientError(w, e)
return
} else {
names[name] = true
_, err := modules.UsersV3.Get(s, name, nil)
if err == nil {
continue
}
}
domainId, ok := domains[row[1]]
@@ -230,14 +285,16 @@ func (mh *MiscHandler) DoBatchUserRegister(ctx context.Context, w http.ResponseW
}
user := jsonutils.NewDict()
user.Add(jsonutils.NewString(row[0]), "name")
user.Add(jsonutils.NewString(name), "name")
user.Add(jsonutils.NewString(domainId), "domain_id")
user.Add(jsonutils.NewString("OneCloud@2019"), "password")
if strings.ToLower(row[2]) == "true" {
if strings.ToLower(row[2]) == "true" || strings.ToLower(row[2]) == "1" {
user.Add(jsonutils.JSONTrue, "allow_web_console")
} else {
user.Add(jsonutils.JSONFalse, "allow_web_console")
}
users = append(users, user)
}
// batch create
@@ -245,7 +302,7 @@ func (mh *MiscHandler) DoBatchUserRegister(ctx context.Context, w http.ResponseW
for i := range users {
user := users[i]
userG.Go(func() error {
_, err := modules.Users.Create(s, &user)
_, err := modules.UsersV3.Create(s, user)
return err
})
}
@@ -271,7 +328,21 @@ func (mh *MiscHandler) getDownloadsHandler(ctx context.Context, w http.ResponseW
var content bytes.Buffer
switch template {
case "BatchHostRegister":
records := [][]string{{"MAC地址", "名称", "IPMI地址", "IPMI用户名", "IPMI密码"}}
records := [][]string{{HOST_MAC, HOST_NAME, HOST_IPMI_ADDR_OPTIONAL, HOST_IPMI_USERNAME_OPTIONAL, HOST_IPMI_PASSWORD_OPTIONAL}}
content, err = writeXlsx("hosts", records)
if err != nil {
httperrors.InternalServerError(w, "internal server error")
return
}
case "BatchHostISORegister":
records := [][]string{{HOST_NAME, HOST_IPMI_ADDR, HOST_IPMI_USERNAME, HOST_IPMI_PASSWORD, HOST_MNG_IP_ADDR}}
content, err = writeXlsx("hosts", records)
if err != nil {
httperrors.InternalServerError(w, "internal server error")
return
}
case "BatchHostPXERegister":
records := [][]string{{HOST_NAME, HOST_IPMI_ADDR, HOST_IPMI_USERNAME, HOST_IPMI_PASSWORD, HOST_MNG_IP_ADDR_OPTIONAL}}
content, err = writeXlsx("hosts", records)
if err != nil {
httperrors.InternalServerError(w, "internal server error")
@@ -304,7 +375,7 @@ func (mh *MiscHandler) getDownloadsHandler(ctx context.Context, w http.ResponseW
}
w.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
w.Header().Set("Content-Disposition", "Attachment; filename=hosts_template.xlsx")
w.Header().Set("Content-Disposition", "Attachment; filename=template.xlsx")
w.Write(content.Bytes())
return
}
+8 -31
View File
@@ -16,7 +16,6 @@ package modules
import (
"fmt"
"regexp"
"strings"
"yunion.io/x/jsonutils"
@@ -89,7 +88,7 @@ func (this *HostManager) GetIpmiInfo(s *mcclient.ClientSession, id string, param
return ret, nil
}
func parseHosts(data string) ([]jsonutils.JSONObject, string) {
func parseHosts(titles []string, data string) ([]jsonutils.JSONObject, string) {
msg := ""
hosts := strings.Split(data, "\n")
ret := []jsonutils.JSONObject{}
@@ -101,37 +100,15 @@ func parseHosts(data string) ([]jsonutils.JSONObject, string) {
}
fields := strings.Split(host, ",")
if len(fields) != 5 {
msg += fmt.Sprintf("第%d行: %s (格式不正确)\n", i, host)
continue
}
// mac address check
if match, err := regexp.MatchString(MACAddressPattern, fields[0]); err != nil || !match {
msg += fmt.Sprintf("第%d行: %s (Mac地址格式不正确)\n", i, host)
continue
}
// name check
if len(fields[1]) == 0 {
msg += fmt.Sprintf("第%d行: %s (名称不能为空)\n", i, host)
}
params := jsonutils.NewDict()
params.Add(jsonutils.NewString(fields[0]), "access_mac")
params.Add(jsonutils.NewString(fields[1]), "name")
params.Add(jsonutils.NewString("baremetal"), "host_type")
if len(fields[2]) > 0 {
params.Add(jsonutils.NewString(fields[2]), "ipmi_ip_addr")
}
if len(fields[3]) > 0 {
params.Add(jsonutils.NewString(fields[3]), "ipmi_username")
}
if len(fields[4]) > 0 {
params.Add(jsonutils.NewString(fields[4]), "ipmi_password")
for i := range fields {
field := fields[i]
if len(field) > 0 {
params.Add(jsonutils.NewString(field), titles[i])
}
}
ret = append(ret, params)
@@ -140,13 +117,13 @@ func parseHosts(data string) ([]jsonutils.JSONObject, string) {
return ret, msg
}
func (this *HostManager) DoBatchRegister(s *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
func (this *HostManager) DoBatchRegister(s *mcclient.ClientSession, titles []string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
data, err := params.GetString("hosts")
if err != nil {
return nil, err
}
hosts, msg := parseHosts(data)
hosts, msg := parseHosts(titles, data)
if len(msg) > 0 {
return nil, httperrors.NewInputParameterError(msg)
}