mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-21 14:19:49 +08:00
Merge pull request #10948 from rainzm/agent/fix
Makes the process of installing the agent more rigorous
This commit is contained in:
@@ -28,9 +28,11 @@ import (
|
||||
ansible_api "yunion.io/x/onecloud/pkg/apis/ansible"
|
||||
cloudproxy_api "yunion.io/x/onecloud/pkg/apis/cloudproxy"
|
||||
comapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
devtool_api "yunion.io/x/onecloud/pkg/apis/devtool"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/devtool/models"
|
||||
"yunion.io/x/onecloud/pkg/devtool/utils"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
@@ -45,23 +47,36 @@ func init() {
|
||||
taskman.RegisterTask(ApplyScriptTask{})
|
||||
}
|
||||
|
||||
var ErrServerNotSshable = errors.Error("server is not sshable")
|
||||
|
||||
func (self *ApplyScriptTask) taskFailed(ctx context.Context, sa *models.SScriptApply, sar *models.SScriptApplyRecord, err error) {
|
||||
err = sa.StopApply(self.UserCred, sar, false, err.Error())
|
||||
var failCode string
|
||||
switch errors.Cause(err) {
|
||||
case ErrServerNotSshable:
|
||||
failCode = devtool_api.SCRIPT_APPLY_RECORD_FAILCODE_SSHABLE
|
||||
case utils.ErrCannotReachInfluxbd:
|
||||
failCode = devtool_api.SCRIPT_APPLY_RECORD_FAILCODE_INFLUXDB
|
||||
default:
|
||||
failCode = devtool_api.SCRIPT_APPLY_RECORD_FAILCODE_OTHERS
|
||||
}
|
||||
err = sa.StopApply(self.UserCred, sar, false, failCode, err.Error())
|
||||
if err != nil {
|
||||
log.Errorf("unable to StopApply script %s to server %s", sa.ScriptId, sa.GuestId)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
return
|
||||
}
|
||||
// restart
|
||||
err = sa.StartApply(ctx, self.UserCred)
|
||||
if err != nil {
|
||||
log.Errorf("unable to StartApply script %s to server %s", sa.ScriptId, sa.GuestId)
|
||||
if failCode == devtool_api.SCRIPT_APPLY_RECORD_FAILCODE_OTHERS {
|
||||
// restart
|
||||
err = sa.StartApply(ctx, self.UserCred)
|
||||
if err != nil {
|
||||
log.Errorf("unable to StartApply script %s to server %s", sa.ScriptId, sa.GuestId)
|
||||
}
|
||||
}
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *ApplyScriptTask) taskSuccess(ctx context.Context, sa *models.SScriptApply, sar *models.SScriptApplyRecord) {
|
||||
err := sa.StopApply(self.UserCred, sar, true, "")
|
||||
err := sa.StopApply(self.UserCred, sar, true, "", "")
|
||||
if err != nil {
|
||||
log.Errorf("unable to StopApply script %s to server %s", sa.ScriptId, sa.GuestId)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
@@ -103,7 +118,11 @@ func (self *ApplyScriptTask) OnInit(ctx context.Context, obj db.IStandaloneModel
|
||||
return
|
||||
}
|
||||
if !sshable.ok {
|
||||
self.taskFailed(ctx, sa, sar, fmt.Errorf("server %s is not sshable: %s", serverDetail.Id, sshable.reason))
|
||||
var err error = ErrServerNotSshable
|
||||
if len(sshable.reason) > 0 {
|
||||
err = errors.Wrap(err, sshable.reason)
|
||||
}
|
||||
self.taskFailed(ctx, sa, sar, err)
|
||||
return
|
||||
}
|
||||
// make sure user
|
||||
@@ -116,49 +135,79 @@ func (self *ApplyScriptTask) OnInit(ctx context.Context, obj db.IStandaloneModel
|
||||
default:
|
||||
user = "cloudroot"
|
||||
}
|
||||
// create local forward
|
||||
createP := jsonutils.NewDict()
|
||||
createP.Set("type", jsonutils.NewString(cloudproxy_api.FORWARD_TYPE_LOCAL))
|
||||
createP.Set("remote_port", jsonutils.NewInt(22))
|
||||
createP.Set("server_id", jsonutils.NewString(serverDetail.Id))
|
||||
|
||||
forward, err := cloudproxy.Forwards.PerformClassAction(session, "create-from-server", createP)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, sa, sar, errors.Wrapf(err, "fail to create local forward from server %q", serverDetail.Id))
|
||||
return
|
||||
var host ansible_api.AnsibleHost
|
||||
var forwardId string
|
||||
if len(sshable.proxyEndpointId) == 0 {
|
||||
host = ansible_api.AnsibleHost{
|
||||
User: user,
|
||||
IP: sshable.host,
|
||||
Port: sshable.port,
|
||||
Name: serverDetail.Name,
|
||||
}
|
||||
} else {
|
||||
// create local forward
|
||||
createP := jsonutils.NewDict()
|
||||
createP.Set("type", jsonutils.NewString(cloudproxy_api.FORWARD_TYPE_LOCAL))
|
||||
createP.Set("remote_port", jsonutils.NewInt(22))
|
||||
createP.Set("server_id", jsonutils.NewString(serverDetail.Id))
|
||||
|
||||
forward, err := cloudproxy.Forwards.PerformClassAction(session, "create-from-server", createP)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, sa, sar, errors.Wrapf(err, "fail to create local forward from server %q", serverDetail.Id))
|
||||
return
|
||||
}
|
||||
|
||||
port, _ := forward.Int("bind_port")
|
||||
forwardId, _ = forward.GetString("id")
|
||||
agentId, _ := forward.GetString("proxy_agent_id")
|
||||
agent, err := cloudproxy.ProxyAgents.Get(session, agentId, nil)
|
||||
if err != nil {
|
||||
self.clearLocalForward(session, forwardId)
|
||||
self.taskFailed(ctx, sa, sar, errors.Wrapf(err, "fail to get proxy agent %q", agentId))
|
||||
return
|
||||
}
|
||||
address, _ := agent.GetString("advertise_addr")
|
||||
// check proxy forward
|
||||
if ok := self.ensureLocalForwardWork(address, int(port)); !ok {
|
||||
self.clearLocalForward(session, forwardId)
|
||||
self.taskFailed(ctx, sa, sar, errors.Error("The created local forward is actually not usable"))
|
||||
return
|
||||
}
|
||||
host = ansible_api.AnsibleHost{
|
||||
User: user,
|
||||
IP: address,
|
||||
Port: int(port),
|
||||
Name: serverDetail.Name,
|
||||
}
|
||||
}
|
||||
|
||||
port, _ := forward.Int("bind_port")
|
||||
forwardId, _ := forward.GetString("id")
|
||||
agentId, _ := forward.GetString("proxy_agent_id")
|
||||
agent, err := cloudproxy.ProxyAgents.Get(session, agentId, nil)
|
||||
if err != nil {
|
||||
self.clearLocalForward(session, forwardId)
|
||||
self.taskFailed(ctx, sa, sar, errors.Wrapf(err, "fail to get proxy agent %q", agentId))
|
||||
return
|
||||
}
|
||||
address, _ := agent.GetString("advertise_addr")
|
||||
host := ansible_api.AnsibleHost{
|
||||
User: user,
|
||||
IP: address,
|
||||
Port: int(port),
|
||||
Name: serverDetail.Name,
|
||||
}
|
||||
// genrate args
|
||||
params = jsonutils.NewDict()
|
||||
params.Set("args", sa.Args)
|
||||
if len(sa.ArgsGenerator) == 0 {
|
||||
params.Set("args", sa.Args)
|
||||
} else {
|
||||
generator, ok := utils.GetArgGenerator(sa.ArgsGenerator)
|
||||
if !ok {
|
||||
params.Set("args", sa.Args)
|
||||
}
|
||||
arg, err := generator(ctx, sa.GuestId, sshable.proxyEndpointId, &host)
|
||||
if err != nil {
|
||||
self.clearLocalForward(session, forwardId)
|
||||
self.taskFailed(ctx, sa, sar, err)
|
||||
return
|
||||
}
|
||||
params.Set("args", jsonutils.Marshal(arg))
|
||||
}
|
||||
|
||||
params.Set("host", jsonutils.Marshal(host))
|
||||
|
||||
// fetch ansible playbook reference id
|
||||
updateData := jsonutils.NewDict()
|
||||
updateData.Set("script_apply_record_id", jsonutils.NewString(sar.GetId()))
|
||||
updateData.Set("proxy_forward_id", jsonutils.NewString(forwardId))
|
||||
|
||||
// check proxy forward
|
||||
if ok := self.ensureLocalForwardWork(address, int(port)); !ok {
|
||||
self.clearLocalForward(session, forwardId)
|
||||
self.taskFailed(ctx, sa, sar, errors.Error("The created local forward is actually not usable"))
|
||||
return
|
||||
}
|
||||
self.SetStage("OnAnsiblePlaybookComplete", updateData)
|
||||
|
||||
// Inject Task Header
|
||||
session.Header = self.GetTaskRequestHeader()
|
||||
_, err = modules.AnsiblePlaybookReference.PerformAction(session, s.PlaybookReferenceId, "run", params)
|
||||
@@ -170,38 +219,59 @@ func (self *ApplyScriptTask) OnInit(ctx context.Context, obj db.IStandaloneModel
|
||||
}
|
||||
|
||||
type sSSHable struct {
|
||||
user string
|
||||
ok bool
|
||||
reason string
|
||||
|
||||
user string
|
||||
|
||||
proxyEndpointId string
|
||||
proxyAgentId string
|
||||
|
||||
host string
|
||||
port int
|
||||
}
|
||||
|
||||
// func (self *ApplyScriptTask) ansibleHost(session modules.SS)
|
||||
|
||||
func (self *ApplyScriptTask) checkSshable(session *mcclient.ClientSession, serverId string) (sSSHable, error) {
|
||||
data, err := modules.Servers.GetSpecific(session, serverId, "sshable", nil)
|
||||
if err != nil {
|
||||
return sSSHable{}, errors.Wrapf(err, "unable to get sshable info of server %s", serverId)
|
||||
}
|
||||
log.Debugf("data to chech sshable:\n %s", data)
|
||||
methodTrieds, _ := data.GetArray("method_tried")
|
||||
sshable := sSSHable{}
|
||||
reasons := make([]string, 0, len(methodTrieds))
|
||||
for _, methodTried := range methodTrieds {
|
||||
ok, _ := methodTried.Bool("sshable")
|
||||
if ok {
|
||||
sshable.ok = true
|
||||
break
|
||||
var sshableOutput comapi.GuestSshableOutput
|
||||
err = data.Unmarshal(&sshableOutput)
|
||||
if err != nil {
|
||||
return sSSHable{}, errors.Wrapf(err, "unable to marshal output of server sshable: %s", data)
|
||||
}
|
||||
sshable := sSSHable{
|
||||
user: sshableOutput.User,
|
||||
}
|
||||
reasons := make([]string, 0, len(sshableOutput.MethodTried))
|
||||
for _, methodTried := range sshableOutput.MethodTried {
|
||||
if !methodTried.Sshable {
|
||||
reasons = append(reasons, methodTried.Reason)
|
||||
continue
|
||||
}
|
||||
sshable.ok = true
|
||||
switch methodTried.Method {
|
||||
case comapi.MethodDirect, comapi.MethodEIP, comapi.MethodDNAT:
|
||||
sshable.host = methodTried.Host
|
||||
sshable.port = methodTried.Port
|
||||
case comapi.MethodProxyForward:
|
||||
sshable.proxyAgentId = methodTried.ForwardDetails.ProxyAgentId
|
||||
sshable.proxyEndpointId = methodTried.ForwardDetails.ProxyEndpointId
|
||||
}
|
||||
reason, _ := methodTried.GetString("reason")
|
||||
reasons = append(reasons, reason)
|
||||
}
|
||||
if !sshable.ok {
|
||||
sshable.reason = strings.Join(reasons, "; ")
|
||||
} else {
|
||||
sshable.user, _ = data.GetString("user")
|
||||
}
|
||||
return sshable, nil
|
||||
}
|
||||
|
||||
func (self *ApplyScriptTask) clearLocalForward(s *mcclient.ClientSession, forwardId string) {
|
||||
if len(forwardId) == 0 {
|
||||
return
|
||||
}
|
||||
_, err := cloudproxy.Forwards.Delete(s, forwardId, nil)
|
||||
if err != nil {
|
||||
log.Errorf("unable to delete proxy forward %s", forwardId)
|
||||
|
||||
Reference in New Issue
Block a user