From ecf61f6ea0cbd7282e9d96af57f5b57dcdded466 Mon Sep 17 00:00:00 2001 From: Zexi Li Date: Mon, 19 Sep 2022 19:16:15 +0800 Subject: [PATCH] feat(baremetal,region): support disable_image_cache for baremetalagent --- cmd/climc/shell/compute/baremetalagents.go | 143 ++++++++++++--------- pkg/baremetal/agent.go | 6 +- pkg/baremetal/manager.go | 31 ++++- pkg/baremetal/tasks/basedeploy.go | 4 + pkg/baremetal/tasks/cdrom.go | 2 +- pkg/baremetal/tasks/create.go | 2 +- pkg/baremetal/tasks/interface.go | 2 +- pkg/baremetal/tasks/rebuild.go | 2 +- pkg/baremetal/types/types.go | 4 +- pkg/baremetal/utils/grub/grub.go | 2 + pkg/compute/guestdrivers/baremetals.go | 19 +++ pkg/compute/hostdrivers/baremetal.go | 22 +++- pkg/compute/models/baremetalagents.go | 23 +++- pkg/compute/models/hosts.go | 6 +- 14 files changed, 189 insertions(+), 79 deletions(-) diff --git a/cmd/climc/shell/compute/baremetalagents.go b/cmd/climc/shell/compute/baremetalagents.go index 1d014dac96..802dd9527a 100644 --- a/cmd/climc/shell/compute/baremetalagents.go +++ b/cmd/climc/shell/compute/baremetalagents.go @@ -17,69 +17,90 @@ package compute import ( "yunion.io/x/jsonutils" - "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/cmd/climc/shell" modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute" "yunion.io/x/onecloud/pkg/mcclient/options" ) -func init() { - type BaremetalAgentListOptions struct { - options.BaseListOptions - } - R(&BaremetalAgentListOptions{}, "agent-list", "List all agent", func(s *mcclient.ClientSession, args *BaremetalAgentListOptions) error { - var params *jsonutils.JSONDict - { - var err error - params, err = args.BaseListOptions.Params() - if err != nil { - return err - - } - } - result, err := modules.Baremetalagents.List(s, params) - if err != nil { - return err - } - printList(result, modules.Baremetalagents.GetColumns(s)) - return nil - }) - - type BaremetalAgentOpsOperations struct { - ID string `help:"ID or name of agent"` - } - R(&BaremetalAgentOpsOperations{}, "agent-show", "Show details of an agent", func(s *mcclient.ClientSession, args *BaremetalAgentOpsOperations) error { - result, err := modules.Baremetalagents.Get(s, args.ID, nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - - R(&BaremetalAgentOpsOperations{}, "agent-enable", "Enable agent", func(s *mcclient.ClientSession, args *BaremetalAgentOpsOperations) error { - result, err := modules.Baremetalagents.PerformAction(s, args.ID, "enable", nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - - R(&BaremetalAgentOpsOperations{}, "agent-disable", "Disable agent", func(s *mcclient.ClientSession, args *BaremetalAgentOpsOperations) error { - result, err := modules.Baremetalagents.PerformAction(s, args.ID, "disable", nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - - R(&BaremetalAgentOpsOperations{}, "agent-delete", "Delete agent", func(s *mcclient.ClientSession, args *BaremetalAgentOpsOperations) error { - result, err := modules.Baremetalagents.Delete(s, args.ID, nil) - if err != nil { - return err - } - printObject(result) - return nil - }) +type AgentListOptions struct { + options.BaseListOptions +} + +func (o AgentListOptions) Params() (jsonutils.JSONObject, error) { + return o.BaseListOptions.Params() +} + +func (o AgentListOptions) Description() string { + return "List all agent" +} + +type AgentOpsOperations struct { + ID string `help:"ID or name of agent"` +} + +func (o AgentOpsOperations) GetId() string { + return o.ID +} + +func (o AgentOpsOperations) Params() (jsonutils.JSONObject, error) { + return nil, nil +} + +type AgentShowOpt struct { + AgentOpsOperations +} + +func (o AgentShowOpt) Description() string { + return "Show details of an agent" +} + +type AgentEnableOpt struct { + AgentOpsOperations +} + +func (o AgentEnableOpt) Description() string { + return "Enable agent" +} + +type AgentDisableOpt struct { + AgentOpsOperations +} + +func (o AgentDisableOpt) Description() string { + return "Disable agent" +} + +type AgentDeleteOpt struct { + AgentOpsOperations +} + +func (o AgentDeleteOpt) Description() string { + return "Delete agent" +} + +type AgentEnableImageCacheOpt struct { + AgentOpsOperations +} + +func (o AgentEnableImageCacheOpt) Description() string { + return "Enable cache image of a agent" +} + +type AgentDisableImageCacheOpt struct { + AgentOpsOperations +} + +func (o AgentDisableImageCacheOpt) Description() string { + return "Disable cache image of a agent" +} + +func init() { + cmd := shell.NewResourceCmd(&modules.Baremetalagents).WithKeyword("agent") + cmd.List(new(AgentListOptions)) + cmd.Show(new(AgentShowOpt)) + cmd.Perform("enable", new(AgentEnableOpt)) + cmd.Perform("disable", new(AgentDisableOpt)) + cmd.Perform("enable-image-cache", new(AgentEnableImageCacheOpt)) + cmd.Perform("disable-image-cache", new(AgentDisableImageCacheOpt)) + cmd.Delete(new(AgentDeleteOpt)) } diff --git a/pkg/baremetal/agent.go b/pkg/baremetal/agent.go index e28f5c953e..ad178c8129 100644 --- a/pkg/baremetal/agent.go +++ b/pkg/baremetal/agent.go @@ -41,11 +41,9 @@ var ( baremetalAgent *SBaremetalAgent ) -// // BaremetalAgent has two types of address // - AccessAddress/Address: this is the address controller to accesss the agent // - ListenAddress: this is the address baremetal to access the agent -// type SBaremetalAgent struct { agent.SBaseAgent @@ -84,6 +82,10 @@ func (agent *SBaremetalAgent) GetAdminSession() *mcclient.ClientSession { return auth.GetAdminSession(context.TODO(), o.Options.Region) } +func (agent *SBaremetalAgent) GetPublicAdminSession() *mcclient.ClientSession { + return auth.GetAdminSessionWithPublic(context.TODO(), o.Options.Region) +} + func (agent *SBaremetalAgent) GetListenIP() (net.IP, error) { return agent.FindListenIP(o.Options.ListenAddress) } diff --git a/pkg/baremetal/manager.go b/pkg/baremetal/manager.go index 5d26e8b716..5d0b5266b4 100644 --- a/pkg/baremetal/manager.go +++ b/pkg/baremetal/manager.go @@ -41,6 +41,7 @@ import ( "yunion.io/x/onecloud/pkg/apis" api "yunion.io/x/onecloud/pkg/apis/compute" + apiidenty "yunion.io/x/onecloud/pkg/apis/identity" o "yunion.io/x/onecloud/pkg/baremetal/options" "yunion.io/x/onecloud/pkg/baremetal/profiles" "yunion.io/x/onecloud/pkg/baremetal/pxe" @@ -101,6 +102,10 @@ func (m *SBaremetalManager) GetClientSession() *mcclient.ClientSession { return m.Agent.GetAdminSession() } +func (m *SBaremetalManager) GetPublicClientSession() *mcclient.ClientSession { + return m.Agent.GetPublicAdminSession() +} + func (m *SBaremetalManager) GetZoneId() string { return m.Agent.Zone.Id } @@ -550,6 +555,10 @@ func (b *SBaremetalInstance) GetClientSession() *mcclient.ClientSession { return b.manager.GetClientSession() } +func (b *SBaremetalInstance) GetPublicClientSession() *mcclient.ClientSession { + return b.manager.GetPublicClientSession() +} + func (b *SBaremetalInstance) Keyword() string { return "host" } @@ -1062,7 +1071,15 @@ func (b *SBaremetalInstance) getTftpFileUrl(filename string) string { return fmt.Sprintf("http://%s/tftp/%s", endpoint, filename) } -func (b *SBaremetalInstance) GetImageCacheUrl() string { +func (b *SBaremetalInstance) GetImageUrl(disableImageCache bool) string { + if disableImageCache { + url, err := b.GetPublicClientSession().GetServiceURL(apis.SERVICE_TYPE_IMAGE, apiidenty.EndpointInterfacePublic, "") + if err != nil { + log.Errorf("Get image public url: %v", err) + return "" + } + return url + } serverIP, err := b.manager.Agent.GetDHCPServerIP() if err != nil { log.Errorf("Get http file server: %v", err) @@ -2665,10 +2682,10 @@ func replaceHostAddr(urlStr string, addr string) string { return urlComp.String() } -func (s *SBaremetalServer) doCreateRoot(term *ssh.Client, devName string) error { +func (s *SBaremetalServer) doCreateRoot(term *ssh.Client, devName string, disableImageCache bool) error { session := s.baremetal.GetClientSession() token := session.GetToken().GetTokenString() - urlStr := s.baremetal.GetImageCacheUrl() + urlStr := s.baremetal.GetImageUrl(disableImageCache) imageId := s.GetRootTemplateId() cmd := fmt.Sprintf("/lib/mos/rootcreate.sh %s %s %s %s", token, urlStr, imageId, devName) log.Infof("rootcreate cmd: %q", cmd) @@ -2678,7 +2695,7 @@ func (s *SBaremetalServer) doCreateRoot(term *ssh.Client, devName string) error return nil } -func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client) ([]*disktool.Partition, error) { +func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) ([]*disktool.Partition, error) { raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false) if err != nil { return nil, err @@ -2711,7 +2728,7 @@ func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term if len(rootImageId) > 0 { rootDisk := disks[0] rootSize, _ := rootDisk.Int("size") - err = s.doCreateRoot(term, tool.GetRootDisk().GetDevName()) + err = s.doCreateRoot(term, tool.GetRootDisk().GetDevName(), disableImageCache) if err != nil { return nil, errors.Wrap(err, "Failed to create root") } @@ -2753,7 +2770,7 @@ func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term return tool.GetPartitions(), nil } -func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client) ([]*disktool.Partition, error) { +func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) ([]*disktool.Partition, error) { // raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false) // if err != nil { // return nil, err @@ -2784,7 +2801,7 @@ func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, te rootDisk := disks[0] rootSize, _ := rootDisk.Int("size") rd := tool.GetRootDisk() - err := s.doCreateRoot(term, rd.GetDevName()) + err := s.doCreateRoot(term, rd.GetDevName(), disableImageCache) if err != nil { return nil, fmt.Errorf("Failed to create root: %v", err) } diff --git a/pkg/baremetal/tasks/basedeploy.go b/pkg/baremetal/tasks/basedeploy.go index fbf83cd324..63bf7f0afb 100644 --- a/pkg/baremetal/tasks/basedeploy.go +++ b/pkg/baremetal/tasks/basedeploy.go @@ -69,6 +69,10 @@ func (self *SBaremetalServerBaseDeployTask) NeedPXEBoot() bool { return self.needPXEBoot } +func (self *SBaremetalServerBaseDeployTask) IsDisableImageCache() bool { + return jsonutils.QueryBoolean(self.data, "disable_image_cache", false) +} + func (self *SBaremetalServerBaseDeployTask) GetFinishAction() string { if self.data != nil { action, _ := self.data.GetString("on_finish") diff --git a/pkg/baremetal/tasks/cdrom.go b/pkg/baremetal/tasks/cdrom.go index a8ca8636e1..565189a4b2 100644 --- a/pkg/baremetal/tasks/cdrom.go +++ b/pkg/baremetal/tasks/cdrom.go @@ -97,7 +97,7 @@ func (self *SBaremetalCdromTask) DoInsertISO(ctx context.Context, args interface if !fileutils2.Exists(localImagePath) { return errors.Error("image not cached") } - imageBaseUrl := self.Baremetal.GetImageCacheUrl() + imageBaseUrl := self.Baremetal.GetImageUrl(true) if len(imageBaseUrl) == 0 { return errors.Error("empty image base url") } diff --git a/pkg/baremetal/tasks/create.go b/pkg/baremetal/tasks/create.go index 07dc560bb0..372785689b 100644 --- a/pkg/baremetal/tasks/create.go +++ b/pkg/baremetal/tasks/create.go @@ -61,7 +61,7 @@ func (self *SBaremetalServerCreateTask) DoDeploys(term *ssh.Client) (jsonutils.J return nil, self.onError(term, err) } time.Sleep(2 * time.Second) - parts, err := self.Baremetal.GetServer().DoPartitionDisk(tool, term) + parts, err := self.Baremetal.GetServer().DoPartitionDisk(tool, term, self.IsDisableImageCache()) if err != nil { return nil, self.onError(term, err) } diff --git a/pkg/baremetal/tasks/interface.go b/pkg/baremetal/tasks/interface.go index 829d6a7486..1212c2f206 100644 --- a/pkg/baremetal/tasks/interface.go +++ b/pkg/baremetal/tasks/interface.go @@ -62,7 +62,7 @@ type IBaremetal interface { GenerateBootISO() error SendNicInfo(nic *types.SNicDevInfo, idx int, nicType string, reset bool, ipAddr string, reserve bool) error DoNTPConfig() error - GetImageCacheUrl() string + GetImageUrl(needImageCache bool) string RemoveServer() InitializeServer(session *mcclient.ClientSession, name string) error diff --git a/pkg/baremetal/tasks/rebuild.go b/pkg/baremetal/tasks/rebuild.go index bc5e672937..ccba0cfe4c 100644 --- a/pkg/baremetal/tasks/rebuild.go +++ b/pkg/baremetal/tasks/rebuild.go @@ -55,7 +55,7 @@ func (self *SBaremetalServerRebuildTask) DoDeploys(term *ssh.Client) (jsonutils. if err != nil { return nil, errors.Wrap(err, "NewConfigedSSHPartitionTool") } - parts, err := self.Baremetal.GetServer().DoRebuildRootDisk(tool, term) + parts, err := self.Baremetal.GetServer().DoRebuildRootDisk(tool, term, self.IsDisableImageCache()) if err != nil { return nil, fmt.Errorf("Rebuild root disk: %v", err) } diff --git a/pkg/baremetal/types/types.go b/pkg/baremetal/types/types.go index 6f510dac35..b56de06bcd 100644 --- a/pkg/baremetal/types/types.go +++ b/pkg/baremetal/types/types.go @@ -31,9 +31,9 @@ type IBaremetalServer interface { DoDiskUnconfig(term *ssh.Client) error DoDiskConfig(term *ssh.Client) (*disktool.SSHPartitionTool, error) DoEraseDisk(term *ssh.Client) error - DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client) ([]*disktool.Partition, error) + DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) ([]*disktool.Partition, error) NewConfigedSSHPartitionTool(term *ssh.Client) (*disktool.SSHPartitionTool, error) - DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client) ([]*disktool.Partition, error) + DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) ([]*disktool.Partition, error) SyncPartitionSize(term *ssh.Client, parts []*disktool.Partition) ([]jsonutils.JSONObject, error) DoDeploy(tool *disktool.SSHPartitionTool, term *ssh.Client, data jsonutils.JSONObject, isInit bool) (jsonutils.JSONObject, error) SaveDesc(desc jsonutils.JSONObject) error diff --git a/pkg/baremetal/utils/grub/grub.go b/pkg/baremetal/utils/grub/grub.go index cb45532184..894be812a6 100644 --- a/pkg/baremetal/utils/grub/grub.go +++ b/pkg/baremetal/utils/grub/grub.go @@ -18,7 +18,9 @@ import "fmt" func GetYunionOSConfig(sleepTime int, httpSite, kernel string, kernelArgs string, initrd string) string { kernel = fmt.Sprintf("(http,${http_site})/tftp/%s", kernel) + // kernel = fmt.Sprintf("(tftp,10.127.100.2)/%s", kernel) initrd = fmt.Sprintf("(http,${http_site})/tftp/%s", initrd) + // initrd = fmt.Sprintf("(tftp,10.127.100.2)/%s", initrd) return fmt.Sprintf(` set timeout=%d set http_site=%s diff --git a/pkg/compute/guestdrivers/baremetals.go b/pkg/compute/guestdrivers/baremetals.go index ac5804344d..900bf629ac 100644 --- a/pkg/compute/guestdrivers/baremetals.go +++ b/pkg/compute/guestdrivers/baremetals.go @@ -500,6 +500,18 @@ func (self *SBaremetalGuestDriver) OnGuestDeployTaskDataReceived(ctx context.Con return nil } +func (self *SBaremetalGuestDriver) IsDisableImageCache(gst *models.SGuest) (bool, error) { + host, err := gst.GetHost() + if err != nil { + return false, errors.Wrapf(err, "Get guest %s(%s) host", gst.GetName(), gst.GetId()) + } + agent := host.GetAgent(api.AgentTypeBaremetal) + if agent == nil { + return false, errors.Wrapf(errors.ErrNotFound, "get host %s(%s) agent", host.GetName(), host.GetId()) + } + return agent.DisableImageCache, nil +} + func (self *SBaremetalGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error { config, err := guest.GetDeployConfigOnHost(ctx, task.GetUserCred(), host, task.GetParams()) if err != nil { @@ -515,6 +527,13 @@ func (self *SBaremetalGuestDriver) RequestDeployGuestOnHost(ctx context.Context, } else if val == "deploy" && jsonutils.QueryBoolean(task.GetParams(), "restart", false) { config.Set("on_finish", jsonutils.NewString("shutdown")) } + + disableCache, err := self.IsDisableImageCache(guest) + if err != nil { + return errors.Wrap(err, "check IsDisableImageCache") + } + config.Set("disable_image_cache", jsonutils.NewBool(disableCache)) + url := fmt.Sprintf("/baremetals/%s/servers/%s/%s", host.Id, guest.Id, val) headers := task.GetTaskRequestHeader() _, err = host.BaremetalSyncRequest(ctx, "POST", url, headers, config) diff --git a/pkg/compute/hostdrivers/baremetal.go b/pkg/compute/hostdrivers/baremetal.go index fa3e2e15ef..ddb99f4ba7 100644 --- a/pkg/compute/hostdrivers/baremetal.go +++ b/pkg/compute/hostdrivers/baremetal.go @@ -19,6 +19,7 @@ import ( "fmt" "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" @@ -43,12 +44,31 @@ func (self *SBaremetalHostDriver) GetHypervisor() string { return api.HYPERVISOR_BAREMETAL } +func (self *SBaremetalHostDriver) IsDisableImageCache(host *models.SHost) (bool, error) { + agent := host.GetAgent(api.AgentTypeBaremetal) + if agent == nil { + return false, errors.Wrapf(errors.ErrNotFound, "get host %s(%s) agent", host.GetName(), host.GetId()) + } + return agent.DisableImageCache, nil +} + func (self *SBaremetalHostDriver) CheckAndSetCacheImage(ctx context.Context, host *models.SHost, storageCache *models.SStoragecache, task taskman.ITask) error { input := api.CacheImageInput{} task.GetParams().Unmarshal(&input) _, err := models.CachedimageManager.FetchById(input.ImageId) if err != nil { - return err + return errors.Wrapf(err, "fetch cachedimage by image_id %s", input.ImageId) + } + + disableCache, err := self.IsDisableImageCache(host) + if err != nil { + return errors.Wrapf(err, "check disable image cache by host %s(%s)", host.GetName(), host.GetId()) + } + + // iso must be cached to use + if disableCache && input.Format != "iso" { + task.ScheduleRun(nil) + return nil } url := "/disks/image_cache" diff --git a/pkg/compute/models/baremetalagents.go b/pkg/compute/models/baremetalagents.go index e34d6dac31..44b35bdf48 100644 --- a/pkg/compute/models/baremetalagents.go +++ b/pkg/compute/models/baremetalagents.go @@ -50,7 +50,8 @@ type SBaremetalagent struct { Version string `width:"64" charset:"ascii" list:"admin" update:"admin" create:"admin_optional"` // Column(VARCHAR(64, charset='ascii')) - StoragecacheId string `width:"36" charset:"ascii" nullable:"true" list:"admin" get:"admin" update:"admin" create:"admin_optional"` + StoragecacheId string `width:"36" charset:"ascii" nullable:"true" list:"admin" get:"admin" update:"admin" create:"admin_optional"` + DisableImageCache bool `default:"false" list:"admin" create:"admin_optional" update:"admin"` } var BaremetalagentManager *SBaremetalagentManager @@ -154,6 +155,26 @@ func (self *SBaremetalagent) PerformDisable(ctx context.Context, userCred mcclie return nil, nil } +func (self *SBaremetalagent) PerformEnableImageCache(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + if self.DisableImageCache { + db.Update(self, func() error { + self.DisableImageCache = false + return nil + }) + } + return nil, nil +} + +func (self *SBaremetalagent) PerformDisableImageCache(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + if !self.DisableImageCache { + db.Update(self, func() error { + self.DisableImageCache = true + return nil + }) + } + return nil, nil +} + func (self *SBaremetalagent) PerformOnline(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { if self.Status == api.BAREMETAL_AGENT_OFFLINE { db.Update(self, func() error { diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index 9193c278a9..b18e853735 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -5392,8 +5392,12 @@ func (self *SHost) EsxiRequest(ctx context.Context, method httputils.THttpMethod return self.doAgentRequest(api.AgentTypeEsxi, ctx, method, url, headers, body) } +func (self *SHost) GetAgent(at api.TAgentType) *SBaremetalagent { + return BaremetalagentManager.GetAgent(at, self.ZoneId) +} + func (self *SHost) isAgentReady(agentType api.TAgentType) bool { - agent := BaremetalagentManager.GetAgent(agentType, self.ZoneId) + agent := self.GetAgent(agentType) if agent == nil { log.Errorf("%s ready: false", agentType) return false