// Copyright 2019 Yunion // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hostman import ( "fmt" "strings" "time" execlient "yunion.io/x/executor/client" "yunion.io/x/log" "yunion.io/x/onecloud/pkg/appsrv" app_common "yunion.io/x/onecloud/pkg/cloudcommon/app" "yunion.io/x/onecloud/pkg/cloudcommon/cronman" common_options "yunion.io/x/onecloud/pkg/cloudcommon/options" "yunion.io/x/onecloud/pkg/cloudcommon/service" "yunion.io/x/onecloud/pkg/hostman/downloader" "yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver" "yunion.io/x/onecloud/pkg/hostman/guestman" "yunion.io/x/onecloud/pkg/hostman/guestman/guesthandlers" "yunion.io/x/onecloud/pkg/hostman/guestman/podhandlers" "yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient" "yunion.io/x/onecloud/pkg/hostman/hosthandler" "yunion.io/x/onecloud/pkg/hostman/hostinfo" "yunion.io/x/onecloud/pkg/hostman/hostinfo/hostpinger" "yunion.io/x/onecloud/pkg/hostman/hostmetrics" "yunion.io/x/onecloud/pkg/hostman/hostutils" "yunion.io/x/onecloud/pkg/hostman/options" "yunion.io/x/onecloud/pkg/hostman/storageman" "yunion.io/x/onecloud/pkg/hostman/storageman/diskhandlers" "yunion.io/x/onecloud/pkg/hostman/storageman/storagehandler" "yunion.io/x/onecloud/pkg/image/drivers/s3" losetupman "yunion.io/x/onecloud/pkg/util/losetup/manager" "yunion.io/x/onecloud/pkg/util/procutils" "yunion.io/x/onecloud/pkg/util/qemuimg" "yunion.io/x/onecloud/pkg/util/sysutils" ) type SHostService struct { *service.SServiceBase } func (host *SHostService) InitService() { options.Init() isRoot := sysutils.IsRootPermission() if !isRoot { log.Fatalf("host service must running with root permissions") } if len(options.HostOptions.DeployServerSocketPath) == 0 { log.Fatalf("missing deploy server socket path") } // options.HostOptions.EnableRbac = false // disable rbac // init base option for pid file host.SServiceBase.O = &options.HostOptions.BaseOptions log.Infof("exec socket path: %s", options.HostOptions.ExecutorSocketPath) if options.HostOptions.EnableRemoteExecutor { execlient.Init(options.HostOptions.ExecutorSocketPath) execlient.SetTimeoutSeconds(options.HostOptions.ExecutorConnectTimeoutSeconds) procutils.SetRemoteExecutor() } losetupman.Init() } func (host *SHostService) OnExitService() {} func (host *SHostService) RunService() { app := app_common.InitApp(&options.HostOptions.BaseOptions, false) cronManager := cronman.InitCronJobManager(false, options.HostOptions.CronJobWorkerCount, options.HostOptions.TimeZone) hostutils.Init() if err := qemuimg.SetPreallocation(options.HostOptions.Qcow2Preallocation); err != nil { log.Fatalf("failed set qemuimg preallocation to %s: %s", options.HostOptions.Qcow2Preallocation, err) } app_common.InitAuth(&options.HostOptions.CommonOptions, func() { log.Infof("Auth complete!!") }) common_options.StartOptionManager(&options.HostOptions.CommonOptions, options.HostOptions.ConfigSyncPeriodSeconds, "", "", common_options.OnCommonOptionsChange) hostInstance := hostinfo.Instance() if err := hostInstance.Init(app.GetContext()); err != nil { log.Errorf("Host instance init error: %s, wait 3 minutes to retry", err) time.Sleep(time.Minute * 3) log.Fatalf("Host instance init error: %s, reboot now", err) } deployclient.Init(options.HostOptions.DeployServerSocketPath) if err := storageman.Init(hostInstance); err != nil { log.Fatalf("Storage manager init error: %v", err) } initS3() var guestChan chan struct{} if err := guestman.Init(hostInstance, options.HostOptions.ServersPath, options.HostOptions.DeployConcurrent); err != nil { log.Fatalf("guest manager init error: %s", err) } guestman.GetGuestManager().InitQemuMaxCpus( hostInstance.GetQemuMachineInfoList(), hostInstance.GetKVMMaxCpus(), ) guestman.GetGuestManager().InitQemuMaxMems(uint(hostInstance.GetMemoryTotal())) if err := guestman.GetGuestManager().InitPythonPath(); err != nil { log.Fatalf("Guest manager init python path %s", err) } hostInstance.StartRegister(2) // <-hostinfo.Instance().IsRegistered // wait host and guest init var err error guestChan, err = guestman.GetGuestManager().Bootstrap() if err != nil { log.Fatalf("Guest manager Bootstrap %s", err) } // hostmetrics after guestmanager bootstrap hostmetrics.Init(hostInstance) hostmetrics.Start() fsdriver.Init("") hostPinger := hostpinger.NewHostPingTask(options.HostOptions.PingRegionInterval, hostInstance) if hostPinger != nil { go hostPinger.Start() } host.initHandlers(app) { cronManager.AddJobEveryFewDays( "CleanRecycleDiskFiles", 1, 3, 0, 0, storageman.CleanRecycleDiskfiles, false) cronManager.AddJobEveryFewDays( "CleanImageCachefiles", 1, 3, 0, 0, storageman.CleanImageCachefiles, options.HostOptions.ImageCacheCleanupOnStartup) cronManager.Start() } close(guestChan) app_common.ServeForeverWithCleanup(app, &options.HostOptions.BaseOptions, func() { if hostPinger != nil { hostPinger.Stop() } hostinfo.Stop() storageman.Stop() hostmetrics.Stop() guestman.Stop() hostutils.GetWorkManager().Stop() }) } func (host *SHostService) initHandlers(app *appsrv.Application) { guesthandlers.AddGuestTaskHandler("", app) storagehandler.AddStorageHandler("", app) diskhandlers.AddDiskHandler("", app) downloader.AddDownloadHandler("", app) podhandlers.AddPodHandlers("", app) //kubehandlers.AddKubeAgentHandler("", app) hosthandler.AddHostHandler("", app) app_common.ExportOptionsHandler(app, &options.HostOptions) } const DEFAULT_SCREENDUMP_S3_BUCKET = "onecloud-screendump-new" func initS3() { url := options.HostOptions.S3Endpoint if len(url) == 0 { return } if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") { prefix := "http://" if options.HostOptions.S3UseSSL { prefix = "https://" } url = prefix + url } if options.HostOptions.S3BucketName == "" { options.HostOptions.S3BucketName = DEFAULT_SCREENDUMP_S3_BUCKET } err := s3.Init( url, options.HostOptions.S3AccessKey, options.HostOptions.S3SecretKey, options.HostOptions.S3BucketName, options.HostOptions.S3UseSSL, "", ) if err != nil { log.Fatalf("failed init s3 client %s", err) } lifecycle := fmt.Sprintf( `%sEnabled%d`, options.HostOptions.S3BucketName, options.HostOptions.S3BucketLifecycleKeepDay, ) err = s3.SetBucketLifecycle(lifecycle) if err != nil { log.Fatalf("failed set bucket lifecycle %s", lifecycle) } } func StartService() { var srv = &SHostService{} srv.SServiceBase = &service.SServiceBase{ Service: srv, } srv.StartService() }