mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
baremetal: change ipmi user password
This commit is contained in:
@@ -23,3 +23,17 @@ type SGMapItem struct {
|
||||
Type int
|
||||
LinuxDeviceName string
|
||||
}
|
||||
|
||||
const (
|
||||
IPMIUserPrivUser = "USER"
|
||||
IPMIUSERPrivAdmin = "ADMINISTRATOR"
|
||||
)
|
||||
|
||||
type IPMIUser struct {
|
||||
Id int
|
||||
Name string
|
||||
Callin bool
|
||||
LinkAuth bool
|
||||
IPMIMsg bool
|
||||
Priv string
|
||||
}
|
||||
|
||||
@@ -1056,7 +1056,7 @@ func (b *SBaremetalInstance) enableWire(mac net.HardwareAddr, ipAddr string, nic
|
||||
if len(netType) > 0 {
|
||||
params.Add(jsonutils.NewString(netType), "net_type")
|
||||
}
|
||||
log.Errorf("enable net if params: %s", params.String())
|
||||
log.Infof("enable net if params: %s", params.String())
|
||||
return modules.Hosts.PerformAction(session, b.GetId(), "enable-netif", params)
|
||||
}
|
||||
|
||||
|
||||
@@ -113,11 +113,18 @@ func (task *sBaremetalPrepareTask) prepareBaremetalInfo(cli *ssh.Client) (*barem
|
||||
}
|
||||
|
||||
return &baremetalPrepareInfo{
|
||||
sysInfo, cpuInfo, dmiCPUInfo, memInfo, nicsInfo, diskInfo, storageDriver, ipmiInfo,
|
||||
sysInfo,
|
||||
cpuInfo,
|
||||
dmiCPUInfo,
|
||||
memInfo,
|
||||
nicsInfo,
|
||||
diskInfo,
|
||||
storageDriver,
|
||||
ipmiInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (task *sBaremetalPrepareTask) ipmiNicDHCP(cli *ssh.Client, i *baremetalPrepareInfo) error {
|
||||
func (task *sBaremetalPrepareTask) configIPMISetting(cli *ssh.Client, i *baremetalPrepareInfo) error {
|
||||
if !i.ipmiInfo.Present {
|
||||
return nil
|
||||
}
|
||||
@@ -153,9 +160,11 @@ func (task *sBaremetalPrepareTask) ipmiNicDHCP(cli *ssh.Client, i *baremetalPrep
|
||||
Speed: 100,
|
||||
Mtu: 1500,
|
||||
}
|
||||
task.sendNicInfo(ipmiNic, -1, types.NIC_TYPE_IPMI, true, "")
|
||||
if err := task.sendNicInfo(ipmiNic, -1, types.NIC_TYPE_IPMI, true, ""); err != nil {
|
||||
log.Errorf("Send IPMI nic %#v info: %v", ipmiNic, err)
|
||||
}
|
||||
rootId := ipmitool.GetRootId(ipmiSysInfo)
|
||||
err = ipmitool.SetLanUserPasswd(sshIPMI, lanChannel, rootId, ipmiUser, ipmiPasswd)
|
||||
err = ipmitool.CreateOrSetAdminUser(sshIPMI, lanChannel, rootId, ipmiUser, ipmiPasswd)
|
||||
if err != nil {
|
||||
// ignore the error
|
||||
log.Errorf("Lan channel %d set user password error: %v", lanChannel, err)
|
||||
@@ -197,7 +206,7 @@ func (task *sBaremetalPrepareTask) ipmiNicDHCP(cli *ssh.Client, i *baremetalPrep
|
||||
if err != nil {
|
||||
log.Errorf("Set lan channel %d dhcp error: %v", lanChannel, err)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
time.Sleep(2 * time.Second)
|
||||
nic := task.baremetal.GetIPMINic(conf.Mac)
|
||||
maxTries := 180 // wait 3 minutes
|
||||
for tried := 0; nic != nil && nic.IpAddr == "" && tried < maxTries; tried++ {
|
||||
@@ -208,9 +217,11 @@ func (task *sBaremetalPrepareTask) ipmiNicDHCP(cli *ssh.Client, i *baremetalPrep
|
||||
if err != nil {
|
||||
log.Errorf("Do BMC reset error: %v", err)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
for tried := 0; nic != nil && nic.IpAddr == "" && tried < maxTries; tried++ {
|
||||
nic = task.baremetal.GetIPMINic(conf.Mac)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
if nic != nil && len(nic.IpAddr) == 0 {
|
||||
log.Errorf("DHCP wait IPMI address fail, retry ...")
|
||||
@@ -262,8 +273,8 @@ func (task *sBaremetalPrepareTask) DoPrepare(cli *ssh.Client) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// set ipmi nic DHCP
|
||||
if err = task.ipmiNicDHCP(cli, infos); err != nil {
|
||||
// set ipmi nic address and user password
|
||||
if err = task.configIPMISetting(cli, infos); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -550,8 +561,7 @@ func (task *sBaremetalPrepareTask) sendNicInfo(nic *types.SNicDevInfo, idx int,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.baremetal.SaveDesc(resp)
|
||||
return nil
|
||||
return task.baremetal.SaveDesc(resp)
|
||||
}
|
||||
|
||||
func (task *sBaremetalPrepareTask) sendStorageInfo(size int64) error {
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/profiles"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
@@ -307,17 +308,58 @@ func EnableLanAccess(exector IPMIExecutor, channel int) error {
|
||||
return setLanAccess(exector, channel, "on")
|
||||
}
|
||||
|
||||
func SetLanUserPasswd(exector IPMIExecutor, channel int, rootId int, user string, password string) error {
|
||||
func ListLanUsers(exector IPMIExecutor, channel int) ([]compute.IPMIUser, error) {
|
||||
args := newArgs("user", "list", channel)
|
||||
ret, err := ExecuteCommands(exector, args)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "list user at channel %d", channel)
|
||||
}
|
||||
return sysutils.ParseIPMIUser(ret), nil
|
||||
}
|
||||
|
||||
func CreateOrSetAdminUser(exector IPMIExecutor, channel int, rootId int, username string, password string) error {
|
||||
users, err := ListLanUsers(exector, channel)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "List users")
|
||||
}
|
||||
if len(users) == 0 {
|
||||
return errors.Errorf("Empty users at channel %d", channel)
|
||||
}
|
||||
var foundUser *compute.IPMIUser = nil
|
||||
for _, user := range users {
|
||||
tmp := user
|
||||
if user.Name == username {
|
||||
foundUser = &tmp
|
||||
break
|
||||
}
|
||||
}
|
||||
if foundUser == nil {
|
||||
minEmptyUserId := -1
|
||||
for _, user := range users {
|
||||
if user.Name == "" {
|
||||
minEmptyUserId = user.Id
|
||||
break
|
||||
}
|
||||
}
|
||||
if minEmptyUserId == -1 {
|
||||
log.Warningf("Not found min empty user id, use root id %d to set", rootId)
|
||||
minEmptyUserId = rootId
|
||||
}
|
||||
return SetIdUserPasswd(exector, channel, minEmptyUserId, username, password)
|
||||
}
|
||||
return SetLanUserAdminPasswd(exector, channel, foundUser.Id, password)
|
||||
}
|
||||
|
||||
func SetLanUserAdminPasswd(exector IPMIExecutor, channel int, id int, password string) error {
|
||||
var err error
|
||||
password, err = stage_stringutils.EscapeEchoString(password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("EscapeEchoString for password: %s, error: %v", password, err)
|
||||
}
|
||||
args := []Args{
|
||||
newArgs("user", "enable", rootId),
|
||||
newArgs("user", "set", "name", rootId, user),
|
||||
newArgs("user", "set", "password", rootId, fmt.Sprintf("\"%s\"", password)),
|
||||
newArgs("user", "priv", rootId, 4, channel),
|
||||
newArgs("user", "enable", id),
|
||||
newArgs("user", "set", "password", id, fmt.Sprintf("\"%s\"", password)),
|
||||
newArgs("user", "priv", id, 4, channel),
|
||||
}
|
||||
err = doActions(exector, "set_lan_user_password", args...)
|
||||
if err != nil {
|
||||
@@ -326,19 +368,27 @@ func SetLanUserPasswd(exector IPMIExecutor, channel int, rootId int, user string
|
||||
args = []Args{newArgs(
|
||||
"raw", "0x06", "0x43",
|
||||
fmt.Sprintf("0x%02x", 0xb0+channel),
|
||||
fmt.Sprintf("0x%02x", rootId), "0x04", "0x00")}
|
||||
fmt.Sprintf("0x%02x", id), "0x04", "0x00")}
|
||||
err = doActions(exector, "set_lan_user_password2", args...)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
args = []Args{newArgs(
|
||||
"channel", "setaccess", channel,
|
||||
rootId, "link=on", "ipmi=on",
|
||||
id, "link=on", "ipmi=on",
|
||||
"callin=on", "privilege=4",
|
||||
)}
|
||||
return doActions(exector, "set_lan_user_password3", args...)
|
||||
}
|
||||
|
||||
func SetIdUserPasswd(exector IPMIExecutor, channel int, id int, user string, password string) error {
|
||||
args := newArgs("user", "set", "name", id, user)
|
||||
if err := doActions(exector, fmt.Sprintf("set_id%d_name", id), args); err != nil {
|
||||
return errors.Wrapf(err, "change root id %d to name %s", id, user)
|
||||
}
|
||||
return SetLanUserAdminPasswd(exector, channel, id, password)
|
||||
}
|
||||
|
||||
func SetLanPasswd(exector IPMIExecutor, rootId int, password string) error {
|
||||
password, err := stringutils2.EscapeEchoString(password)
|
||||
if err != nil {
|
||||
|
||||
@@ -50,6 +50,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/httputils"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
"yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
)
|
||||
|
||||
/*
|
||||
@@ -2594,6 +2595,10 @@ func (manager *SHostManager) ValidateCreateData(ctx context.Context, userCred mc
|
||||
if len(ipmiIpAddr) > 0 && !NetworkManager.IsValidOnPremiseNetworkIP(ipmiIpAddr) {
|
||||
return nil, httperrors.NewInputParameterError("%s is out of network IP ranges", ipmiIpAddr)
|
||||
}
|
||||
ipmiPasswd, _ := ipmiInfo.GetString("password")
|
||||
if len(ipmiPasswd) > 0 && !seclib2.MeetComplxity(ipmiPasswd) {
|
||||
return nil, httperrors.NewWeakPasswordError()
|
||||
}
|
||||
return manager.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
|
||||
}
|
||||
|
||||
|
||||
@@ -311,3 +311,34 @@ func Start(closeFd bool, args ...string) (p *os.Process, err error) {
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func ParseIPMIUser(lines []string) []compute.IPMIUser {
|
||||
ret := make([]compute.IPMIUser, 0)
|
||||
for _, l := range lines {
|
||||
if strings.HasPrefix(l, "ID") {
|
||||
continue
|
||||
}
|
||||
fields := strings.Fields(l)
|
||||
if strings.Contains(l, "Empty User") {
|
||||
id, err := strconv.Atoi(fields[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, compute.IPMIUser{Id: id})
|
||||
continue
|
||||
}
|
||||
if len(fields) != 6 {
|
||||
continue
|
||||
}
|
||||
id, err := strconv.Atoi(fields[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, compute.IPMIUser{
|
||||
Id: id,
|
||||
Name: fields[1],
|
||||
Priv: fields[5],
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -401,3 +401,57 @@ func TestParseSGMap(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseIPMIUser(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
want []compute.IPMIUser
|
||||
}{
|
||||
{
|
||||
name: "empty line",
|
||||
args: []string{"ID Name Callin Link Auth IPMI Msg Channel Priv Limit"},
|
||||
want: []compute.IPMIUser{},
|
||||
},
|
||||
{
|
||||
name: "users",
|
||||
args: []string{
|
||||
"ID Name Callin Link Auth IPMI Msg Channel Priv Limit",
|
||||
"1 root true false true ADMINISTRATOR",
|
||||
"2 admin true false true ADMINISTRATOR",
|
||||
"3 true false true USER",
|
||||
"4 (Empty User) true false false NO ACCESS",
|
||||
"5 (Empty User) true false false NO ACCESS",
|
||||
},
|
||||
want: []compute.IPMIUser{
|
||||
{
|
||||
Id: 1,
|
||||
Name: "root",
|
||||
Priv: "ADMINISTRATOR",
|
||||
},
|
||||
{
|
||||
Id: 2,
|
||||
Name: "admin",
|
||||
Priv: "ADMINISTRATOR",
|
||||
},
|
||||
{
|
||||
Id: 4,
|
||||
Name: "",
|
||||
Priv: "",
|
||||
},
|
||||
{
|
||||
Id: 5,
|
||||
Name: "",
|
||||
Priv: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := ParseIPMIUser(tt.args); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("ParseIPMIUser() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user