mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 02:37:24 +08:00
Merge pull request #1603 from wanyaoqi/feature/wyq/storage-agent
host deploy agent
This commit is contained in:
@@ -0,0 +1 @@
|
||||
DESCRIPTION="Yunion Host Deploy Agent"
|
||||
@@ -12,4 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package sshkeys // import "yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
package main
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployserver"
|
||||
|
||||
func main() {
|
||||
deployer := deployserver.NewDeployService()
|
||||
deployer.StartService()
|
||||
}
|
||||
@@ -61,6 +61,7 @@ require (
|
||||
github.com/golang-plus/testing v1.0.0 // indirect
|
||||
github.com/golang-plus/uuid v1.0.0
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect
|
||||
github.com/golang/protobuf v1.3.1
|
||||
github.com/google/btree v1.0.0 // indirect
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf // indirect
|
||||
github.com/google/gopacket v1.1.17
|
||||
@@ -138,6 +139,7 @@ require (
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c // indirect
|
||||
google.golang.org/appengine v1.3.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20181218023534-67d6565462c5 // indirect
|
||||
google.golang.org/grpc v1.19.0
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2 // indirect
|
||||
|
||||
@@ -167,6 +167,8 @@ github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200j
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
|
||||
@@ -50,11 +50,11 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/disktool"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/ipmitool"
|
||||
raiddrivers "yunion.io/x/onecloud/pkg/baremetal/utils/raid/drivers"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs/sshpart"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
@@ -1704,18 +1704,19 @@ func (s *SBaremetalServer) SyncPartitionSize(term *ssh.Client, parts []*disktool
|
||||
}
|
||||
|
||||
func (s *SBaremetalServer) DoDeploy(term *ssh.Client, data jsonutils.JSONObject, isInit bool) (jsonutils.JSONObject, error) {
|
||||
publicKey := sshkeys.GetKeys(data)
|
||||
publicKey := deployapi.GetKeys(data)
|
||||
deploys, _ := data.GetArray("deploys")
|
||||
password, _ := data.GetString("password")
|
||||
resetPassword := jsonutils.QueryBoolean(data, "reset_password", false)
|
||||
if resetPassword && len(password) == 0 {
|
||||
password = seclib.RandomPassword(12)
|
||||
}
|
||||
deployInfo := guestfs.NewDeployInfo(publicKey, deploys, password, isInit, true, o.Options.LinuxDefaultRootUser, o.Options.WindowsDefaultAdminUser, false)
|
||||
deployInfo := deployapi.NewDeployInfo(publicKey, deployapi.JsonDeploysToStructs(deploys),
|
||||
password, isInit, true, o.Options.LinuxDefaultRootUser, o.Options.WindowsDefaultAdminUser, false)
|
||||
return s.deployFs(term, deployInfo)
|
||||
}
|
||||
|
||||
func (s *SBaremetalServer) deployFs(term *ssh.Client, deployInfo *guestfs.SDeployInfo) (jsonutils.JSONObject, error) {
|
||||
func (s *SBaremetalServer) deployFs(term *ssh.Client, deployInfo *deployapi.DeployInfo) (jsonutils.JSONObject, error) {
|
||||
raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -50,7 +50,7 @@ func GetNicDHCPConfig(
|
||||
|
||||
routes := make([][]string, 0)
|
||||
for _, route := range n.Routes {
|
||||
routes = append(routes, []string{route[0], route[1]})
|
||||
routes = append(routes, []string{route.Route[0], route.Route[1]})
|
||||
}
|
||||
|
||||
conf := &dhcp.ResponseConfig{
|
||||
|
||||
@@ -16,14 +16,18 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
"yunion.io/x/pkg/util/signalutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
type IService interface {
|
||||
@@ -38,6 +42,10 @@ type SServiceBase struct {
|
||||
O *options.BaseOptions
|
||||
}
|
||||
|
||||
func NewBaseService(service IService) *SServiceBase {
|
||||
return &SServiceBase{Service: service}
|
||||
}
|
||||
|
||||
func (s *SServiceBase) StartService() {
|
||||
defer s.Service.OnExitService()
|
||||
defer s.RemovePid()
|
||||
@@ -78,3 +86,15 @@ func (s *SServiceBase) RemovePid() {
|
||||
os.Remove(s.O.PidFile)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SServiceBase) SignalTrap(onExit func()) {
|
||||
// dump goroutine stack
|
||||
signalutils.RegisterSignal(func() {
|
||||
utils.DumpAllGoroutineStack(log.Logger().Out)
|
||||
}, syscall.SIGUSR1)
|
||||
if onExit != nil {
|
||||
quitSignals := []os.Signal{syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM}
|
||||
signalutils.RegisterSignal(onExit, quitSignals...)
|
||||
}
|
||||
signalutils.StartTrap()
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
// 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 sshkeys
|
||||
|
||||
import "yunion.io/x/jsonutils"
|
||||
|
||||
type SSHKeys struct {
|
||||
PublicKey string
|
||||
DeletePublicKey string
|
||||
AdminPublicKey string
|
||||
ProjectPublicKey string
|
||||
}
|
||||
|
||||
func GetKeys(data jsonutils.JSONObject) *SSHKeys {
|
||||
var ret = new(SSHKeys)
|
||||
ret.PublicKey, _ = data.GetString("public_key")
|
||||
ret.DeletePublicKey, _ = data.GetString("delete_public_key")
|
||||
ret.AdminPublicKey, _ = data.GetString("admin_public_key")
|
||||
ret.ProjectPublicKey, _ = data.GetString("project_public_key")
|
||||
return ret
|
||||
}
|
||||
@@ -18,6 +18,8 @@ import (
|
||||
"net"
|
||||
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -30,21 +32,21 @@ var (
|
||||
)
|
||||
|
||||
type SNic struct {
|
||||
Type string `json:"nic_type"`
|
||||
Domain string `json:"domain"`
|
||||
Wire string `json:"wire"`
|
||||
IpAddr string `json:"ip_addr"`
|
||||
WireId string `json:"wire_id"`
|
||||
NetId string `json:"net_id"`
|
||||
Rate int64 `json:"rate"`
|
||||
Mtu int64 `json:"mtu"`
|
||||
Mac string `json:"mac"`
|
||||
Dns string `json:"dns"`
|
||||
MaskLen int8 `json:"masklen"`
|
||||
Net string `json:"net"`
|
||||
Gateway string `json:"gateway"`
|
||||
LinkUp bool `json:"link_up"`
|
||||
Routes []SRoute `json:"routes,omitempty"`
|
||||
Type string `json:"nic_type"`
|
||||
Domain string `json:"domain"`
|
||||
Wire string `json:"wire"`
|
||||
IpAddr string `json:"ip_addr"`
|
||||
WireId string `json:"wire_id"`
|
||||
NetId string `json:"net_id"`
|
||||
Rate int64 `json:"rate"`
|
||||
Mtu int64 `json:"mtu"`
|
||||
Mac string `json:"mac"`
|
||||
Dns string `json:"dns"`
|
||||
MaskLen int8 `json:"masklen"`
|
||||
Net string `json:"net"`
|
||||
Gateway string `json:"gateway"`
|
||||
LinkUp bool `json:"link_up"`
|
||||
Routes []*deployapi.Routes `json:"routes,omitempty"`
|
||||
}
|
||||
|
||||
func (n SNic) GetNetMask() string {
|
||||
@@ -55,33 +57,8 @@ func (n SNic) GetMac() net.HardwareAddr {
|
||||
return getMac(n.Mac)
|
||||
}
|
||||
|
||||
type SRoute []string
|
||||
|
||||
type SServerNic struct {
|
||||
Name string `json:"name"`
|
||||
Index int `json:"index"`
|
||||
Bridge string `json:"bridge"`
|
||||
Domain string `json:"domain"`
|
||||
Ip string `json:"ip"`
|
||||
Vlan int `json:"vlan"`
|
||||
Driver string `json:"driver"`
|
||||
Masklen int `json:"masklen"`
|
||||
Virtual bool `json:"virtual"`
|
||||
Manual bool `json:"manual"`
|
||||
WireId string `json:"wire_id"`
|
||||
NetId string `json:"net_id"`
|
||||
Mac string `json:"mac"`
|
||||
BandWidth int `json:"bw"`
|
||||
Dns string `json:"dns"`
|
||||
Net string `json:"net"`
|
||||
Interface string `json:"interface"`
|
||||
Gateway string `json:"gateway"`
|
||||
Ifname string `json:"ifname"`
|
||||
Routes []SRoute `json:"routes,omitempty"`
|
||||
NicType string `json:"nic_type,omitempty"`
|
||||
LinkUp bool `json:"link_up,omitempty"`
|
||||
Mtu int64 `json:"mtu,omitempty"`
|
||||
TeamWith string `json:"team_with,omitempty"`
|
||||
*deployapi.Nic
|
||||
|
||||
TeamingMaster *SServerNic `json:"-"`
|
||||
TeamingSlaves []*SServerNic `json:"-"`
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
// 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 cloudprovider
|
||||
|
||||
type SServerSku struct {
|
||||
|
||||
@@ -225,17 +225,22 @@ func (self *SKVMHostDriver) RequestAllocateDiskOnStorage(ctx context.Context, ho
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
snapshotStorage := models.StorageManager.FetchStorageById(snapshot.StorageId)
|
||||
snapshotHost := snapshotStorage.GetMasterHost()
|
||||
if options.Options.SnapshotCreateDiskProtocol == "url" {
|
||||
content.Set("snapshot_url",
|
||||
jsonutils.NewString(fmt.Sprintf("%s/download/snapshots/%s/%s/%s",
|
||||
snapshotHost.ManagerUri, snapshotStorage.Id, snapshot.DiskId, snapshot.Id)))
|
||||
content.Set("snapshot_out_of_chain", jsonutils.NewBool(snapshot.OutOfChain))
|
||||
} else if options.Options.SnapshotCreateDiskProtocol == "fuse" {
|
||||
content.Set("snapshot_url", jsonutils.NewString(fmt.Sprintf("%s/snapshots/%s/%s",
|
||||
snapshotHost.GetFetchUrl(true), snapshot.DiskId, snapshot.Id)))
|
||||
if snapshotStorage.StorageType == api.STORAGE_LOCAL {
|
||||
snapshotHost := snapshotStorage.GetMasterHost()
|
||||
if options.Options.SnapshotCreateDiskProtocol == "url" {
|
||||
content.Set("snapshot_url",
|
||||
jsonutils.NewString(fmt.Sprintf("%s/download/snapshots/%s/%s/%s",
|
||||
snapshotHost.ManagerUri, snapshotStorage.Id, snapshot.DiskId, snapshot.Id)))
|
||||
content.Set("snapshot_out_of_chain", jsonutils.NewBool(snapshot.OutOfChain))
|
||||
} else if options.Options.SnapshotCreateDiskProtocol == "fuse" {
|
||||
content.Set("snapshot_url", jsonutils.NewString(fmt.Sprintf("%s/snapshots/%s/%s",
|
||||
snapshotHost.GetFetchUrl(true), snapshot.DiskId, snapshot.Id)))
|
||||
}
|
||||
content.Set("protocol", jsonutils.NewString(options.Options.SnapshotCreateDiskProtocol))
|
||||
} else {
|
||||
content.Set("snapshot_url", jsonutils.NewString(snapshot.Location))
|
||||
content.Set("protocol", jsonutils.NewString("location"))
|
||||
}
|
||||
content.Set("protocol", jsonutils.NewString(options.Options.SnapshotCreateDiskProtocol))
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/disks/%s/create/%s", storage.Id, disk.Id)
|
||||
|
||||
@@ -589,6 +589,14 @@ func (self *SDisk) AllowGetDetailsConvertSnapshot(ctx context.Context, userCred
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDetailsConvertSnapshot(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
needs, err := SnapshotManager.IsDiskSnapshotsNeedConvert(self.Id)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("Fetch snapshot count failed %s", err)
|
||||
}
|
||||
if !needs {
|
||||
return nil, httperrors.NewBadRequestError("Disk %s don't need convert snapshots", self.Id)
|
||||
}
|
||||
|
||||
deleteSnapshot := SnapshotManager.GetDiskFirstSnapshot(self.Id)
|
||||
if deleteSnapshot == nil {
|
||||
return nil, httperrors.NewNotFoundError("Can not get disk snapshot")
|
||||
@@ -651,7 +659,8 @@ func (self *SDisk) PerformCreateSnapshot(ctx context.Context, userCred mcclient.
|
||||
return nil, httperrors.NewBadRequestError("Disk dosen't attach guest??")
|
||||
}
|
||||
storage := self.GetStorage()
|
||||
if guests[0].Hypervisor == api.HYPERVISOR_KVM && storage.StorageType != api.STORAGE_LOCAL {
|
||||
if guests[0].Hypervisor == api.HYPERVISOR_KVM &&
|
||||
!utils.IsInStringArray(storage.StorageType, []string{api.STORAGE_LOCAL, api.STORAGE_NFS, api.STORAGE_GPFS}) {
|
||||
return nil, httperrors.NewBadRequestError("storage %s not support snapshot", storage.StorageType)
|
||||
}
|
||||
|
||||
|
||||
@@ -406,6 +406,16 @@ func (self *SSnapshotManager) GetDiskSnapshots(diskId string) []SSnapshot {
|
||||
return dest
|
||||
}
|
||||
|
||||
func (self *SSnapshotManager) IsDiskSnapshotsNeedConvert(diskId string) (bool, error) {
|
||||
count, err := self.Query().Equals("disk_id", diskId).
|
||||
In("status", []string{api.SNAPSHOT_READY, api.SNAPSHOT_DELETING}).
|
||||
Equals("out_of_chain", false).CountWithError()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return count >= options.Options.DefaultMaxSnapshotCount, nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotManager) GetDiskFirstSnapshot(diskId string) *SSnapshot {
|
||||
dest := &SSnapshot{}
|
||||
q := self.Query().SubQuery()
|
||||
@@ -476,8 +486,8 @@ func (self *SSnapshot) StartSnapshotDeleteTask(ctx context.Context, userCred mcc
|
||||
}
|
||||
|
||||
func (self *SSnapshot) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if self.RefCount > 0 {
|
||||
return fmt.Errorf("Snapshot reference(by disk) count > 0, can not delete")
|
||||
if len(self.ExternalId) == 0 && self.RefCount > 0 {
|
||||
return httperrors.NewBadRequestError("Snapshot reference(by disk) count > 0, can not delete")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -488,8 +498,10 @@ func (self *SSnapshot) CustomizeDelete(ctx context.Context, userCred mcclient.To
|
||||
}
|
||||
if len(self.ExternalId) == 0 {
|
||||
if self.CreatedBy == api.SNAPSHOT_MANUAL {
|
||||
if !self.FakeDeleted {
|
||||
if !self.OutOfChain && !self.FakeDeleted {
|
||||
return self.FakeDelete()
|
||||
} else if self.OutOfChain {
|
||||
return self.StartSnapshotDeleteTask(ctx, userCred, false, "")
|
||||
}
|
||||
_, err := SnapshotManager.GetConvertSnapshot(self)
|
||||
if err != nil {
|
||||
|
||||
@@ -65,7 +65,7 @@ func (self *DiskCreateTask) OnStorageCacheImageComplete(ctx context.Context, dis
|
||||
storage := disk.GetStorage()
|
||||
host := storage.GetMasterHost()
|
||||
db.OpsLog.LogEvent(disk, db.ACT_ALLOCATING, disk.GetShortDesc(ctx), self.GetUserCred())
|
||||
disk.SetStatus(self.GetUserCred(), api.DISK_STARTALLOC, "")
|
||||
disk.SetStatus(self.GetUserCred(), api.DISK_STARTALLOC, fmt.Sprintf("Disk start alloc use host %s(%s)", host.Name, host.Id))
|
||||
if len(disk.BackupStorageId) > 0 {
|
||||
self.SetStage("OnMasterStorageCreateDiskComplete", nil)
|
||||
} else {
|
||||
@@ -82,7 +82,7 @@ func (self *DiskCreateTask) OnMasterStorageCreateDiskComplete(ctx context.Contex
|
||||
storage := models.StorageManager.FetchStorageById(disk.BackupStorageId)
|
||||
host := storage.GetMasterHost()
|
||||
db.OpsLog.LogEvent(disk, db.ACT_BACKUP_ALLOCATING, disk.GetShortDesc(ctx), self.GetUserCred())
|
||||
disk.SetStatus(self.UserCred, api.DISK_BACKUP_STARTALLOC, "")
|
||||
disk.SetStatus(self.UserCred, api.DISK_BACKUP_STARTALLOC, fmt.Sprintf("Backup disk start alloc use host %s(%s)", host.Name, host.Id))
|
||||
self.SetStage("OnDiskReady", nil)
|
||||
if err := disk.StartAllocate(ctx, host, storage, self.GetTaskId(), self.GetUserCred(), rebuild, snapshot, self); err != nil {
|
||||
self.OnBackupAllocateFailed(ctx, disk, jsonutils.NewString(fmt.Sprintf("Backup disk alloctate failed: %s", err.Error())))
|
||||
|
||||
@@ -96,7 +96,7 @@ func (self *GuestSwitchToBackupTask) OnBackupGuestStoped(ctx context.Context, gu
|
||||
}
|
||||
|
||||
func (self *GuestSwitchToBackupTask) OnNewMasterStarted(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
self.OnComplete(ctx, guest, nil)
|
||||
}
|
||||
|
||||
func (self *GuestSwitchToBackupTask) OnFail(ctx context.Context, guest *models.SGuest, reason string) {
|
||||
@@ -106,13 +106,18 @@ func (self *GuestSwitchToBackupTask) OnFail(ctx context.Context, guest *models.S
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
func (self *GuestSwitchToBackupTask) OnComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
guest.SetMetadata(ctx, "__mirror_job_status", "", self.UserCred)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *GuestSwitchToBackupTask) OnSwitched(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
oldStatus, _ := self.Params.GetString("old_status")
|
||||
if utils.IsInStringArray(oldStatus, api.VM_RUNNING_STATUS) {
|
||||
self.SetStage("OnNewMasterStarted", nil)
|
||||
guest.StartGueststartTask(ctx, self.UserCred, nil, self.GetTaskId())
|
||||
} else {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
self.OnComplete(ctx, guest, nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +253,6 @@ func (self *SnapshotDeleteTask) OnDeleteSnapshot(ctx context.Context, snapshot *
|
||||
snapshot.RealDelete(ctx, self.UserCred)
|
||||
self.TaskComplete(ctx, snapshot, nil)
|
||||
} else {
|
||||
guest, _ := snapshot.GetGuest()
|
||||
var FakeDelete = false
|
||||
if snapshot.CreatedBy == api.SNAPSHOT_MANUAL && snapshot.FakeDeleted == false {
|
||||
FakeDelete = true
|
||||
@@ -266,8 +265,7 @@ func (self *SnapshotDeleteTask) OnDeleteSnapshot(ctx context.Context, snapshot *
|
||||
} else {
|
||||
snapshot.RealDelete(ctx, self.UserCred)
|
||||
}
|
||||
self.SetStage("TaskComplete", nil)
|
||||
guest.StartSyncstatus(ctx, self.UserCred, "")
|
||||
self.TaskComplete(ctx, snapshot, nil)
|
||||
}
|
||||
} else {
|
||||
snapshot.SetStatus(self.UserCred, api.SNAPSHOT_READY, "OnDeleteSnapshot")
|
||||
@@ -282,35 +280,40 @@ func (self *SnapshotDeleteTask) OnDeleteSnapshotFailed(ctx context.Context, snap
|
||||
|
||||
func (self *SnapshotDeleteTask) OnReloadDiskSnapshot(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
|
||||
if !jsonutils.QueryBoolean(data, "reopen", false) {
|
||||
log.Infof("OnDeleteSnapshot with no reopen")
|
||||
log.Infof("OnReloadDiskSnapshot with no reopen")
|
||||
return
|
||||
}
|
||||
if snapshot.CreatedBy == api.SNAPSHOT_AUTO {
|
||||
err := snapshot.RealDelete(ctx, self.UserCred)
|
||||
if err != nil {
|
||||
self.TaskFailed(ctx, snapshot, err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
err := snapshot.FakeDelete()
|
||||
if err != nil {
|
||||
self.TaskFailed(ctx, snapshot, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
self.SetStage("TaskComplete", nil)
|
||||
|
||||
guest, err := snapshot.GetGuest()
|
||||
if err != nil {
|
||||
self.SetStageFailed(ctx, err.Error())
|
||||
self.TaskFailed(ctx, snapshot, err.Error())
|
||||
return
|
||||
}
|
||||
guest.StartSyncstatus(ctx, self.UserCred, self.GetTaskId())
|
||||
if snapshot.FakeDeleted {
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("delete_snapshot", jsonutils.NewString(snapshot.Id))
|
||||
params.Set("disk_id", jsonutils.NewString(snapshot.DiskId))
|
||||
params.Set("auto_deleted", jsonutils.JSONTrue)
|
||||
self.SetStage("OnDeleteSnapshot", nil)
|
||||
err = guest.GetDriver().RequestDeleteSnapshot(ctx, guest, self, params)
|
||||
if err != nil {
|
||||
self.TaskFailed(ctx, snapshot, err.Error())
|
||||
}
|
||||
} else {
|
||||
self.TaskComplete(ctx, snapshot, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SnapshotDeleteTask) TaskComplete(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
|
||||
db.OpsLog.LogEvent(snapshot, db.ACT_SNAPSHOT_DELETE, snapshot.GetShortDesc(ctx), self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, snapshot, logclient.ACT_DELOCATE, nil, self.UserCred, true)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
guest, err := snapshot.GetGuest()
|
||||
if err != nil {
|
||||
log.Errorln(err.Error())
|
||||
return
|
||||
}
|
||||
guest.StartSyncstatus(ctx, self.UserCred, "")
|
||||
}
|
||||
|
||||
func (self *SnapshotDeleteTask) TaskFailed(ctx context.Context, snapshot *models.SSnapshot, reason string) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package storageman
|
||||
package diskutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -26,9 +26,9 @@ import (
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/hostman/diskutils/nbd"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman/nbd"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
"yunion.io/x/onecloud/pkg/util/qemuimg"
|
||||
@@ -0,0 +1 @@
|
||||
package diskutils // import "yunion.io/x/onecloud/pkg/hostman/diskutils"
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package storageman
|
||||
package diskutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -12,4 +12,4 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nbd // import "yunion.io/x/onecloud/pkg/hostman/storageman/nbd"
|
||||
package nbd // import "yunion.io/x/onecloud/pkg/hostman/diskutils/nbd"
|
||||
+55
-81
@@ -18,52 +18,15 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
|
||||
fsdriver "yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
)
|
||||
|
||||
type SDeployInfo struct {
|
||||
publicKey *sshkeys.SSHKeys
|
||||
deploys []jsonutils.JSONObject
|
||||
password string
|
||||
isInit bool
|
||||
enableTty bool
|
||||
defaultRootUser bool
|
||||
windowsDefaultAdminUser bool
|
||||
enableCloudInit bool
|
||||
}
|
||||
|
||||
func NewDeployInfo(
|
||||
publicKey *sshkeys.SSHKeys,
|
||||
deploys []jsonutils.JSONObject,
|
||||
password string,
|
||||
isInit bool,
|
||||
enableTty bool,
|
||||
defaultRootUser bool,
|
||||
windowsDefaultAdminUser bool,
|
||||
enableCloudInit bool,
|
||||
) *SDeployInfo {
|
||||
return &SDeployInfo{
|
||||
publicKey: publicKey,
|
||||
deploys: deploys,
|
||||
password: password,
|
||||
isInit: isInit,
|
||||
enableTty: enableTty,
|
||||
defaultRootUser: defaultRootUser,
|
||||
windowsDefaultAdminUser: windowsDefaultAdminUser,
|
||||
enableCloudInit: enableCloudInit,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *SDeployInfo) String() string {
|
||||
return fmt.Sprintf("deplys: %s, password %s, isInit: %v, enableTty: %v, defaultRootUser: %v, enableCloudInit: %v",
|
||||
d.deploys, d.password, d.isInit, d.enableTty, d.defaultRootUser, d.enableCloudInit)
|
||||
}
|
||||
|
||||
func DetectRootFs(part fsdriver.IDiskPartition) fsdriver.IRootFsDriver {
|
||||
for _, newDriverFunc := range fsdriver.GetRootfsDrivers() {
|
||||
d := newDriverFunc(part)
|
||||
@@ -91,53 +54,49 @@ func testRootfs(d fsdriver.IRootFsDriver) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func DeployGuestFs(
|
||||
rootfs fsdriver.IRootFsDriver,
|
||||
guestDesc *jsonutils.JSONDict,
|
||||
deployInfo *SDeployInfo,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
var ret = jsonutils.NewDict()
|
||||
var ips = make([]string, 0)
|
||||
var err error
|
||||
|
||||
hn, _ := guestDesc.GetString("name")
|
||||
domain, _ := guestDesc.GetString("domain")
|
||||
gid, _ := guestDesc.GetString("uuid")
|
||||
nics, _ := guestDesc.GetArray("nics")
|
||||
|
||||
partition := rootfs.GetPartition()
|
||||
releaseInfo := rootfs.GetReleaseInfo(partition)
|
||||
|
||||
func DoDeployGuestFs(rootfs fsdriver.IRootFsDriver, guestDesc *deployapi.GuestDesc, deployInfo *deployapi.DeployInfo,
|
||||
) (*deployapi.DeployGuestFsResponse, error) {
|
||||
var (
|
||||
err error
|
||||
ret = new(deployapi.DeployGuestFsResponse)
|
||||
ips = make([]string, 0)
|
||||
hn = guestDesc.Name
|
||||
domain = guestDesc.Domain
|
||||
gid = guestDesc.Uuid
|
||||
nics = guestDesc.Nics
|
||||
nicsStandby = guestDesc.NicsStandby
|
||||
partition = rootfs.GetPartition()
|
||||
releaseInfo = rootfs.GetReleaseInfo(partition)
|
||||
)
|
||||
for _, n := range nics {
|
||||
ip, _ := n.GetString("ip")
|
||||
var addr netutils.IPV4Addr
|
||||
if addr, err = netutils.NewIPV4Addr(ip); err != nil {
|
||||
if addr, err = netutils.NewIPV4Addr(n.Ip); err != nil {
|
||||
return nil, fmt.Errorf("Fail to get ip addr from %s: %v", n.String(), err)
|
||||
}
|
||||
if netutils.IsPrivate(addr) {
|
||||
ips = append(ips, ip)
|
||||
ips = append(ips, n.Ip)
|
||||
}
|
||||
}
|
||||
if releaseInfo != nil {
|
||||
ret.Set("distro", jsonutils.NewString(releaseInfo.Distro))
|
||||
ret.Distro = releaseInfo.Distro
|
||||
if len(releaseInfo.Version) > 0 {
|
||||
ret.Set("version", jsonutils.NewString(releaseInfo.Version))
|
||||
ret.Version = releaseInfo.Version
|
||||
}
|
||||
if len(releaseInfo.Arch) > 0 {
|
||||
ret.Set("arch", jsonutils.NewString(releaseInfo.Arch))
|
||||
ret.Arch = releaseInfo.Arch
|
||||
}
|
||||
if len(releaseInfo.Language) > 0 {
|
||||
ret.Set("language", jsonutils.NewString(releaseInfo.Language))
|
||||
ret.Language = releaseInfo.Language
|
||||
}
|
||||
}
|
||||
ret.Set("os", jsonutils.NewString(rootfs.GetOs()))
|
||||
ret.Os = rootfs.GetOs()
|
||||
|
||||
if IsPartitionReadonly(partition) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
if len(deployInfo.deploys) > 0 {
|
||||
if err = rootfs.DeployFiles(deployInfo.deploys); err != nil {
|
||||
if len(deployInfo.Deploys) > 0 {
|
||||
if err = rootfs.DeployFiles(deployInfo.Deploys); err != nil {
|
||||
return nil, fmt.Errorf("DeployFiles: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -150,7 +109,7 @@ func DeployGuestFs(
|
||||
if err = rootfs.DeployNetworkingScripts(partition, nics); err != nil {
|
||||
return nil, fmt.Errorf("DeployNetworkingScripts: %v", err)
|
||||
}
|
||||
if nicsStandby, e := guestDesc.GetArray("nics_standby"); e == nil {
|
||||
if len(nicsStandby) > 0 {
|
||||
if err = rootfs.DeployStandbyNetworkingScripts(partition, nics, nicsStandby); err != nil {
|
||||
return nil, fmt.Errorf("DeployStandbyNetworkingScripts: %v", err)
|
||||
}
|
||||
@@ -158,36 +117,35 @@ func DeployGuestFs(
|
||||
if err = rootfs.DeployUdevSubsystemScripts(partition); err != nil {
|
||||
return nil, fmt.Errorf("DeployUdevSubsystemScripts: %v", err)
|
||||
}
|
||||
if deployInfo.isInit {
|
||||
disks, _ := guestDesc.GetArray("disks")
|
||||
if err = rootfs.DeployFstabScripts(partition, disks); err != nil {
|
||||
if deployInfo.IsInit {
|
||||
if err = rootfs.DeployFstabScripts(partition, guestDesc.Disks); err != nil {
|
||||
return nil, fmt.Errorf("DeployFstabScripts: %v", err)
|
||||
}
|
||||
}
|
||||
if len(deployInfo.password) > 0 {
|
||||
if len(deployInfo.Password) > 0 {
|
||||
if account := rootfs.GetLoginAccount(partition,
|
||||
deployInfo.defaultRootUser, deployInfo.windowsDefaultAdminUser); len(account) > 0 {
|
||||
ret.Set("account", jsonutils.NewString(account))
|
||||
if err = rootfs.DeployPublicKey(partition, account, deployInfo.publicKey); err != nil {
|
||||
deployInfo.DefaultRootUser, deployInfo.WindowsDefaultAdminUser); len(account) > 0 {
|
||||
if err = rootfs.DeployPublicKey(partition, account, deployInfo.PublicKey); err != nil {
|
||||
return nil, fmt.Errorf("DeployPublicKey: %v", err)
|
||||
}
|
||||
var secret string
|
||||
if secret, err = rootfs.ChangeUserPasswd(partition, account, gid,
|
||||
deployInfo.publicKey.PublicKey, deployInfo.password); err != nil {
|
||||
deployInfo.PublicKey.PublicKey, deployInfo.Password); err != nil {
|
||||
return nil, fmt.Errorf("ChangeUserPasswd: %v", err)
|
||||
}
|
||||
ret.Account = account
|
||||
if len(secret) > 0 {
|
||||
ret.Set("key", jsonutils.NewString(secret))
|
||||
ret.Key = secret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err = rootfs.DeployYunionroot(partition, deployInfo.publicKey, deployInfo.isInit, deployInfo.enableCloudInit); err != nil {
|
||||
if err = rootfs.DeployYunionroot(partition, deployInfo.PublicKey, deployInfo.IsInit, deployInfo.EnableCloudInit); err != nil {
|
||||
return nil, fmt.Errorf("DeployYunionroot: %v", err)
|
||||
}
|
||||
if partition.SupportSerialPorts() {
|
||||
if deployInfo.enableTty {
|
||||
if err = rootfs.EnableSerialConsole(partition, ret); err != nil {
|
||||
if deployInfo.EnableTty {
|
||||
if err = rootfs.EnableSerialConsole(partition, nil); err != nil {
|
||||
return nil, fmt.Errorf("EnableSerialConsole: %v", err)
|
||||
}
|
||||
} else {
|
||||
@@ -200,10 +158,26 @@ func DeployGuestFs(
|
||||
return nil, fmt.Errorf("CommitChanges: %v", err)
|
||||
}
|
||||
|
||||
log.Debugf("Deploy finished, return: %s", ret.String())
|
||||
log.Infof("Deploy finished, return: %s", ret.String())
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func DeployGuestFs(
|
||||
rootfs fsdriver.IRootFsDriver,
|
||||
guestDesc *jsonutils.JSONDict,
|
||||
deployInfo *deployapi.DeployInfo,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
desc, err := deployapi.GuestDescToDeployDesc(guestDesc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "To deploy desc fail")
|
||||
}
|
||||
ret, err := DoDeployGuestFs(rootfs, desc, deployInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return jsonutils.Marshal(ret), nil
|
||||
}
|
||||
|
||||
func IsPartitionReadonly(rootfs fsdriver.IDiskPartition) bool {
|
||||
log.Infof("Test if read-only fs ...")
|
||||
var filename = fmt.Sprintf("/.%f", rand.Float32())
|
||||
|
||||
@@ -19,9 +19,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
)
|
||||
|
||||
func ParsePropStr(lines string) map[string]string {
|
||||
@@ -83,7 +81,7 @@ func (m *SAndroidRootFs) GetLoginAccount(rootFs IDiskPartition, defaultRootUser
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SAndroidRootFs) DeployPublicKey(rootfs IDiskPartition, uname string, pubkeys *sshkeys.SSHKeys) error {
|
||||
func (m *SAndroidRootFs) DeployPublicKey(rootfs IDiskPartition, uname string, pubkeys *deployapi.SSHKeys) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -103,14 +101,14 @@ func (m *SAndroidRootFs) GetOs() string {
|
||||
return "Android"
|
||||
}
|
||||
|
||||
func (m *SAndroidRootFs) GetReleaseInfo(IDiskPartition) *SReleaseInfo {
|
||||
func (m *SAndroidRootFs) GetReleaseInfo(IDiskPartition) *deployapi.ReleaseInfo {
|
||||
spath := "/android-*/system/build.prop"
|
||||
lines, _ := m.rootFs.FileGetContents(spath, false)
|
||||
prop := ParsePropStr(string(lines))
|
||||
distro, _ := prop["ro.product.model"]
|
||||
version, _ := prop["ro.build.version.release"]
|
||||
arch, _ := prop["ro.product.cpu.abi"]
|
||||
return &SReleaseInfo{
|
||||
return &deployapi.ReleaseInfo{
|
||||
Distro: distro,
|
||||
Version: version,
|
||||
Arch: arch,
|
||||
@@ -121,7 +119,7 @@ func (m *SAndroidRootFs) PrepareFsForTemplate(IDiskPartition) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SAndroidRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
func (m *SAndroidRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []*deployapi.Nic) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
)
|
||||
|
||||
type sGuestRootFsDriver struct {
|
||||
@@ -37,19 +37,17 @@ func newGuestRootFsDriver(rootFs IDiskPartition) *sGuestRootFsDriver {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *sGuestRootFsDriver) DeployFiles(deploys []jsonutils.JSONObject) error {
|
||||
func (d *sGuestRootFsDriver) DeployFiles(deploys []*deployapi.DeployContent) error {
|
||||
caseInsensitive := d.IsFsCaseInsensitive()
|
||||
for _, deploy := range deploys {
|
||||
var modAppend = false
|
||||
if action, _ := deploy.GetString("action"); action == "append" {
|
||||
if deploy.Action == "append" {
|
||||
modAppend = true
|
||||
}
|
||||
sPath, err := deploy.GetString("path")
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
if len(deploy.Path) == 0 {
|
||||
return fmt.Errorf("Deploy file missing param path")
|
||||
}
|
||||
dirname := filepath.Dir(sPath)
|
||||
dirname := filepath.Dir(deploy.Path)
|
||||
if !d.GetPartition().Exists(dirname, caseInsensitive) {
|
||||
modeRWXOwner := syscall.S_IRUSR | syscall.S_IWUSR | syscall.S_IXUSR
|
||||
err := d.GetPartition().Mkdir(dirname, modeRWXOwner, caseInsensitive)
|
||||
@@ -58,8 +56,8 @@ func (d *sGuestRootFsDriver) DeployFiles(deploys []jsonutils.JSONObject) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if content, err := deploy.GetString("content"); err == nil {
|
||||
err := d.GetPartition().FilePutContents(sPath, content, modAppend, caseInsensitive)
|
||||
if len(deploy.Content) > 0 {
|
||||
err := d.GetPartition().FilePutContents(deploy.Path, deploy.Content, modAppend, caseInsensitive)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
@@ -81,7 +79,7 @@ func (d *sGuestRootFsDriver) IsFsCaseInsensitive() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *sGuestRootFsDriver) DeployYunionroot(rootfs IDiskPartition, pubkeys *sshkeys.SSHKeys, isInit, enableCloudInit bool) error {
|
||||
func (d *sGuestRootFsDriver) DeployYunionroot(rootfs IDiskPartition, pubkeys *deployapi.SSHKeys, isInit, enableCloudInit bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -89,11 +87,11 @@ func (d *sGuestRootFsDriver) DeployUdevSubsystemScripts(rootfs IDiskPartition) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *sGuestRootFsDriver) DeployStandbyNetworkingScripts(part IDiskPartition, nics, nicsStandby []jsonutils.JSONObject) error {
|
||||
func (d *sGuestRootFsDriver) DeployStandbyNetworkingScripts(part IDiskPartition, nics, nicsStandby []*deployapi.Nic) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *sGuestRootFsDriver) DeployFstabScripts(_ IDiskPartition, _ []jsonutils.JSONObject) error {
|
||||
func (d *sGuestRootFsDriver) DeployFstabScripts(_ IDiskPartition, _ []*deployapi.Disk) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -117,22 +115,7 @@ func (l *sGuestRootFsDriver) IsCloudinitInstall() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type SReleaseInfo struct {
|
||||
Distro string `json:"os_distribution,omitempty"`
|
||||
Version string `json:"os_version,omitempty"`
|
||||
Arch string `json:"os_arch,omitempty"`
|
||||
Language string `json:"os_language,omitempty"`
|
||||
}
|
||||
|
||||
func newReleaseInfo(distro, version, arch string) *SReleaseInfo {
|
||||
return &SReleaseInfo{
|
||||
Distro: distro,
|
||||
Version: version,
|
||||
Arch: arch,
|
||||
}
|
||||
}
|
||||
|
||||
func DeployAuthorizedKeys(rootFs IDiskPartition, usrDir string, pubkeys *sshkeys.SSHKeys, replace bool) error {
|
||||
func DeployAuthorizedKeys(rootFs IDiskPartition, usrDir string, pubkeys *deployapi.SSHKeys, replace bool) error {
|
||||
usrStat := rootFs.Stat(usrDir, false)
|
||||
if usrStat != nil {
|
||||
sshDir := path.Join(usrDir, ".ssh")
|
||||
@@ -171,7 +154,7 @@ func DeployAuthorizedKeys(rootFs IDiskPartition, usrDir string, pubkeys *sshkeys
|
||||
return nil
|
||||
}
|
||||
|
||||
func MergeAuthorizedKeys(oldKeys string, pubkeys *sshkeys.SSHKeys) string {
|
||||
func MergeAuthorizedKeys(oldKeys string, pubkeys *deployapi.SSHKeys) string {
|
||||
var allkeys = make(map[string]string)
|
||||
if len(oldKeys) > 0 {
|
||||
for _, line := range strings.Split(oldKeys, "\n") {
|
||||
|
||||
@@ -17,13 +17,13 @@ package fsdriver
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
)
|
||||
|
||||
func TestMergeAuthorizedKeys(t *testing.T) {
|
||||
type args struct {
|
||||
oldKeys string
|
||||
pubkeys *sshkeys.SSHKeys
|
||||
pubkeys *deployapi.SSHKeys
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -34,7 +34,7 @@ func TestMergeAuthorizedKeys(t *testing.T) {
|
||||
name: "MergeAuthorizedKeys",
|
||||
args: args{
|
||||
oldKeys: "Test KEY",
|
||||
pubkeys: &sshkeys.SSHKeys{},
|
||||
pubkeys: &deployapi.SSHKeys{},
|
||||
},
|
||||
want: "Test KEY\n",
|
||||
},
|
||||
|
||||
@@ -16,13 +16,18 @@ package fsdriver
|
||||
|
||||
type newRootFsDriverFunc func(part IDiskPartition) IRootFsDriver
|
||||
|
||||
var rootfsDrivers = make([]newRootFsDriverFunc, 0)
|
||||
var (
|
||||
privatePrefixes []string
|
||||
rootfsDrivers = make([]newRootFsDriverFunc, 0)
|
||||
)
|
||||
|
||||
func GetRootfsDrivers() []newRootFsDriverFunc {
|
||||
return rootfsDrivers
|
||||
}
|
||||
|
||||
func init() {
|
||||
func Init(initPrivatePrefixes []string) {
|
||||
privatePrefixes = make([]string, len(initPrivatePrefixes))
|
||||
copy(privatePrefixes, initPrivatePrefixes)
|
||||
linuxFsDrivers := []newRootFsDriverFunc{
|
||||
NewCentosRootFs, NewFedoraRootFs, NewRhelRootFs,
|
||||
NewDebianRootFs, NewCirrosRootFs, NewCirrosNewRootFs, NewUbuntuRootFs,
|
||||
|
||||
@@ -15,10 +15,9 @@
|
||||
package fsdriver
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
)
|
||||
|
||||
type SEsxiRootFs struct {
|
||||
@@ -67,19 +66,19 @@ func (m *SEsxiRootFs) DeployHosts(part IDiskPartition, hn, domain string, ips []
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SEsxiRootFs) GetReleaseInfo(IDiskPartition) *SReleaseInfo {
|
||||
func (m *SEsxiRootFs) GetReleaseInfo(IDiskPartition) *deployapi.ReleaseInfo {
|
||||
spath := "/boot.cfg"
|
||||
lines, _ := m.rootFs.FileGetContents(spath, false)
|
||||
prop := ParsePropStr(string(lines))
|
||||
version, _ := prop["build"]
|
||||
return &SReleaseInfo{
|
||||
return &deployapi.ReleaseInfo{
|
||||
Distro: "ESXi",
|
||||
Version: version,
|
||||
Arch: "x86_64",
|
||||
}
|
||||
}
|
||||
|
||||
func (m *SEsxiRootFs) DeployPublicKey(rootfs IDiskPartition, uname string, pubkeys *sshkeys.SSHKeys) error {
|
||||
func (m *SEsxiRootFs) DeployPublicKey(rootfs IDiskPartition, uname string, pubkeys *deployapi.SSHKeys) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -87,6 +86,6 @@ func (m *SEsxiRootFs) PrepareFsForTemplate(IDiskPartition) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SEsxiRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
func (m *SEsxiRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []*deployapi.Nic) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
)
|
||||
|
||||
type IDiskPartition interface {
|
||||
@@ -61,22 +61,22 @@ type IRootFsDriver interface {
|
||||
IsFsCaseInsensitive() bool
|
||||
RootSignatures() []string
|
||||
RootExcludeSignatures() []string
|
||||
GetReleaseInfo(IDiskPartition) *SReleaseInfo
|
||||
GetReleaseInfo(IDiskPartition) *deployapi.ReleaseInfo
|
||||
GetOs() string
|
||||
DeployHostname(part IDiskPartition, hn, domain string) error
|
||||
DeployHosts(part IDiskPartition, hn, domain string, ips []string) error
|
||||
DeployNetworkingScripts(IDiskPartition, []jsonutils.JSONObject) error
|
||||
DeployStandbyNetworkingScripts(part IDiskPartition, nics, nicsStandby []jsonutils.JSONObject) error
|
||||
DeployNetworkingScripts(IDiskPartition, []*deployapi.Nic) error
|
||||
DeployStandbyNetworkingScripts(part IDiskPartition, nics, nicsStandby []*deployapi.Nic) error
|
||||
DeployUdevSubsystemScripts(IDiskPartition) error
|
||||
DeployFstabScripts(IDiskPartition, []jsonutils.JSONObject) error
|
||||
DeployFstabScripts(IDiskPartition, []*deployapi.Disk) error
|
||||
GetLoginAccount(IDiskPartition, bool, bool) string
|
||||
DeployPublicKey(IDiskPartition, string, *sshkeys.SSHKeys) error
|
||||
DeployPublicKey(IDiskPartition, string, *deployapi.SSHKeys) error
|
||||
ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string) (string, error)
|
||||
DeployYunionroot(rootFs IDiskPartition, pubkeys *sshkeys.SSHKeys, isInit bool, enableCloudInit bool) error
|
||||
DeployYunionroot(rootFs IDiskPartition, pubkeys *deployapi.SSHKeys, isInit bool, enableCloudInit bool) error
|
||||
EnableSerialConsole(IDiskPartition, *jsonutils.JSONDict) error
|
||||
DisableSerialConsole(IDiskPartition) error
|
||||
CommitChanges(IDiskPartition) error
|
||||
DeployFiles(deploys []jsonutils.JSONObject) error
|
||||
DeployFiles(deploys []*deployapi.DeployContent) error
|
||||
DetectIsUEFISupport(IDiskPartition) bool
|
||||
IsCloudinitInstall() bool
|
||||
|
||||
|
||||
@@ -30,9 +30,8 @@ import (
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
"yunion.io/x/onecloud/pkg/util/coreosutils"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/fstabutils"
|
||||
@@ -117,7 +116,7 @@ func (l *sLinuxRootFs) ChangeUserPasswd(rootFs IDiskPartition, account, gid, pub
|
||||
return secret, err
|
||||
}
|
||||
|
||||
func (l *sLinuxRootFs) DeployPublicKey(rootFs IDiskPartition, selUsr string, pubkeys *sshkeys.SSHKeys) error {
|
||||
func (l *sLinuxRootFs) DeployPublicKey(rootFs IDiskPartition, selUsr string, pubkeys *deployapi.SSHKeys) error {
|
||||
var usrDir string
|
||||
if selUsr == "root" {
|
||||
usrDir = "/root"
|
||||
@@ -127,7 +126,7 @@ func (l *sLinuxRootFs) DeployPublicKey(rootFs IDiskPartition, selUsr string, pub
|
||||
return DeployAuthorizedKeys(rootFs, usrDir, pubkeys, false)
|
||||
}
|
||||
|
||||
func (l *sLinuxRootFs) DeployYunionroot(rootFs IDiskPartition, pubkeys *sshkeys.SSHKeys, isInit, enableCloudInit bool) error {
|
||||
func (l *sLinuxRootFs) DeployYunionroot(rootFs IDiskPartition, pubkeys *deployapi.SSHKeys, isInit, enableCloudInit bool) error {
|
||||
l.DisableSelinux(rootFs)
|
||||
if !enableCloudInit && isInit {
|
||||
l.DisableCloudinit(rootFs)
|
||||
@@ -191,7 +190,7 @@ func (l *sLinuxRootFs) DisableCloudinit(rootFs IDiskPartition) {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *sLinuxRootFs) DeployFstabScripts(rootFs IDiskPartition, disks []jsonutils.JSONObject) error {
|
||||
func (l *sLinuxRootFs) DeployFstabScripts(rootFs IDiskPartition, disks []*deployapi.Disk) error {
|
||||
fstabcont, err := rootFs.FileGetContents("/etc/fstab", false)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -203,18 +202,18 @@ func (l *sLinuxRootFs) DeployFstabScripts(rootFs IDiskPartition, disks []jsonuti
|
||||
fstab.RemoveDevices(len(disks))
|
||||
|
||||
for i := 1; i < len(disks); i++ {
|
||||
diskId, err := disks[i].GetString("disk_id")
|
||||
if err != nil {
|
||||
diskId := disks[i].DiskId
|
||||
if len(diskId) == 0 {
|
||||
diskId = "None"
|
||||
}
|
||||
dev := fmt.Sprintf("UUID=%s", diskId)
|
||||
if !fstab.IsExists(dev) {
|
||||
fs, _ := disks[i].GetString("fs")
|
||||
fs := disks[i].Fs
|
||||
if len(fs) > 0 {
|
||||
if fs == "swap" {
|
||||
rec = fmt.Sprintf("%s none %s sw 0 0", dev, fs)
|
||||
} else {
|
||||
mtPath, _ := disks[i].GetString("mountpoint")
|
||||
mtPath := disks[i].Mountpoint
|
||||
if len(mtPath) == 0 {
|
||||
mtPath = "/data"
|
||||
if dataDiskIdx > 0 {
|
||||
@@ -237,7 +236,7 @@ func (l *sLinuxRootFs) DeployFstabScripts(rootFs IDiskPartition, disks []jsonuti
|
||||
return rootFs.FilePutContents("/etc/fstab", cf, false, false)
|
||||
}
|
||||
|
||||
func (l *sLinuxRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
func (l *sLinuxRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*deployapi.Nic) error {
|
||||
udevPath := "/etc/udev/rules.d/"
|
||||
if rootFs.Exists(udevPath, false) {
|
||||
rules := rootFs.ListDir(udevPath, false)
|
||||
@@ -254,9 +253,9 @@ func (l *sLinuxRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []jso
|
||||
for _, nic := range nics {
|
||||
nicRules += `KERNEL=="*", SUBSYSTEM=="net", ACTION=="add", `
|
||||
nicRules += `DRIVERS=="?*", `
|
||||
mac, _ := nic.GetString("mac")
|
||||
mac := nic.Mac
|
||||
nicRules += fmt.Sprintf(`ATTR{address}=="%s", ATTR{type}=="1", `, strings.ToLower(mac))
|
||||
idx, _ := nic.Int("index")
|
||||
idx := nic.Index
|
||||
nicRules += fmt.Sprintf("NAME=\"eth%d\"\n", idx)
|
||||
}
|
||||
if err := rootFs.FilePutContents(path.Join(udevPath, "70-persistent-net.rules"), nicRules, false, false); err != nil {
|
||||
@@ -274,17 +273,16 @@ func (l *sLinuxRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []jso
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *sLinuxRootFs) DeployStandbyNetworkingScripts(rootFs IDiskPartition, nics, nicsStandby []jsonutils.JSONObject) error {
|
||||
func (l *sLinuxRootFs) DeployStandbyNetworkingScripts(rootFs IDiskPartition, nics, nicsStandby []*deployapi.Nic) error {
|
||||
var udevPath = "/etc/udev/rules.d/"
|
||||
var nicRules string
|
||||
for _, nic := range nicsStandby {
|
||||
nicType, _ := nic.GetString("nic_type")
|
||||
if !nic.Contains("nic_type") || nicType != "impi" {
|
||||
if len(nic.NicType) == 0 || nic.NicType != "impi" {
|
||||
nicRules += `KERNEL=="*", SUBSYSTEM=="net", ACTION=="add", `
|
||||
nicRules += `DRIVERS=="?*", `
|
||||
mac, _ := nic.GetString("mac")
|
||||
mac := nic.Mac
|
||||
nicRules += fmt.Sprintf(`ATTR{address}=="%s", ATTR{type}=="1", `, strings.ToLower(mac))
|
||||
idx, _ := nic.Int("index")
|
||||
idx := nic.Index
|
||||
nicRules += fmt.Sprintf("NAME=\"eth%d\"\n", idx)
|
||||
}
|
||||
}
|
||||
@@ -474,14 +472,14 @@ func newDebianLikeRootFs(part IDiskPartition) *sDebianLikeRootFs {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *sDebianLikeRootFs) GetReleaseInfo(rootFs IDiskPartition, driver IDebianRootFsDriver) *SReleaseInfo {
|
||||
func (d *sDebianLikeRootFs) GetReleaseInfo(rootFs IDiskPartition, driver IDebianRootFsDriver) *deployapi.ReleaseInfo {
|
||||
version, err := rootFs.FileGetContents(driver.VersionFilePath(), false)
|
||||
if err != nil {
|
||||
log.Errorf("Get %s error: %v", driver.VersionFilePath(), err)
|
||||
return nil
|
||||
}
|
||||
versionStr := strings.TrimSpace(string(version))
|
||||
return &SReleaseInfo{
|
||||
return &deployapi.ReleaseInfo{
|
||||
Distro: driver.DistroName(),
|
||||
Version: versionStr,
|
||||
Arch: d.GetArch(rootFs),
|
||||
@@ -512,7 +510,7 @@ func getNicTeamingConfigCmds(slaves []*types.SServerNic) string {
|
||||
return cmds.String()
|
||||
}
|
||||
|
||||
func (d *sDebianLikeRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
func (d *sDebianLikeRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*deployapi.Nic) error {
|
||||
if err := d.sLinuxRootFs.DeployNetworkingScripts(rootFs, nics); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -521,7 +519,7 @@ func (d *sDebianLikeRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics
|
||||
cmds.WriteString("auto lo\n")
|
||||
cmds.WriteString("iface lo inet loopback\n\n")
|
||||
|
||||
allNics, _ := convertNicConfigs(nics)
|
||||
allNics, _ := convertNicConfigs(ToServerNics(nics))
|
||||
mainNic, err := getMainNic(allNics)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -543,7 +541,7 @@ func (d *sDebianLikeRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics
|
||||
cmds.WriteString(" netmask 255.255.255.255\n")
|
||||
cmds.WriteString("\n")
|
||||
} else if nicDesc.Manual {
|
||||
netmask := netutils2.Netlen2Mask(nicDesc.Masklen)
|
||||
netmask := netutils2.Netlen2Mask(int(nicDesc.Masklen))
|
||||
cmds.WriteString(fmt.Sprintf("iface %s inet static\n", nicDesc.Name))
|
||||
cmds.WriteString(fmt.Sprintf(" address %s\n", nicDesc.Ip))
|
||||
cmds.WriteString(fmt.Sprintf(" netmask %s\n", netmask))
|
||||
@@ -551,7 +549,7 @@ func (d *sDebianLikeRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics
|
||||
cmds.WriteString(fmt.Sprintf(" gateway %s\n", nicDesc.Gateway))
|
||||
}
|
||||
var routes = make([][]string, 0)
|
||||
netutils2.AddNicRoutes(&routes, nicDesc, mainIp, len(nics), options.HostOptions.PrivatePrefixes)
|
||||
netutils2.AddNicRoutes(&routes, nicDesc, mainIp, len(nics), privatePrefixes)
|
||||
for _, r := range routes {
|
||||
cmds.WriteString(fmt.Sprintf(" up route add -net %s gw %s || true\n", r[0], r[1]))
|
||||
cmds.WriteString(fmt.Sprintf(" down route del -net %s gw %s || true\n", r[0], r[1]))
|
||||
@@ -615,7 +613,7 @@ func (d *SDebianRootFs) RootExcludeSignatures() []string {
|
||||
return []string{"/etc/lsb-release"}
|
||||
}
|
||||
|
||||
func (d *SDebianRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
func (d *SDebianRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
|
||||
return d.sDebianLikeRootFs.GetReleaseInfo(rootFs, d)
|
||||
}
|
||||
|
||||
@@ -645,7 +643,7 @@ func (d *SCirrosRootFs) VersionFilePath() string {
|
||||
return "/etc/br-version"
|
||||
}
|
||||
|
||||
func (d *SCirrosRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
func (d *SCirrosRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
|
||||
return d.SDebianRootFs.sDebianLikeRootFs.GetReleaseInfo(rootFs, d)
|
||||
}
|
||||
|
||||
@@ -683,7 +681,7 @@ func (d *SCirrosNewRootFs) RootSignatures() []string {
|
||||
return d.rootSignatures(d)
|
||||
}
|
||||
|
||||
func (d *SCirrosNewRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
func (d *SCirrosNewRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
|
||||
return d.SDebianRootFs.sDebianLikeRootFs.GetReleaseInfo(rootFs, d)
|
||||
}
|
||||
|
||||
@@ -710,7 +708,7 @@ func (d *SUbuntuRootFs) String() string {
|
||||
return "UbuntuRootFs"
|
||||
}
|
||||
|
||||
func (d *SUbuntuRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
func (d *SUbuntuRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
|
||||
distroKey := "DISTRIB_RELEASE="
|
||||
rel, err := rootFs.FileGetContents("/etc/lsb-release", false)
|
||||
if err != nil {
|
||||
@@ -724,7 +722,7 @@ func (d *SUbuntuRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
version = strings.TrimSpace(l[len(distroKey) : len(l)-1])
|
||||
}
|
||||
}
|
||||
return newReleaseInfo(d.GetName(), version, d.GetArch(rootFs))
|
||||
return deployapi.NewReleaseInfo(d.GetName(), version, d.GetArch(rootFs))
|
||||
}
|
||||
|
||||
func (d *SUbuntuRootFs) EnableSerialConsole(rootFs IDiskPartition, sysInfo *jsonutils.JSONDict) error {
|
||||
@@ -778,18 +776,14 @@ func (r *sRedhatLikeRootFs) DeployHostname(rootFs IDiskPartition, hn, domain str
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *sRedhatLikeRootFs) Centos5DeployNetworkingScripts(rootFs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
func (r *sRedhatLikeRootFs) Centos5DeployNetworkingScripts(rootFs IDiskPartition, nics []*deployapi.Nic) error {
|
||||
var udevPath = "/etc/udev/rules.d/"
|
||||
if rootFs.Exists(udevPath, false) {
|
||||
var nicRules = ""
|
||||
for _, nic := range nics {
|
||||
var nicdesc = new(types.SServerNic)
|
||||
if err := nic.Unmarshal(nicdesc); err != nil {
|
||||
return err
|
||||
}
|
||||
nicRules += `KERNEL=="*", `
|
||||
nicRules += fmt.Sprintf(`SYSFS{address}=="%s", `, strings.ToLower(nicdesc.Mac))
|
||||
nicRules += fmt.Sprintf("NAME=\"eth%d\"\n", nicdesc.Index)
|
||||
nicRules += fmt.Sprintf(`SYSFS{address}=="%s", `, strings.ToLower(nic.Mac))
|
||||
nicRules += fmt.Sprintf("NAME=\"eth%d\"\n", nic.Index)
|
||||
}
|
||||
return rootFs.FilePutContents(path.Join(udevPath, "60-net.rules"),
|
||||
nicRules, false, false)
|
||||
@@ -830,7 +824,7 @@ func (r *sRedhatLikeRootFs) enableBondingModule(rootFs IDiskPartition, bondNics
|
||||
return rootFs.FilePutContents("/etc/modprobe.d/bonding.conf", content.String(), false, false)
|
||||
}
|
||||
|
||||
func (r *sRedhatLikeRootFs) deployNetworkingScripts(rootFs IDiskPartition, nics []jsonutils.JSONObject, relInfo *SReleaseInfo) error {
|
||||
func (r *sRedhatLikeRootFs) deployNetworkingScripts(rootFs IDiskPartition, nics []*deployapi.Nic, relInfo *deployapi.ReleaseInfo) error {
|
||||
if err := r.sLinuxRootFs.DeployNetworkingScripts(rootFs, nics); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -848,7 +842,7 @@ func (r *sRedhatLikeRootFs) deployNetworkingScripts(rootFs IDiskPartition, nics
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allNics, bondNics := convertNicConfigs(nics)
|
||||
allNics, bondNics := convertNicConfigs(ToServerNics(nics))
|
||||
if len(bondNics) > 0 {
|
||||
err = r.enableBondingModule(rootFs, bondNics)
|
||||
if err != nil {
|
||||
@@ -896,7 +890,7 @@ func (r *sRedhatLikeRootFs) deployNetworkingScripts(rootFs IDiskPartition, nics
|
||||
cmds.WriteString(netutils2.PSEUDO_VIP)
|
||||
cmds.WriteString("\n")
|
||||
} else if nicDesc.Manual {
|
||||
netmask := netutils2.Netlen2Mask(nicDesc.Masklen)
|
||||
netmask := netutils2.Netlen2Mask(int(nicDesc.Masklen))
|
||||
cmds.WriteString("BOOTPROTO=none\n")
|
||||
cmds.WriteString("NETMASK=")
|
||||
cmds.WriteString(netmask)
|
||||
@@ -910,7 +904,7 @@ func (r *sRedhatLikeRootFs) deployNetworkingScripts(rootFs IDiskPartition, nics
|
||||
cmds.WriteString("\n")
|
||||
}
|
||||
var routes = make([][]string, 0)
|
||||
netutils2.AddNicRoutes(&routes, nicDesc, mainIp, len(nics), options.HostOptions.PrivatePrefixes)
|
||||
netutils2.AddNicRoutes(&routes, nicDesc, mainIp, len(nics), privatePrefixes)
|
||||
var rtbl strings.Builder
|
||||
for _, r := range routes {
|
||||
rtbl.WriteString(r[0])
|
||||
@@ -946,23 +940,19 @@ func (r *sRedhatLikeRootFs) deployNetworkingScripts(rootFs IDiskPartition, nics
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *sRedhatLikeRootFs) DeployStandbyNetworkingScripts(rootFs IDiskPartition, nics, nicsStandby []jsonutils.JSONObject) error {
|
||||
func (r *sRedhatLikeRootFs) DeployStandbyNetworkingScripts(rootFs IDiskPartition, nics, nicsStandby []*deployapi.Nic) error {
|
||||
if err := r.sLinuxRootFs.DeployStandbyNetworkingScripts(rootFs, nics, nicsStandby); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, nic := range nicsStandby {
|
||||
var cmds string
|
||||
var nicdesc = new(types.SServerNic)
|
||||
if err := nic.Unmarshal(nicdesc); err != nil {
|
||||
return err
|
||||
}
|
||||
if nicType, err := nic.GetString("nic_type"); err != nil && nicType != "ipmi" {
|
||||
cmds += fmt.Sprintf("DEVICE=eth%d\n", nicdesc.Index)
|
||||
cmds += fmt.Sprintf("NAME=eth%d\n", nicdesc.Index)
|
||||
cmds += fmt.Sprintf("HWADDR=%s\n", nicdesc.Mac)
|
||||
cmds += fmt.Sprintf("MACADDR=%s\n", nicdesc.Mac)
|
||||
if len(nic.NicType) == 0 || nic.NicType != "ipmi" {
|
||||
cmds += fmt.Sprintf("DEVICE=eth%d\n", nic.Index)
|
||||
cmds += fmt.Sprintf("NAME=eth%d\n", nic.Index)
|
||||
cmds += fmt.Sprintf("HWADDR=%s\n", nic.Mac)
|
||||
cmds += fmt.Sprintf("MACADDR=%s\n", nic.Mac)
|
||||
cmds += "ONBOOT=no\n"
|
||||
var fn = fmt.Sprintf("/etc/sysconfig/network-scripts/ifcfg-eth%d", nicdesc.Index)
|
||||
var fn = fmt.Sprintf("/etc/sysconfig/network-scripts/ifcfg-eth%d", nic.Index)
|
||||
if err := rootFs.FilePutContents(fn, cmds, false, false); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1029,7 +1019,7 @@ func (c *SCentosRootFs) RootSignatures() []string {
|
||||
return append([]string{"/etc/centos-release"}, sig...)
|
||||
}
|
||||
|
||||
func (c *SCentosRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
func (c *SCentosRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
|
||||
rel, _ := rootFs.FileGetContents("/etc/centos-release", false)
|
||||
var version string
|
||||
if len(rel) > 0 {
|
||||
@@ -1042,10 +1032,10 @@ func (c *SCentosRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
}
|
||||
}
|
||||
}
|
||||
return newReleaseInfo(c.GetName(), version, c.GetArch(rootFs))
|
||||
return deployapi.NewReleaseInfo(c.GetName(), version, c.GetArch(rootFs))
|
||||
}
|
||||
|
||||
func (c *SCentosRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
func (c *SCentosRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*deployapi.Nic) error {
|
||||
relInfo := c.GetReleaseInfo(rootFs)
|
||||
if err := c.sRedhatLikeRootFs.deployNetworkingScripts(rootFs, nics, relInfo); err != nil {
|
||||
return err
|
||||
@@ -1092,7 +1082,7 @@ func (c *SFedoraRootFs) RootSignatures() []string {
|
||||
return append([]string{"/etc/fedora-release"}, sig...)
|
||||
}
|
||||
|
||||
func (c *SFedoraRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
func (c *SFedoraRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
|
||||
rel, _ := rootFs.FileGetContents("/etc/fedora-release", false)
|
||||
var version string
|
||||
if len(rel) > 0 {
|
||||
@@ -1105,10 +1095,10 @@ func (c *SFedoraRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
}
|
||||
}
|
||||
}
|
||||
return newReleaseInfo(c.GetName(), version, c.GetArch(rootFs))
|
||||
return deployapi.NewReleaseInfo(c.GetName(), version, c.GetArch(rootFs))
|
||||
}
|
||||
|
||||
func (c *SFedoraRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
func (c *SFedoraRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*deployapi.Nic) error {
|
||||
relInfo := c.GetReleaseInfo(rootFs)
|
||||
if err := c.sRedhatLikeRootFs.deployNetworkingScripts(rootFs, nics, relInfo); err != nil {
|
||||
return err
|
||||
@@ -1140,7 +1130,7 @@ func (d *SRhelRootFs) String() string {
|
||||
return "RhelRootFs"
|
||||
}
|
||||
|
||||
func (d *SRhelRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
func (d *SRhelRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
|
||||
rel, _ := rootFs.FileGetContents("/etc/redhat-release", false)
|
||||
var version string
|
||||
if len(rel) > 0 {
|
||||
@@ -1149,10 +1139,10 @@ func (d *SRhelRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
version = dat[6]
|
||||
}
|
||||
}
|
||||
return newReleaseInfo(d.GetName(), version, d.GetArch(rootFs))
|
||||
return deployapi.NewReleaseInfo(d.GetName(), version, d.GetArch(rootFs))
|
||||
}
|
||||
|
||||
func (d *SRhelRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
func (d *SRhelRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*deployapi.Nic) error {
|
||||
relInfo := d.GetReleaseInfo(rootFs)
|
||||
if err := d.sRedhatLikeRootFs.deployNetworkingScripts(rootFs, nics, relInfo); err != nil {
|
||||
return err
|
||||
@@ -1199,7 +1189,7 @@ func (d *SGentooRootFs) DeployHostname(rootFs IDiskPartition, hn, domain string)
|
||||
return rootFs.FilePutContents(spath, content, false, false)
|
||||
}
|
||||
|
||||
func (l *SGentooRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
func (l *SGentooRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*deployapi.Nic) error {
|
||||
if err := l.sLinuxRootFs.DeployNetworkingScripts(rootFs, nics); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1210,8 +1200,8 @@ func (l *SGentooRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []js
|
||||
)
|
||||
|
||||
for _, nic := range nics {
|
||||
nicIndex, _ := nic.Int("index")
|
||||
if jsonutils.QueryBoolean(nic, "virtual", false) {
|
||||
nicIndex := nic.Index
|
||||
if nic.Virtual {
|
||||
cmds += fmt.Sprintf(`config_eth%d="`, nicIndex)
|
||||
cmds += fmt.Sprintf("%s netmask 255.255.255.255", netutils2.PSEUDO_VIP)
|
||||
cmds += `"\n`
|
||||
@@ -1223,7 +1213,7 @@ func (l *SGentooRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []js
|
||||
return err
|
||||
}
|
||||
for _, nic := range nics {
|
||||
nicIndex, _ := nic.Int("index")
|
||||
nicIndex := nic.Index
|
||||
netname := fmt.Sprintf("net.eth%d", nicIndex)
|
||||
procutils.NewCommand("ln", "-s", "net.lo",
|
||||
fmt.Sprintf("%s/etc/init.d/%s", rootFs.GetMountPath(), netname)).Run()
|
||||
@@ -1233,8 +1223,8 @@ func (l *SGentooRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []js
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *SGentooRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
return &SReleaseInfo{
|
||||
func (d *SGentooRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
|
||||
return &deployapi.ReleaseInfo{
|
||||
Distro: "Gentoo",
|
||||
Arch: d.GetArch(rootFs),
|
||||
}
|
||||
@@ -1269,8 +1259,8 @@ func (d *SArchLinuxRootFs) DeployHostname(rootFs IDiskPartition, hn, domain stri
|
||||
return rootFs.FilePutContents("/etc/hostname", hn, false, false)
|
||||
}
|
||||
|
||||
func (d *SArchLinuxRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
return &SReleaseInfo{
|
||||
func (d *SArchLinuxRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
|
||||
return &deployapi.ReleaseInfo{
|
||||
Distro: "ArchLinux",
|
||||
Arch: d.GetArch(rootFs),
|
||||
}
|
||||
@@ -1308,9 +1298,9 @@ func (d *SOpenWrtRootFs) DeployHostname(rootFs IDiskPartition, hn, domain string
|
||||
return rootFs.FilePutContents(spath, cont, false, false)
|
||||
}
|
||||
|
||||
func (d *SOpenWrtRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
func (d *SOpenWrtRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
|
||||
ver, _ := rootFs.FileGetContents("/etc/openwrt_version", false)
|
||||
return &SReleaseInfo{
|
||||
return &deployapi.ReleaseInfo{
|
||||
Distro: "OpenWRT",
|
||||
Version: string(ver),
|
||||
Arch: d.GetArch(rootFs),
|
||||
@@ -1338,8 +1328,8 @@ func (d *SCoreOsRootFs) GetOs() string {
|
||||
return "Linux"
|
||||
}
|
||||
|
||||
func (d *SCoreOsRootFs) GetReleaseInfo(rootFs IDiskPartition) *SReleaseInfo {
|
||||
return &SReleaseInfo{
|
||||
func (d *SCoreOsRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
|
||||
return &deployapi.ReleaseInfo{
|
||||
Distro: "CoreOS",
|
||||
Version: "stable",
|
||||
}
|
||||
@@ -1367,7 +1357,7 @@ func (d *SCoreOsRootFs) DeployHostname(rootFs IDiskPartition, hn, domain string)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *SCoreOsRootFs) DeployPublicKey(rootFs IDiskPartition, selUsr string, pubkeys *sshkeys.SSHKeys) error {
|
||||
func (d *SCoreOsRootFs) DeployPublicKey(rootFs IDiskPartition, selUsr string, pubkeys *deployapi.SSHKeys) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1376,7 +1366,7 @@ func (d *SCoreOsRootFs) DeployHosts(rootFs IDiskPartition, hostname, domain stri
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *SCoreOsRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
func (d *SCoreOsRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*deployapi.Nic) error {
|
||||
cont := "[Match]\n"
|
||||
cont += "Name=eth*\n\n"
|
||||
cont += "[Network]\n"
|
||||
@@ -1386,17 +1376,16 @@ func (d *SCoreOsRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []js
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *SCoreOsRootFs) DeployFstabScripts(rootFs IDiskPartition, disks []jsonutils.JSONObject) error {
|
||||
func (d *SCoreOsRootFs) DeployFstabScripts(rootFs IDiskPartition, disks []*deployapi.Disk) error {
|
||||
dataDiskIdx := 0
|
||||
for i := 1; i < len(disks); i++ {
|
||||
diskId, _ := disks[i].GetString("disk_id")
|
||||
dev := fmt.Sprintf("UUID=%s", diskId)
|
||||
fs, _ := disks[i].GetString("fs")
|
||||
dev := fmt.Sprintf("UUID=%s", disks[i].DiskId)
|
||||
fs := disks[i].Fs
|
||||
if len(fs) > 0 {
|
||||
if fs == "swap" {
|
||||
d.GetConfig().AddSwap(dev)
|
||||
} else {
|
||||
mtPath, _ := disks[i].GetString("mountpoint")
|
||||
mtPath := disks[i].Mountpoint
|
||||
if len(mtPath) == 0 {
|
||||
mtPath = "/data"
|
||||
if dataDiskIdx > 0 {
|
||||
@@ -1428,11 +1417,9 @@ func (d *SCoreOsRootFs) GetLoginAccount(rootFs IDiskPartition, defaultRootUser b
|
||||
return "core"
|
||||
}
|
||||
|
||||
func (d *SCoreOsRootFs) DeployFiles(deploys []jsonutils.JSONObject) error {
|
||||
func (d *SCoreOsRootFs) DeployFiles(deploys []*deployapi.DeployContent) error {
|
||||
for _, deploy := range deploys {
|
||||
spath, _ := deploy.GetString("path")
|
||||
content, _ := deploy.GetString("content")
|
||||
d.GetConfig().AddWriteFile(spath, content, "", "", false)
|
||||
d.GetConfig().AddWriteFile(deploy.Path, deploy.Content, "", "", false)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -19,10 +19,9 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
"yunion.io/x/onecloud/pkg/util/macutils"
|
||||
"yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
@@ -72,7 +71,7 @@ func (m *SMacOSRootFs) RootSignatures() []string {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *SMacOSRootFs) DeployPublicKey(rootfs IDiskPartition, uname string, pubkeys *sshkeys.SSHKeys) error {
|
||||
func (m *SMacOSRootFs) DeployPublicKey(rootfs IDiskPartition, uname string, pubkeys *deployapi.SSHKeys) error {
|
||||
usrDir := fmt.Sprintf("/Users/%s", uname)
|
||||
return DeployAuthorizedKeys(m.rootFs, usrDir, pubkeys, false)
|
||||
}
|
||||
@@ -115,13 +114,13 @@ func (m *SMacOSRootFs) DeployHosts(part IDiskPartition, hn, domain string, ips [
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SMacOSRootFs) GetReleaseInfo(IDiskPartition) *SReleaseInfo {
|
||||
func (m *SMacOSRootFs) GetReleaseInfo(IDiskPartition) *deployapi.ReleaseInfo {
|
||||
spath := "/System/Library/CoreServices/SystemVersion.plist"
|
||||
sInfo, _ := m.rootFs.FileGetContents(spath, false)
|
||||
info := macutils.ParsePlist(sInfo)
|
||||
distro, _ := info["ProductName"]
|
||||
version, _ := info["ProductUserVisibleVersion"]
|
||||
return &SReleaseInfo{
|
||||
return &deployapi.ReleaseInfo{
|
||||
Distro: distro,
|
||||
Version: version,
|
||||
Arch: "x86_64",
|
||||
@@ -132,7 +131,7 @@ func (m *SMacOSRootFs) GetOs() string {
|
||||
return "macOs"
|
||||
}
|
||||
|
||||
func (m *SMacOSRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
func (m *SMacOSRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []*deployapi.Nic) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
)
|
||||
|
||||
func unmarshalNicConfigs(jsonNics []jsonutils.JSONObject) []types.SServerNic {
|
||||
@@ -33,18 +34,24 @@ func unmarshalNicConfigs(jsonNics []jsonutils.JSONObject) []types.SServerNic {
|
||||
return nics
|
||||
}
|
||||
|
||||
func findTeamingNic(nics []types.SServerNic, mac string) *types.SServerNic {
|
||||
func findTeamingNic(nics []*types.SServerNic, mac string) *types.SServerNic {
|
||||
for i := range nics {
|
||||
if nics[i].TeamWith == mac {
|
||||
return &nics[i]
|
||||
return nics[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertNicConfigs(jsonNics []jsonutils.JSONObject) ([]*types.SServerNic, []*types.SServerNic) {
|
||||
nics := unmarshalNicConfigs(jsonNics)
|
||||
func ToServerNics(nics []*deployapi.Nic) []*types.SServerNic {
|
||||
ret := make([]*types.SServerNic, len(nics))
|
||||
for i := 0; i < len(nics); i++ {
|
||||
ret[i] = &types.SServerNic{Nic: nics[i]}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func convertNicConfigs(nics []*types.SServerNic) ([]*types.SServerNic, []*types.SServerNic) {
|
||||
allNics := make([]*types.SServerNic, 0)
|
||||
bondNics := make([]*types.SServerNic, 0)
|
||||
|
||||
@@ -61,25 +68,25 @@ func convertNicConfigs(jsonNics []jsonutils.JSONObject) ([]*types.SServerNic, []
|
||||
if teamNic == nil {
|
||||
nnic := nics[i]
|
||||
nnic.Name = fmt.Sprintf("eth%d", nnic.Index)
|
||||
allNics = append(allNics, &nnic)
|
||||
allNics = append(allNics, nnic)
|
||||
continue
|
||||
}
|
||||
master := nics[i]
|
||||
nnic := nics[i]
|
||||
tnic := *teamNic
|
||||
nnic.Name = fmt.Sprintf("eth%d", nnic.Index)
|
||||
nnic.TeamingMaster = &master
|
||||
nnic.TeamingMaster = master
|
||||
nnic.Ip = ""
|
||||
nnic.Gateway = ""
|
||||
tnic.Name = fmt.Sprintf("eth%d", tnic.Index)
|
||||
tnic.TeamingMaster = &master
|
||||
tnic.TeamingMaster = master
|
||||
tnic.Ip = ""
|
||||
tnic.Gateway = ""
|
||||
master.Name = fmt.Sprintf("bond%d", len(bondNics))
|
||||
master.TeamingSlaves = []*types.SServerNic{&nnic, &tnic}
|
||||
master.TeamingSlaves = []*types.SServerNic{nnic, &tnic}
|
||||
master.Mac = ""
|
||||
allNics = append(allNics, &nnic, &tnic, &master)
|
||||
bondNics = append(bondNics, &master)
|
||||
allNics = append(allNics, nnic, &tnic, master)
|
||||
bondNics = append(bondNics, master)
|
||||
}
|
||||
return allNics, bondNics
|
||||
}
|
||||
|
||||
@@ -22,13 +22,11 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/netutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
@@ -76,7 +74,7 @@ func (w *SWindowsRootFs) String() string {
|
||||
return "WindowsRootFs"
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) DeployPublicKey(IDiskPartition, string, *sshkeys.SSHKeys) error {
|
||||
func (w *SWindowsRootFs) DeployPublicKey(IDiskPartition, string, *deployapi.SSHKeys) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -90,7 +88,7 @@ func (w *SWindowsRootFs) RootSignatures() []string {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) GetReleaseInfo(IDiskPartition) *SReleaseInfo {
|
||||
func (w *SWindowsRootFs) GetReleaseInfo(IDiskPartition) *deployapi.ReleaseInfo {
|
||||
confPath := w.rootFs.GetLocalPath("/windows/system32/config", true)
|
||||
tool := winutils.NewWinRegTool(confPath)
|
||||
if tool.CheckPath() {
|
||||
@@ -98,7 +96,12 @@ func (w *SWindowsRootFs) GetReleaseInfo(IDiskPartition) *SReleaseInfo {
|
||||
version := tool.GetVersion()
|
||||
arch := tool.GetArch()
|
||||
lan := tool.GetInstallLanguage()
|
||||
return &SReleaseInfo{distro, version, arch, lan}
|
||||
return &deployapi.ReleaseInfo{
|
||||
Distro: distro,
|
||||
Version: version,
|
||||
Arch: arch,
|
||||
Language: lan,
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@@ -228,14 +231,14 @@ func (w *SWindowsRootFs) DeployHosts(part IDiskPartition, hn, domain string, ips
|
||||
return w.rootFs.FilePutContents(ETC_HOSTS, hf.String(), false, true)
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
mainNic, err := netutils2.GetMainNic(nics)
|
||||
func (w *SWindowsRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []*deployapi.Nic) error {
|
||||
mainNic, err := netutils2.GetMainNicFromDeployApi(nics)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mainIp := ""
|
||||
if mainNic != nil {
|
||||
mainIp, _ = mainNic.GetString("ip")
|
||||
mainIp = mainNic.Ip
|
||||
}
|
||||
bootScript := strings.Join([]string{
|
||||
`set NETCFG_SCRIPT=%SystemRoot%\netcfg.bat`,
|
||||
@@ -255,24 +258,19 @@ func (w *SWindowsRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []j
|
||||
}
|
||||
|
||||
for _, nic := range nics {
|
||||
snic := &types.SServerNic{}
|
||||
if err := nic.Unmarshal(snic); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
snic := &types.SServerNic{Nic: nic}
|
||||
mac := snic.Mac
|
||||
mac = strings.Replace(strings.ToUpper(mac), ":", "-", -1)
|
||||
lines = append(lines, fmt.Sprintf(` if "%%%%c" == "%s" (`, mac))
|
||||
if jsonutils.QueryBoolean(nic, "manual", false) {
|
||||
netmask := netutils2.Netlen2Mask(snic.Masklen)
|
||||
if snic.Manual {
|
||||
netmask := netutils2.Netlen2Mask(int(snic.Masklen))
|
||||
cfg := fmt.Sprintf(` netsh interface ip set address "%%%%b" static %s %s`, snic.Ip, netmask)
|
||||
if len(snic.Gateway) > 0 && snic.Ip == mainIp {
|
||||
cfg += fmt.Sprintf(" %s", snic.Gateway)
|
||||
}
|
||||
lines = append(lines, cfg)
|
||||
routes := [][]string{}
|
||||
netutils2.AddNicRoutes(&routes, snic, mainIp, len(nics), options.HostOptions.PrivatePrefixes)
|
||||
netutils2.AddNicRoutes(&routes, snic, mainIp, len(nics), privatePrefixes)
|
||||
for _, r := range routes {
|
||||
lines = append(lines, fmt.Sprintf(` netsh interface ip add route %s "%%%%b" %s`, r[0], r[1]))
|
||||
}
|
||||
@@ -449,7 +447,7 @@ func (w *SWindowsRootFs) deploySetupCompleteScripts(uname, passwd string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) DeployFstabScripts(rootFs IDiskPartition, disks []jsonutils.JSONObject) error {
|
||||
func (w *SWindowsRootFs) DeployFstabScripts(rootFs IDiskPartition, disks []*deployapi.Disk) error {
|
||||
if len(disks) == 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -52,13 +52,11 @@ func NewKVMGuestDiskPartition(devPath, sourceDev string, isLVM bool) *SKVMGuestD
|
||||
func (p *SKVMGuestDiskPartition) GetPhysicalPartitionType() string {
|
||||
dev := p.partDev
|
||||
if p.IsLVMPart {
|
||||
// for lvm part, sourceDev like /dev/nbdxpx
|
||||
idx := strings.LastIndexByte(p.sourceDev, 'p')
|
||||
if idx > 0 {
|
||||
dev = p.sourceDev[:idx]
|
||||
} else {
|
||||
dev = p.sourceDev
|
||||
}
|
||||
dev = p.sourceDev
|
||||
}
|
||||
idxP := strings.LastIndexByte(dev, 'p')
|
||||
if idxP > 0 {
|
||||
dev = dev[:idxP]
|
||||
}
|
||||
cmd := fmt.Sprintf(`fdisk -l %s | grep "Disk label type:"`, dev)
|
||||
output, err := procutils.NewCommand("sh", "-c", cmd).Run()
|
||||
|
||||
@@ -35,6 +35,12 @@ type SLocalGuestFS struct {
|
||||
mountPath string
|
||||
}
|
||||
|
||||
func NewLocalGuestFS(mountPath string) *SLocalGuestFS {
|
||||
var ret = new(SLocalGuestFS)
|
||||
ret.mountPath = mountPath
|
||||
return ret
|
||||
}
|
||||
|
||||
func (f *SLocalGuestFS) GetMountPath() string {
|
||||
return f.mountPath
|
||||
}
|
||||
@@ -256,9 +262,3 @@ func (f *SLocalGuestFS) FilePutContents(sPath, content string, modAppend, caseIn
|
||||
return fmt.Errorf("Cann't put content")
|
||||
}
|
||||
}
|
||||
|
||||
func NewLocalGuestFS(mountPath string) *SLocalGuestFS {
|
||||
var ret = new(SLocalGuestFS)
|
||||
ret.mountPath = mountPath
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package guesthandlers // import "yunion.io/x/onecloud/pkg/hostman/guesthandlers"
|
||||
package guesthandlers // import "yunion.io/x/onecloud/pkg/hostman/guestman/guesthandlers"
|
||||
+2
-2
@@ -452,7 +452,7 @@ func guestReloadDiskSnapshot(ctx context.Context, sid string, body jsonutils.JSO
|
||||
return nil, httperrors.NewNotFoundError("Disk not found")
|
||||
}
|
||||
|
||||
hostutils.DelayTaskWithoutReqctx(ctx, guestman.GetGuestManager().ReloadDiskSnapshot, &guestman.SReloadDisk{sid, disk})
|
||||
hostutils.DelayTask(ctx, guestman.GetGuestManager().ReloadDiskSnapshot, &guestman.SReloadDisk{sid, disk})
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -519,7 +519,7 @@ func guestDeleteSnapshot(ctx context.Context, sid string, body jsonutils.JSONObj
|
||||
Disk: disk,
|
||||
}
|
||||
|
||||
if !jsonutils.QueryBoolean(body, "auto_delete", false) {
|
||||
if !jsonutils.QueryBoolean(body, "auto_deleted", false) {
|
||||
convertSnapshot, err := body.GetString("convert_snapshot")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("convert_snapshot")
|
||||
@@ -25,24 +25,24 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs"
|
||||
"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/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/cgrouputils"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/netutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
"yunion.io/x/onecloud/pkg/util/timeutils2"
|
||||
compute "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
appsrv "yunion.io/x/onecloud/pkg/appsrv"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
hostutils "yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
options "yunion.io/x/onecloud/pkg/hostman/options"
|
||||
storageman "yunion.io/x/onecloud/pkg/hostman/storageman"
|
||||
httperrors "yunion.io/x/onecloud/pkg/httperrors"
|
||||
modules "yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
cgrouputils "yunion.io/x/onecloud/pkg/util/cgrouputils"
|
||||
fileutils2 "yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
netutils2 "yunion.io/x/onecloud/pkg/util/netutils2"
|
||||
seclib2 "yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
timeutils2 "yunion.io/x/onecloud/pkg/util/timeutils2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -323,7 +323,7 @@ func (m *SGuestManager) GuestDeploy(ctx context.Context, params interface{}) (js
|
||||
if jsonutils.QueryBoolean(deployParams.Body, "k8s_pod", false) {
|
||||
return nil, nil
|
||||
}
|
||||
publicKey := sshkeys.GetKeys(deployParams.Body)
|
||||
publicKey := deployapi.GetKeys(deployParams.Body)
|
||||
deploys, _ := deployParams.Body.GetArray("deploys")
|
||||
password, _ := deployParams.Body.GetString("password")
|
||||
resetPassword := jsonutils.QueryBoolean(deployParams.Body, "reset_password", false)
|
||||
@@ -332,12 +332,11 @@ func (m *SGuestManager) GuestDeploy(ctx context.Context, params interface{}) (js
|
||||
}
|
||||
enableCloudInit := jsonutils.QueryBoolean(deployParams.Body, "enable_cloud_init", false)
|
||||
|
||||
guestInfo, err := guest.DeployFs(guestfs.NewDeployInfo(
|
||||
publicKey, deploys, password, deployParams.IsInit, false,
|
||||
guestInfo, err := guest.DeployFs(deployapi.NewDeployInfo(
|
||||
publicKey, deployapi.JsonDeploysToStructs(deploys), password, deployParams.IsInit, false,
|
||||
options.HostOptions.LinuxDefaultRootUser, options.HostOptions.WindowsDefaultAdminUser, enableCloudInit))
|
||||
if err != nil {
|
||||
log.Errorf("Deploy guest fs error: %s", err)
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Deploy guest fs")
|
||||
} else {
|
||||
return guestInfo, nil
|
||||
}
|
||||
|
||||
@@ -587,8 +587,8 @@ func (s *SGuestStreamDisksTask) onBlockDrivesSucc(res *jsonutils.JSONArray) {
|
||||
if len(s.streamDevs) == 0 {
|
||||
s.taskComplete()
|
||||
} else {
|
||||
s.SyncStatus()
|
||||
s.startDoBlockStream()
|
||||
s.SyncStatus()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -679,8 +679,11 @@ func (s *SGuestReloadDiskTask) WaitSnapshotReplaced(callback func()) error {
|
||||
return fmt.Errorf(
|
||||
"SnapshotDeleteJob.deleting_disk_snapshot always has %s", s.disk.GetId())
|
||||
}
|
||||
if _, ok := storageman.DELETEING_SNAPSHOTS[s.disk.GetId()]; ok {
|
||||
|
||||
if _, ok := storageman.DELETEING_SNAPSHOTS.Load(s.disk.GetId()); ok {
|
||||
time.Sleep(time.Second * 1)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -747,7 +750,9 @@ func (s *SGuestReloadDiskTask) onReloadSucc(err string) {
|
||||
|
||||
func (s *SGuestReloadDiskTask) onResumeSucc(results string) {
|
||||
log.Infof("guest reload disk task resume succ %s", results)
|
||||
hostutils.TaskComplete(s.ctx, nil)
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("reopen", jsonutils.JSONTrue)
|
||||
hostutils.TaskComplete(s.ctx, params)
|
||||
}
|
||||
|
||||
func (s *SGuestReloadDiskTask) taskFailed(reason string) {
|
||||
@@ -803,8 +808,7 @@ func (s *SGuestDiskSnapshotTask) onSnapshotBlkdevFail(string) {
|
||||
|
||||
func (s *SGuestDiskSnapshotTask) onResumeSucc(res string) {
|
||||
log.Infof("guest disk snapshot task resume succ %s", res)
|
||||
snapshotDir := s.disk.GetSnapshotDir()
|
||||
snapshotLocation := path.Join(snapshotDir, s.snapshotId)
|
||||
snapshotLocation := path.Join(s.disk.GetSnapshotLocation(), s.snapshotId)
|
||||
body := jsonutils.NewDict()
|
||||
body.Set("location", jsonutils.NewString(snapshotLocation))
|
||||
hostutils.TaskComplete(s.ctx, body)
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/appctx"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostinfo/hostbridge"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
"yunion.io/x/onecloud/pkg/hostman/monitor"
|
||||
@@ -761,7 +761,7 @@ func (s *SKVMGuestInstance) StartGuest(ctx context.Context, params jsonutils.JSO
|
||||
func() { s.asyncScriptStart(ctx, jsonutils.NewDict()) }, nil, nil)
|
||||
}
|
||||
|
||||
func (s *SKVMGuestInstance) DeployFs(deployInfo *guestfs.SDeployInfo) (jsonutils.JSONObject, error) {
|
||||
func (s *SKVMGuestInstance) DeployFs(deployInfo *deployapi.DeployInfo) (jsonutils.JSONObject, error) {
|
||||
disks, _ := s.Desc.GetArray("disks")
|
||||
if len(disks) > 0 {
|
||||
diskPath, _ := disks[0].GetString("path")
|
||||
@@ -1354,9 +1354,9 @@ func (s *SKVMGuestInstance) StaticSaveSnapshot(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
location := path.Join(disk.GetSnapshotDir(), snapshotId)
|
||||
location := path.Join(disk.GetSnapshotLocation(), snapshotId)
|
||||
res := jsonutils.NewDict()
|
||||
res.Set("localtion", jsonutils.NewString(location))
|
||||
res.Set("location", jsonutils.NewString(location))
|
||||
return res, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -24,10 +24,10 @@ import (
|
||||
"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/diskhandlers"
|
||||
"yunion.io/x/onecloud/pkg/hostman/downloader"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guesthandlers"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestman"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestman/guesthandlers"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostinfo"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostmetrics"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
@@ -35,6 +35,8 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/hostman/metadata"
|
||||
"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/util/sysutils"
|
||||
)
|
||||
|
||||
@@ -49,7 +51,12 @@ func (host *SHostService) InitService() {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -64,6 +71,7 @@ func (host *SHostService) RunService() {
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
deployclient.Init(options.HostOptions.DeployServerSocketPath)
|
||||
if err := storageman.Init(hostInstance); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
@@ -104,7 +112,7 @@ func (host *SHostService) RunService() {
|
||||
|
||||
func (host *SHostService) initHandlers(app *appsrv.Application) {
|
||||
guesthandlers.AddGuestTaskHandler("", app)
|
||||
storageman.AddStorageHandler("", app)
|
||||
storagehandler.AddStorageHandler("", app)
|
||||
diskhandlers.AddDiskHandler("", app)
|
||||
downloader.AddDownloadHandler("", app)
|
||||
kubehandlers.AddKubeAgentHandler("", app)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,159 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package apis;
|
||||
|
||||
message GuestDesc {
|
||||
string name = 1;
|
||||
string uuid = 2;
|
||||
string domain = 3;
|
||||
|
||||
repeated Nic nics = 4;
|
||||
repeated Nic nics_standby = 5;
|
||||
repeated Disk disks = 6;
|
||||
}
|
||||
|
||||
message Disk {
|
||||
string disk_id = 1;
|
||||
string driver = 2;
|
||||
string cache_mode = 3;
|
||||
string aio_mode = 4;
|
||||
int64 size = 5;
|
||||
string template_id = 6;
|
||||
string image_path = 7;
|
||||
string storage_id = 8;
|
||||
bool migrating = 9;
|
||||
string target_storage_id = 10;
|
||||
string path = 11;
|
||||
string format = 12;
|
||||
int32 index = 13;
|
||||
bool merge_snapshot = 14;
|
||||
string fs = 15;
|
||||
string mountpoint = 16;
|
||||
string dev = 17;
|
||||
}
|
||||
|
||||
|
||||
message Nic {
|
||||
string mac = 1;
|
||||
string ip = 2;
|
||||
string net = 3;
|
||||
string net_id = 4;
|
||||
bool virtual = 5;
|
||||
string gateway = 6;
|
||||
string dns = 7;
|
||||
string domain = 8;
|
||||
repeated Routes routes = 9;
|
||||
string ifname = 10;
|
||||
int32 masklen = 11;
|
||||
string driver = 12;
|
||||
string bridge = 13;
|
||||
string wire_id = 14;
|
||||
int32 vlan = 15;
|
||||
string interface = 16;
|
||||
int32 bw = 17;
|
||||
int32 index = 18;
|
||||
repeated string virtual_ips = 19;
|
||||
string externel_id = 20;
|
||||
string team_with = 21;
|
||||
bool manual = 22;
|
||||
string nic_type = 23;
|
||||
bool link_up = 24;
|
||||
int64 mtu = 25;
|
||||
string name = 26;
|
||||
}
|
||||
|
||||
message Routes {
|
||||
repeated string route = 1;
|
||||
}
|
||||
|
||||
message DeployInfo {
|
||||
SSHKeys public_key = 1;
|
||||
repeated DeployContent deploys = 2;
|
||||
string password = 3;
|
||||
bool is_init = 4;
|
||||
bool enable_tty = 5;
|
||||
bool default_root_user = 6;
|
||||
bool windows_default_admin_user = 7;
|
||||
bool enable_cloud_init = 8;
|
||||
}
|
||||
|
||||
message SSHKeys {
|
||||
string public_key = 1;
|
||||
string delete_public_key = 2;
|
||||
string admin_public_key = 3;
|
||||
string project_public_key = 4;
|
||||
}
|
||||
|
||||
message DeployContent {
|
||||
string path = 1;
|
||||
string content = 2;
|
||||
string action = 3;
|
||||
}
|
||||
|
||||
message Empty {
|
||||
}
|
||||
|
||||
message DeployGuestFsResponse {
|
||||
string distro = 1;
|
||||
string version = 2;
|
||||
string arch = 3;
|
||||
string language = 4;
|
||||
string os = 5;
|
||||
string account = 6;
|
||||
string key = 7;
|
||||
}
|
||||
|
||||
message DeployParams {
|
||||
string disk_path = 1;
|
||||
GuestDesc guest_desc = 2;
|
||||
DeployInfo deploy_info = 3;
|
||||
}
|
||||
|
||||
message ResizeFsParams {
|
||||
string disk_path = 1;
|
||||
}
|
||||
|
||||
message FormatFsParams {
|
||||
string disk_path = 1;
|
||||
string fs_format = 2;
|
||||
string uuid = 3;
|
||||
}
|
||||
|
||||
message ReleaseInfo {
|
||||
string distro = 1;
|
||||
string version = 2;
|
||||
string arch = 3;
|
||||
string language = 4;
|
||||
}
|
||||
|
||||
message SaveToGlanceParams {
|
||||
string disk_path = 1;
|
||||
bool compress = 2;
|
||||
}
|
||||
|
||||
message SaveToGlanceResponse {
|
||||
string os_info = 1;
|
||||
ReleaseInfo release_info = 2;
|
||||
}
|
||||
|
||||
message ProbeImageInfoPramas {
|
||||
string disk_path = 1;
|
||||
}
|
||||
|
||||
message ImageInfo {
|
||||
ReleaseInfo os_info = 1;
|
||||
string os_type = 2;
|
||||
bool is_uefi_support = 3;
|
||||
bool is_lvm_partition = 4;
|
||||
bool is_readonly = 5;
|
||||
string physical_partition_type = 6;
|
||||
bool is_installed_cloud_init = 7;
|
||||
}
|
||||
|
||||
service DeployAgent {
|
||||
rpc DeployGuestFs (DeployParams) returns (DeployGuestFsResponse);
|
||||
rpc ResizeFs (ResizeFsParams) returns (Empty);
|
||||
rpc FormatFs (FormatFsParams) returns (Empty);
|
||||
rpc SaveToGlance (SaveToGlanceParams) returns (SaveToGlanceResponse);
|
||||
rpc ProbeImageInfo(ProbeImageInfoPramas) returns (ImageInfo);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package apis // import "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
@@ -0,0 +1,114 @@
|
||||
// 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 apis
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
)
|
||||
|
||||
func NewDeployInfo(
|
||||
publicKey *SSHKeys,
|
||||
deploys []*DeployContent,
|
||||
password string,
|
||||
isInit bool,
|
||||
enableTty bool,
|
||||
defaultRootUser bool,
|
||||
windowsDefaultAdminUser bool,
|
||||
enableCloudInit bool,
|
||||
) *DeployInfo {
|
||||
return &DeployInfo{
|
||||
PublicKey: publicKey,
|
||||
Deploys: deploys,
|
||||
Password: password,
|
||||
IsInit: isInit,
|
||||
EnableTty: enableTty,
|
||||
DefaultRootUser: defaultRootUser,
|
||||
WindowsDefaultAdminUser: windowsDefaultAdminUser,
|
||||
EnableCloudInit: enableCloudInit,
|
||||
}
|
||||
}
|
||||
|
||||
func JsonDeploysToStructs(jdeploys []jsonutils.JSONObject) []*DeployContent {
|
||||
ret := []*DeployContent{}
|
||||
for i := 0; i < len(jdeploys); i++ {
|
||||
d := new(DeployContent)
|
||||
path, err := jdeploys[i].GetString("path")
|
||||
if err == nil {
|
||||
d.Path = path
|
||||
}
|
||||
content, err := jdeploys[i].GetString("content")
|
||||
if err == nil {
|
||||
d.Content = content
|
||||
}
|
||||
ret = append(ret, d)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetKeys(data jsonutils.JSONObject) *SSHKeys {
|
||||
var ret = new(SSHKeys)
|
||||
ret.PublicKey, _ = data.GetString("public_key")
|
||||
ret.DeletePublicKey, _ = data.GetString("delete_public_key")
|
||||
ret.AdminPublicKey, _ = data.GetString("admin_public_key")
|
||||
ret.ProjectPublicKey, _ = data.GetString("project_public_key")
|
||||
return ret
|
||||
}
|
||||
|
||||
func GuestDescToDeployDesc(guestDesc *jsonutils.JSONDict) (*GuestDesc, error) {
|
||||
ret := new(GuestDesc)
|
||||
ret.Name, _ = guestDesc.GetString("name")
|
||||
ret.Domain, _ = guestDesc.GetString("domain")
|
||||
ret.Uuid, _ = guestDesc.GetString("uuid")
|
||||
jnics, _ := guestDesc.Get("nics")
|
||||
jdisks, _ := guestDesc.Get("disks")
|
||||
jnicsStandby, _ := guestDesc.Get("nics_standby")
|
||||
|
||||
if jnics != nil {
|
||||
nics := make([]*Nic, 0)
|
||||
err := jnics.Unmarshal(&nics)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret.Nics = nics
|
||||
}
|
||||
|
||||
if jdisks != nil {
|
||||
disks := make([]*Disk, 0)
|
||||
err := jdisks.Unmarshal(&disks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret.Disks = disks
|
||||
}
|
||||
|
||||
if jnicsStandby != nil {
|
||||
nicsStandby := make([]*Nic, 0)
|
||||
err := jnicsStandby.Unmarshal(nicsStandby)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret.NicsStandby = nicsStandby
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func NewReleaseInfo(distro, version, arch string) *ReleaseInfo {
|
||||
return &ReleaseInfo{
|
||||
Distro: distro,
|
||||
Version: version,
|
||||
Arch: arch,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// 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 deployclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
)
|
||||
|
||||
var (
|
||||
deployClient *DeployClient
|
||||
_ deployapi.DeployAgentClient = deployClient
|
||||
)
|
||||
|
||||
func Init(socketPath string) {
|
||||
deployClient = NewDeployClient(socketPath)
|
||||
}
|
||||
|
||||
type DeployClient struct {
|
||||
socketPath string
|
||||
}
|
||||
|
||||
func NewDeployClient(socketPath string) *DeployClient {
|
||||
return &DeployClient{socketPath}
|
||||
}
|
||||
|
||||
func GetDeployClient() *DeployClient {
|
||||
return deployClient
|
||||
}
|
||||
|
||||
func grcpDialWithUnixSocket(ctx context.Context, socketPath string) (*grpc.ClientConn, error) {
|
||||
return grpc.DialContext(ctx, socketPath, grpc.WithInsecure(), grpc.WithBlock(),
|
||||
grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
|
||||
return net.DialTimeout("unix", addr, timeout)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
func (c *DeployClient) DeployGuestFs(ctx context.Context, in *deployapi.DeployParams, opts ...grpc.CallOption) (*deployapi.DeployGuestFsResponse, error) {
|
||||
conn, err := grcpDialWithUnixSocket(ctx, c.socketPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := deployapi.NewDeployAgentClient(conn)
|
||||
ret, err := client.DeployGuestFs(ctx, in, opts...)
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (c *DeployClient) ResizeFs(ctx context.Context, in *deployapi.ResizeFsParams, opts ...grpc.CallOption) (*deployapi.Empty, error) {
|
||||
conn, err := grcpDialWithUnixSocket(ctx, c.socketPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := deployapi.NewDeployAgentClient(conn)
|
||||
return client.ResizeFs(ctx, in, opts...)
|
||||
}
|
||||
|
||||
func (c *DeployClient) FormatFs(ctx context.Context, in *deployapi.FormatFsParams, opts ...grpc.CallOption) (*deployapi.Empty, error) {
|
||||
conn, err := grcpDialWithUnixSocket(ctx, c.socketPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := deployapi.NewDeployAgentClient(conn)
|
||||
return client.FormatFs(ctx, in, opts...)
|
||||
}
|
||||
|
||||
func (c *DeployClient) SaveToGlance(ctx context.Context, in *deployapi.SaveToGlanceParams, opts ...grpc.CallOption) (*deployapi.SaveToGlanceResponse, error) {
|
||||
conn, err := grcpDialWithUnixSocket(ctx, c.socketPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := deployapi.NewDeployAgentClient(conn)
|
||||
return client.SaveToGlance(ctx, in, opts...)
|
||||
}
|
||||
|
||||
func (c *DeployClient) ProbeImageInfo(ctx context.Context, in *deployapi.ProbeImageInfoPramas, opts ...grpc.CallOption) (*deployapi.ImageInfo, error) {
|
||||
conn, err := grcpDialWithUnixSocket(ctx, c.socketPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
client := deployapi.NewDeployAgentClient(conn)
|
||||
return client.ProbeImageInfo(ctx, in, opts...)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package deployclient // import "yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient"
|
||||
@@ -0,0 +1,254 @@
|
||||
// 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 deployserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"yunion.io/x/log"
|
||||
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
service "yunion.io/x/onecloud/pkg/cloudcommon/service"
|
||||
diskutils "yunion.io/x/onecloud/pkg/hostman/diskutils"
|
||||
nbd "yunion.io/x/onecloud/pkg/hostman/diskutils/nbd"
|
||||
guestfs "yunion.io/x/onecloud/pkg/hostman/guestfs"
|
||||
fsdriver "yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
fileutils2 "yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
"yunion.io/x/onecloud/pkg/util/sysutils"
|
||||
"yunion.io/x/onecloud/pkg/util/winutils"
|
||||
)
|
||||
|
||||
type DeployerServer struct{}
|
||||
|
||||
func (*DeployerServer) DeployGuestFs(ctx context.Context, req *deployapi.DeployParams,
|
||||
) (*deployapi.DeployGuestFsResponse, error) {
|
||||
log.Infof("Deploy guest fs on %s", req.DiskPath)
|
||||
var kvmDisk = diskutils.NewKVMGuestDisk(req.DiskPath)
|
||||
defer kvmDisk.Disconnect()
|
||||
if !kvmDisk.Connect() {
|
||||
log.Infof("Failed to connect kvm disk")
|
||||
return new(deployapi.DeployGuestFsResponse), nil
|
||||
}
|
||||
|
||||
root := kvmDisk.MountKvmRootfs()
|
||||
if root == nil {
|
||||
log.Infof("Failed mounting rootfs for kvm disk")
|
||||
return new(deployapi.DeployGuestFsResponse), nil
|
||||
}
|
||||
defer kvmDisk.UmountKvmRootfs(root)
|
||||
|
||||
ret, err := guestfs.DoDeployGuestFs(root, req.GuestDesc, req.DeployInfo)
|
||||
if err != nil {
|
||||
return new(deployapi.DeployGuestFsResponse), err
|
||||
}
|
||||
if ret == nil {
|
||||
return new(deployapi.DeployGuestFsResponse), nil
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (*DeployerServer) ResizeFs(ctx context.Context, req *deployapi.ResizeFsParams,
|
||||
) (*deployapi.Empty, error) {
|
||||
log.Infof("Resize fs on %s", req.DiskPath)
|
||||
disk := diskutils.NewKVMGuestDisk(req.DiskPath)
|
||||
defer disk.Disconnect()
|
||||
if disk.Connect() {
|
||||
if err := disk.ResizePartition(); err != nil {
|
||||
return new(deployapi.Empty), err
|
||||
}
|
||||
}
|
||||
return new(deployapi.Empty), nil
|
||||
}
|
||||
|
||||
func (*DeployerServer) FormatFs(ctx context.Context, req *deployapi.FormatFsParams) (*deployapi.Empty, error) {
|
||||
log.Infof("Format fs on %s", req.DiskPath)
|
||||
gd := diskutils.NewKVMGuestDisk(req.DiskPath)
|
||||
defer gd.Disconnect()
|
||||
if gd.Connect() {
|
||||
if err := gd.MakePartition(req.FsFormat); err == nil {
|
||||
err = gd.FormatPartition(req.FsFormat, req.Uuid)
|
||||
if err != nil {
|
||||
return new(deployapi.Empty), err
|
||||
}
|
||||
} else {
|
||||
return new(deployapi.Empty), err
|
||||
}
|
||||
}
|
||||
return new(deployapi.Empty), nil
|
||||
}
|
||||
|
||||
func (*DeployerServer) SaveToGlance(ctx context.Context, req *deployapi.SaveToGlanceParams) (*deployapi.SaveToGlanceResponse, error) {
|
||||
log.Infof("%s save to glance", req.DiskPath)
|
||||
var (
|
||||
kvmDisk = diskutils.NewKVMGuestDisk(req.DiskPath)
|
||||
osInfo string
|
||||
relInfo *deployapi.ReleaseInfo
|
||||
)
|
||||
defer kvmDisk.Disconnect()
|
||||
if kvmDisk.Connect() {
|
||||
var err error
|
||||
func() {
|
||||
if root := kvmDisk.MountKvmRootfs(); root != nil {
|
||||
defer kvmDisk.UmountKvmRootfs(root)
|
||||
|
||||
osInfo = root.GetOs()
|
||||
relInfo = root.GetReleaseInfo(root.GetPartition())
|
||||
if req.Compress {
|
||||
err = root.PrepareFsForTemplate(root.GetPartition())
|
||||
}
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return new(deployapi.SaveToGlanceResponse), err
|
||||
}
|
||||
|
||||
if req.Compress {
|
||||
kvmDisk.Zerofree()
|
||||
}
|
||||
}
|
||||
return &deployapi.SaveToGlanceResponse{
|
||||
OsInfo: osInfo,
|
||||
ReleaseInfo: relInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getImageInfo(kvmDisk *diskutils.SKVMGuestDisk, rootfs fsdriver.IRootFsDriver) *deployapi.ImageInfo {
|
||||
partition := rootfs.GetPartition()
|
||||
return &deployapi.ImageInfo{
|
||||
OsInfo: rootfs.GetReleaseInfo(partition),
|
||||
OsType: rootfs.GetOs(),
|
||||
IsUefiSupport: kvmDisk.DetectIsUEFISupport(rootfs),
|
||||
IsLvmPartition: kvmDisk.IsLVMPartition(),
|
||||
IsReadonly: partition.IsReadonly(),
|
||||
PhysicalPartitionType: partition.GetPhysicalPartitionType(),
|
||||
IsInstalledCloudInit: rootfs.IsCloudinitInstall(),
|
||||
}
|
||||
}
|
||||
|
||||
func (*DeployerServer) ProbeImageInfo(ctx context.Context, req *deployapi.ProbeImageInfoPramas) (*deployapi.ImageInfo, error) {
|
||||
log.Infof("%s probe image info", req.DiskPath)
|
||||
kvmDisk := diskutils.NewKVMGuestDisk(req.DiskPath)
|
||||
defer kvmDisk.Disconnect()
|
||||
if !kvmDisk.Connect() {
|
||||
log.Infof("Failed to connect kvm disk")
|
||||
return new(deployapi.ImageInfo), errors.New("Disk connector failed to connect image")
|
||||
}
|
||||
|
||||
// Fsck is executed during mount
|
||||
rootfs := kvmDisk.MountKvmRootfs()
|
||||
if rootfs == nil {
|
||||
return new(deployapi.ImageInfo), fmt.Errorf("Failed mounting rootfs for kvm disk")
|
||||
}
|
||||
defer kvmDisk.UmountKvmRootfs(rootfs)
|
||||
imageInfo := getImageInfo(kvmDisk, rootfs)
|
||||
log.Infof("ProbeImageInfo response %s", imageInfo)
|
||||
return imageInfo, nil
|
||||
}
|
||||
|
||||
type SDeployService struct {
|
||||
*service.SServiceBase
|
||||
}
|
||||
|
||||
func NewDeployService() *SDeployService {
|
||||
deployer := &SDeployService{}
|
||||
deployer.SServiceBase = service.NewBaseService(deployer)
|
||||
return deployer
|
||||
}
|
||||
|
||||
func (s *SDeployService) RunService() {
|
||||
grpcServer := grpc.NewServer()
|
||||
deployapi.RegisterDeployAgentServer(grpcServer, &DeployerServer{})
|
||||
if fileutils2.Exists(DeployOption.DeployServerSocketPath) {
|
||||
if err := os.Remove(DeployOption.DeployServerSocketPath); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
listener, err := net.Listen("unix", DeployOption.DeployServerSocketPath)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
defer listener.Close()
|
||||
log.Infof("Init net listener on %s succ", DeployOption.DeployServerSocketPath)
|
||||
grpcServer.Serve(listener)
|
||||
}
|
||||
|
||||
func (s *SDeployService) FixPathEnv() error {
|
||||
var paths = []string{
|
||||
"/usr/local/sbin",
|
||||
"/usr/local/bin",
|
||||
"/sbin",
|
||||
"/bin",
|
||||
"/usr/sbin",
|
||||
"/usr/bin",
|
||||
}
|
||||
return os.Setenv("PATH", strings.Join(paths, ":"))
|
||||
}
|
||||
|
||||
func (s *SDeployService) PrepareEnv() error {
|
||||
if err := s.FixPathEnv(); err != nil {
|
||||
return err
|
||||
}
|
||||
output, err := procutils.NewCommand("rmmod", "nbd").Run()
|
||||
if err != nil {
|
||||
log.Errorf("rmmod error: %s", output)
|
||||
}
|
||||
output, err = procutils.NewCommand("modprobe", "nbd", "max_part=16").Run()
|
||||
if err != nil {
|
||||
log.Errorf("Failed to activate nbd device: %s", output)
|
||||
}
|
||||
nbd.Init()
|
||||
|
||||
for i := 0; i < 16; i++ {
|
||||
nbdBdi := fmt.Sprintf("/sys/block/nbd%d/bdi/", i)
|
||||
sysutils.SetSysConfig(nbdBdi+"max_ratio", "0")
|
||||
sysutils.SetSysConfig(nbdBdi+"min_ratio", "0")
|
||||
}
|
||||
|
||||
if !winutils.CheckTool(DeployOption.ChntpwPath) {
|
||||
log.Errorf("Failed to find chntpw tool")
|
||||
}
|
||||
|
||||
output, err = procutils.NewCommand("pvscan").Run()
|
||||
if err != nil {
|
||||
log.Errorf("Failed exec lvm command pvscan: %s", output)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SDeployService) InitService() {
|
||||
common_options.ParseOptions(&DeployOption, os.Args, "host.conf", "deploy-server")
|
||||
if err := s.PrepareEnv(); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
fsdriver.Init(DeployOption.PrivatePrefixes)
|
||||
s.O = &DeployOption.BaseOptions
|
||||
if len(DeployOption.DeployServerSocketPath) == 0 {
|
||||
log.Fatalf("missing deploy server socket path")
|
||||
}
|
||||
// TODO implentment func onExit
|
||||
s.SignalTrap(nil)
|
||||
}
|
||||
|
||||
func (s *SDeployService) OnExitService() {}
|
||||
@@ -0,0 +1 @@
|
||||
package deployserver // import "yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployserver"
|
||||
@@ -0,0 +1,27 @@
|
||||
// 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 deployserver
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
|
||||
type SDeployOptions struct {
|
||||
options.BaseOptions
|
||||
|
||||
DeployServerSocketPath string `help:"Deploy server listen socket path"`
|
||||
PrivatePrefixes []string `help:"IPv4 private prefixes"`
|
||||
ChntpwPath string `help:"path to chntpw tool" default:"/usr/local/bin/chntpw.static"`
|
||||
}
|
||||
|
||||
var DeployOption SDeployOptions
|
||||
@@ -98,7 +98,7 @@ func (s *SGuestDHCPServer) getGuestConfig(guestDesc, guestNic jsonutils.JSONObje
|
||||
|
||||
masklen := nicdesc.Masklen
|
||||
conf.ServerIP = net.ParseIP(v4Ip.NetAddr(int8(masklen)).String())
|
||||
conf.SubnetMask = net.ParseIP(netutils2.Netlen2Mask(masklen))
|
||||
conf.SubnetMask = net.ParseIP(netutils2.Netlen2Mask(int(masklen)))
|
||||
conf.BroadcastAddr = v4Ip.BroadcastAddr(int8(masklen)).ToBytes()
|
||||
conf.Hostname, _ = guestDesc.GetString("name")
|
||||
conf.Domain = nicdesc.Domain
|
||||
|
||||
@@ -31,14 +31,13 @@ import (
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostinfo/hostbridge"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
"yunion.io/x/onecloud/pkg/hostman/isolated_device"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman/nbd"
|
||||
"yunion.io/x/onecloud/pkg/hostman/system_service"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
@@ -50,7 +49,6 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/util/qemutils"
|
||||
"yunion.io/x/onecloud/pkg/util/sysutils"
|
||||
"yunion.io/x/onecloud/pkg/util/timeutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/winutils"
|
||||
)
|
||||
|
||||
type SHostInfo struct {
|
||||
@@ -214,25 +212,6 @@ func (h *SHostInfo) prepareEnv() error {
|
||||
return fmt.Errorf("Cannot initialize control group subsystem")
|
||||
}
|
||||
|
||||
output, err = procutils.NewCommand("rmmod", "nbd").Run()
|
||||
if err != nil {
|
||||
log.Errorf("rmmod error: %s", output)
|
||||
}
|
||||
output, err = procutils.NewCommand("modprobe", "nbd", "max_part=16").Run()
|
||||
if err != nil {
|
||||
log.Errorf("Failed to activate nbd device: %s", output)
|
||||
}
|
||||
nbd.Init()
|
||||
|
||||
if !winutils.CheckTool(options.HostOptions.ChntpwPath) {
|
||||
return fmt.Errorf("Failed to find chntpw tool")
|
||||
}
|
||||
|
||||
output, err = procutils.NewCommand("pvscan").Run()
|
||||
if err != nil {
|
||||
log.Errorf("Failed exec lvm command pvscan: %s", output)
|
||||
}
|
||||
|
||||
if err := hostbridge.Prepare(options.HostOptions.BridgeDriver); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
@@ -261,11 +240,7 @@ func (h *SHostInfo) prepareEnv() error {
|
||||
default:
|
||||
return fmt.Errorf("Invalid hugepages option")
|
||||
}
|
||||
for i := 0; i < 16; i++ {
|
||||
nbdBdi := fmt.Sprintf("/sys/block/nbd%d/bdi/", i)
|
||||
h.setSysConfig(nbdBdi+"max_ratio", "0")
|
||||
h.setSysConfig(nbdBdi+"min_ratio", "0")
|
||||
}
|
||||
|
||||
h.PreventArpFlux()
|
||||
h.TuneSystem()
|
||||
return nil
|
||||
@@ -312,7 +287,7 @@ func (h *SHostInfo) checkSystemServices() error {
|
||||
}
|
||||
}
|
||||
|
||||
for _, srv := range []string{"host_sdnagent"} {
|
||||
for _, srv := range []string{"host_sdnagent", "host-deployer"} {
|
||||
srvinst := system_service.GetService(srv)
|
||||
if !srvinst.IsInstalled() {
|
||||
log.Warningf("Service %s not installed", srv)
|
||||
@@ -350,7 +325,7 @@ func (h *SHostInfo) DisableHugepages() {
|
||||
"/sys/kernel/mm/transparent_hugepage/defrag": "never",
|
||||
}
|
||||
for k, v := range kv {
|
||||
h.setSysConfig(k, v)
|
||||
sysutils.SetSysConfig(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +336,7 @@ func (h *SHostInfo) EnableTransparentHugepages() {
|
||||
"/sys/kernel/mm/transparent_hugepage/defrag": "always",
|
||||
}
|
||||
for k, v := range kv {
|
||||
h.setSysConfig(k, v)
|
||||
sysutils.SetSysConfig(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,7 +355,7 @@ func (h *SHostInfo) EnableNativeHugepages() error {
|
||||
"/sys/kernel/mm/transparent_hugepage/defrag": "never",
|
||||
}
|
||||
for k, v := range kv {
|
||||
h.setSysConfig(k, v)
|
||||
sysutils.SetSysConfig(k, v)
|
||||
}
|
||||
preAllocPagesNum := h.GetMemory()/h.Mem.GetHugepagesizeMb() + 1
|
||||
err := timeutils2.CommandWithTimeout(1, "sh", "-c", fmt.Sprintf("echo %d > /proc/sys/vm/nr_hugepages", preAllocPagesNum)).Run()
|
||||
@@ -397,36 +372,18 @@ func (h *SHostInfo) EnableNativeHugepages() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *SHostInfo) setSysConfig(cpath, val string) bool {
|
||||
if fileutils2.Exists(cpath) {
|
||||
oval, err := ioutil.ReadFile(cpath)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return false
|
||||
}
|
||||
if string(oval) != val {
|
||||
err = fileutils2.FilePutContents(cpath, val, false)
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
log.Errorln(err)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *SHostInfo) EnableKsm(sleepSec int) {
|
||||
h.setSysConfig("/sys/kernel/mm/ksm/run", "1")
|
||||
h.setSysConfig("/sys/kernel/mm/ksm/sleep_millisecs",
|
||||
sysutils.SetSysConfig("/sys/kernel/mm/ksm/run", "1")
|
||||
sysutils.SetSysConfig("/sys/kernel/mm/ksm/sleep_millisecs",
|
||||
fmt.Sprintf("%d", sleepSec*1000))
|
||||
}
|
||||
|
||||
func (h *SHostInfo) DisableKsm() {
|
||||
h.setSysConfig("/sys/kernel/mm/ksm/run", "0")
|
||||
sysutils.SetSysConfig("/sys/kernel/mm/ksm/run", "0")
|
||||
}
|
||||
|
||||
func (h *SHostInfo) PreventArpFlux() {
|
||||
h.setSysConfig("/proc/sys/net/ipv4/conf/all/arp_filter", "1")
|
||||
sysutils.SetSysConfig("/proc/sys/net/ipv4/conf/all/arp_filter", "1")
|
||||
}
|
||||
|
||||
// Any system wide optimizations
|
||||
@@ -436,7 +393,7 @@ func (h *SHostInfo) TuneSystem() {
|
||||
"/sys/module/kvm/parameters/ignore_msrs": "1",
|
||||
}
|
||||
for k, v := range kv {
|
||||
h.setSysConfig(k, v)
|
||||
sysutils.SetSysConfig(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1158,7 +1115,7 @@ func (h *SHostInfo) deployAdminAuthorizedKeys() {
|
||||
}
|
||||
keys := ret.Data[0]
|
||||
adminPublicKey, _ := keys.GetString("public_key")
|
||||
pubKeys := &sshkeys.SSHKeys{AdminPublicKey: adminPublicKey}
|
||||
pubKeys := &deployapi.SSHKeys{AdminPublicKey: adminPublicKey}
|
||||
|
||||
authFile := path.Join(sshDir, "authorized_keys")
|
||||
oldKeysBytes, _ := fileutils2.FileGetContents(authFile)
|
||||
|
||||
@@ -63,7 +63,7 @@ type SHostOptions struct {
|
||||
LocalImagePath []string `help:"Local image storage paths"`
|
||||
SharedStorages []string `help:"Path of shared storages"`
|
||||
|
||||
DefaultQemuVersion string `help:"Default qemu version" default:"2.9.1"`
|
||||
DefaultQemuVersion string `help:"Default qemu version" default:"2.12.1"`
|
||||
|
||||
DhcpRelay []string `help:"DHCP relay upstream"`
|
||||
DhcpLeaseTime int `default:"100663296" help:"DHCP lease time in seconds"`
|
||||
@@ -104,6 +104,8 @@ type SHostOptions struct {
|
||||
HostCpuPassthrough bool `default:"true" help:"if it is true, set qemu cpu type as -cpu host, otherwise, qemu64. default is true"`
|
||||
|
||||
MaxReservedMemory int `default:"10240" help:"host reserved memory"`
|
||||
|
||||
DeployServerSocketPath string `help:"Deploy server listen socket path"`
|
||||
}
|
||||
|
||||
var HostOptions SHostOptions
|
||||
|
||||
@@ -61,7 +61,7 @@ func NewStorageManager(host hostutils.IHost) (*SStorageManager, error) {
|
||||
for i, d := range options.HostOptions.LocalImagePath {
|
||||
s := NewLocalStorage(ret, d, i)
|
||||
if s.Accessible() {
|
||||
s.StartSnapshotRecycle()
|
||||
StartSnapshotRecycle(s)
|
||||
ret.Storages = append(ret.Storages, s)
|
||||
if allFull && s.GetFreeSizeMb() > MINIMAL_FREE_SPACE {
|
||||
allFull = false
|
||||
|
||||
@@ -19,10 +19,12 @@ import (
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient"
|
||||
)
|
||||
|
||||
type IDisk interface {
|
||||
@@ -33,6 +35,7 @@ type IDisk interface {
|
||||
GetSnapshotDir() string
|
||||
GetDiskDesc() jsonutils.JSONObject
|
||||
GetDiskSetupScripts(idx int) string
|
||||
GetSnapshotLocation() string
|
||||
|
||||
DeleteAllSnapshot() error
|
||||
Delete(ctx context.Context, params interface{}) (jsonutils.JSONObject, error)
|
||||
@@ -42,16 +45,17 @@ type IDisk interface {
|
||||
CleanupSnapshots(ctx context.Context, params interface{}) (jsonutils.JSONObject, error)
|
||||
|
||||
PrepareMigrate(liveMigrate bool) (string, error)
|
||||
CreateFromUrl(context.Context, string) error
|
||||
CreateFromUrl(ctx context.Context, url string, size int64) error
|
||||
CreateFromTemplate(context.Context, string, string, int64) (jsonutils.JSONObject, error)
|
||||
CreateFromImageFuse(context.Context, string) error
|
||||
CreateFromSnapshotLocation(ctx context.Context, location string, size int64) error
|
||||
CreateFromImageFuse(ctx context.Context, url string, size int64) error
|
||||
CreateRaw(ctx context.Context, sizeMb int, diskFromat string, fsFormat string,
|
||||
encryption bool, diskId string, back string) (jsonutils.JSONObject, error)
|
||||
PostCreateFromImageFuse()
|
||||
CreateSnapshot(snapshotId string) error
|
||||
DeleteSnapshot(snapshotId, convertSnapshot string, pendingDelete bool) error
|
||||
DeployGuestFs(diskPath string, guestDesc *jsonutils.JSONDict,
|
||||
deployInfo *guestfs.SDeployInfo) (jsonutils.JSONObject, error)
|
||||
deployInfo *deployapi.DeployInfo) (jsonutils.JSONObject, error)
|
||||
}
|
||||
|
||||
type SBaseDisk struct {
|
||||
@@ -82,7 +86,7 @@ func (d *SBaseDisk) Delete(ctx context.Context, params interface{}) (jsonutils.J
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (d *SBaseDisk) CreateFromUrl(context.Context, string) error {
|
||||
func (d *SBaseDisk) CreateFromUrl(ctx context.Context, url string, size int64) error {
|
||||
return fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
@@ -90,6 +94,10 @@ func (d *SBaseDisk) CreateFromTemplate(context.Context, string, string, int64) (
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (d *SBaseDisk) CreateFromSnapshotLocation(ctx context.Context, location string, size int64) error {
|
||||
return fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (d *SBaseDisk) Resize(context.Context, interface{}) (jsonutils.JSONObject, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
@@ -99,36 +107,49 @@ func (d *SBaseDisk) GetZone() string {
|
||||
}
|
||||
|
||||
func (d *SBaseDisk) DeployGuestFs(diskPath string, guestDesc *jsonutils.JSONDict,
|
||||
deployInfo *guestfs.SDeployInfo) (jsonutils.JSONObject, error) {
|
||||
var kvmDisk = NewKVMGuestDisk(diskPath)
|
||||
|
||||
defer kvmDisk.Disconnect()
|
||||
if !kvmDisk.Connect() {
|
||||
log.Infof("Failed to connect kvm disk")
|
||||
return nil, nil
|
||||
deployInfo *deployapi.DeployInfo) (jsonutils.JSONObject, error) {
|
||||
deployGuestDesc, err := deployapi.GuestDescToDeployDesc(guestDesc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "guest desc to deploy desc")
|
||||
}
|
||||
|
||||
root := kvmDisk.MountKvmRootfs()
|
||||
if root == nil {
|
||||
log.Infof("Failed mounting rootfs for kvm disk")
|
||||
return nil, nil
|
||||
ret, err := deployclient.GetDeployClient().DeployGuestFs(
|
||||
context.Background(), &deployapi.DeployParams{
|
||||
DiskPath: diskPath,
|
||||
GuestDesc: deployGuestDesc,
|
||||
DeployInfo: deployInfo,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "request deploy guest fs")
|
||||
}
|
||||
defer kvmDisk.UmountKvmRootfs(root)
|
||||
|
||||
return guestfs.DeployGuestFs(root, guestDesc, deployInfo)
|
||||
return jsonutils.Marshal(ret), nil
|
||||
}
|
||||
|
||||
func (d *SBaseDisk) ResizeFs(diskPath string) error {
|
||||
disk := NewKVMGuestDisk(diskPath)
|
||||
defer disk.Disconnect()
|
||||
if disk.Connect() {
|
||||
if err := disk.ResizePartition(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
_, err := deployclient.GetDeployClient().ResizeFs(
|
||||
context.Background(), &deployapi.ResizeFsParams{DiskPath: diskPath})
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *SBaseDisk) GetDiskSetupScripts(diskIndex int) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (d *SBaseDisk) GetSnapshotLocation() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (d *SBaseDisk) FormatFs(fsFormat, uuid, diskPath string) {
|
||||
log.Infof("Make disk %s fs %s", uuid, fsFormat)
|
||||
_, err := deployclient.GetDeployClient().FormatFs(
|
||||
context.Background(),
|
||||
&deployapi.FormatFsParams{
|
||||
DiskPath: diskPath,
|
||||
FsFormat: fsFormat,
|
||||
Uuid: uuid,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf("Format fs error : %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@ func (d *SLocalDisk) GetSnapshotDir() string {
|
||||
return path.Join(d.Storage.GetSnapshotDir(), d.Id+options.HostOptions.SnapshotDirSuffix)
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) GetSnapshotLocation() string {
|
||||
return d.GetSnapshotDir()
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) Probe() error {
|
||||
if fileutils2.Exists(d.getPath()) {
|
||||
d.isAlter = false
|
||||
@@ -137,7 +141,7 @@ func (d *SLocalDisk) Resize(ctx context.Context, params interface{}) (jsonutils.
|
||||
return d.GetDiskDesc(), nil
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) CreateFromImageFuse(ctx context.Context, url string) error {
|
||||
func (d *SLocalDisk) CreateFromImageFuse(ctx context.Context, url string, size int64) error {
|
||||
log.Infof("Create from image fuse %s", url)
|
||||
|
||||
var (
|
||||
@@ -223,7 +227,7 @@ func (d *SLocalDisk) createFromTemplate(
|
||||
}
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) CreateFromUrl(ctx context.Context, url string) error {
|
||||
func (d *SLocalDisk) CreateFromUrl(ctx context.Context, url string, size int64) error {
|
||||
remoteFile := remotefile.NewRemoteFile(ctx, url, d.getPath(), false, "", -1, nil, "", "")
|
||||
if remoteFile.Fetch() {
|
||||
if options.HostOptions.EnableFallocateDisk {
|
||||
@@ -267,28 +271,12 @@ func (d *SLocalDisk) CreateRaw(ctx context.Context, sizeMB int, diskFormat, fsFo
|
||||
}
|
||||
|
||||
if utils.IsInStringArray(fsFormat, []string{"swap", "ext2", "ext3", "ext4", "xfs"}) {
|
||||
d.FormatFs(fsFormat, uuid)
|
||||
d.FormatFs(fsFormat, uuid, d.GetPath())
|
||||
}
|
||||
|
||||
return d.GetDiskDesc(), nil
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) FormatFs(fsFormat, uuid string) {
|
||||
log.Infof("Make disk %s fs %s", uuid, fsFormat)
|
||||
gd := NewKVMGuestDisk(d.GetPath())
|
||||
defer gd.Disconnect()
|
||||
if gd.Connect() {
|
||||
if err := gd.MakePartition(fsFormat); err == nil {
|
||||
err = gd.FormatPartition(fsFormat, uuid)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
} else {
|
||||
log.Errorln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) GetDiskDesc() jsonutils.JSONObject {
|
||||
qemuImg, err := qemuimg.NewQemuImage(d.getPath())
|
||||
if err != nil {
|
||||
|
||||
@@ -16,10 +16,15 @@ package storageman
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/util/qemuimg"
|
||||
)
|
||||
|
||||
type SNasDisk struct {
|
||||
@@ -46,6 +51,41 @@ func (d *SNasDisk) CreateFromTemplate(ctx context.Context, imageId, format strin
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (d *SNasDisk) CreateFromImageFuse(ctx context.Context, url string, size int64) error {
|
||||
return fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (d *SNasDisk) CreateFromSnapshotLocation(ctx context.Context, snapshotLocation string, size int64) error {
|
||||
snapshotPath := path.Join(d.Storage.GetPath(), snapshotLocation)
|
||||
newImg, err := qemuimg.NewQemuImage(d.GetPath())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "new image from snapshot")
|
||||
}
|
||||
if newImg.IsValid() {
|
||||
if err := newImg.Delete(); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = newImg.CreateQcow2(0, false, snapshotPath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "create image from snapshot")
|
||||
}
|
||||
retSize, _ := d.GetDiskDesc().Int("disk_size")
|
||||
log.Infof("REQSIZE: %d, RETSIZE: %d", size, retSize)
|
||||
if size > retSize {
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("size", jsonutils.NewInt(size))
|
||||
_, err = d.Resize(ctx, params)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *SNasDisk) GetSnapshotLocation() string {
|
||||
return d.GetSnapshotDir()[len(d.Storage.GetPath())+1:]
|
||||
}
|
||||
|
||||
type SNFSDisk struct {
|
||||
SNasDisk
|
||||
}
|
||||
|
||||
@@ -147,10 +147,6 @@ func (d *SRBDDisk) PrepareMigrate(liveMigrate bool) (string, error) {
|
||||
return "", fmt.Errorf("Not support")
|
||||
}
|
||||
|
||||
func (d *SRBDDisk) CreateFromUrl(context.Context, string) error {
|
||||
return fmt.Errorf("Not impl")
|
||||
}
|
||||
|
||||
func (d *SRBDDisk) CreateFromTemplate(ctx context.Context, imageId string, format string, size int64) (jsonutils.JSONObject, error) {
|
||||
ret, err := d.createFromTemplate(ctx, imageId, format)
|
||||
if err != nil {
|
||||
@@ -186,7 +182,7 @@ func (d *SRBDDisk) createFromTemplate(ctx context.Context, imageId, format strin
|
||||
return d.GetDiskDesc(), nil
|
||||
}
|
||||
|
||||
func (d *SRBDDisk) CreateFromImageFuse(context.Context, string) error {
|
||||
func (d *SRBDDisk) CreateFromImageFuse(ctx context.Context, url string, size int64) error {
|
||||
return fmt.Errorf("Not support")
|
||||
}
|
||||
|
||||
@@ -198,28 +194,12 @@ func (d *SRBDDisk) CreateRaw(ctx context.Context, sizeMb int, diskFromat string,
|
||||
}
|
||||
|
||||
if utils.IsInStringArray(fsFormat, []string{"swap", "ext2", "ext3", "ext4", "xfs"}) {
|
||||
d.FormatFs(fsFormat, diskId)
|
||||
d.FormatFs(fsFormat, diskId, d.GetPath())
|
||||
}
|
||||
|
||||
return d.GetDiskDesc(), nil
|
||||
}
|
||||
|
||||
func (d *SRBDDisk) FormatFs(fsFormat, uuid string) {
|
||||
log.Infof("Make disk %s fs %s", uuid, fsFormat)
|
||||
gd := NewKVMGuestDisk(d.GetPath())
|
||||
defer gd.Disconnect()
|
||||
if gd.Connect() {
|
||||
if err := gd.MakePartition(fsFormat); err == nil {
|
||||
err = gd.FormatPartition(fsFormat, uuid)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
} else {
|
||||
log.Errorln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *SRBDDisk) PostCreateFromImageFuse() {
|
||||
log.Errorf("Not support PostCreateFromImageFuse")
|
||||
}
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package diskhandlers // import "yunion.io/x/onecloud/pkg/hostman/diskhandlers"
|
||||
package diskhandlers // import "yunion.io/x/onecloud/pkg/hostman/storageman/diskhandlers"
|
||||
@@ -17,21 +17,37 @@ package storageman
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/cronman"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
"yunion.io/x/onecloud/pkg/util/qemuimg"
|
||||
)
|
||||
|
||||
const (
|
||||
_RECYCLE_BIN_ = "recycle_bin"
|
||||
_IMGSAVE_BACKUPS_ = "imgsave_backups"
|
||||
_SNAPSHOT_PATH_ = "snapshots"
|
||||
)
|
||||
|
||||
var DELETEING_SNAPSHOTS = sync.Map{}
|
||||
|
||||
type IStorageFactory interface {
|
||||
NewStorage(manager *SStorageManager, mountPoint string) IStorage
|
||||
StorageType() string
|
||||
@@ -275,30 +291,167 @@ func (s *SBaseStorage) CreateDiskFromSnpashot(ctx context.Context, disk IDisk, c
|
||||
// diskPath = path.Join(s.Path, createParams.DiskId)
|
||||
snapshotUrl, _ = createParams.DiskInfo.GetString("snapshot_url")
|
||||
transferProtocol, _ = createParams.DiskInfo.GetString("protocol")
|
||||
diskSize, _ = createParams.DiskInfo.Int("size")
|
||||
)
|
||||
|
||||
if len(snapshotUrl) == 0 || len(transferProtocol) == 0 {
|
||||
return nil, fmt.Errorf("Create disk from snapshot missing params snapshot url or protocol")
|
||||
}
|
||||
|
||||
if transferProtocol == "url" {
|
||||
// TODO
|
||||
// snapshotOutOfChain := jsonutils.QueryBoolean(
|
||||
// createParams.DiskInfo, "snapshot_out_of_chain", false)
|
||||
// // you wen ti...
|
||||
// if err := s.CreateDiskFromUrl(ctx, snapshotUrl, diskPath, !snapshotOutOfChain); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
} else if transferProtocol == "fuse" {
|
||||
if err := disk.CreateFromImageFuse(ctx, snapshotUrl); err != nil {
|
||||
return nil, err
|
||||
if createParams.Storage.StorageType() == compute.STORAGE_LOCAL {
|
||||
if transferProtocol == "url" {
|
||||
// not implement
|
||||
} else if transferProtocol == "fuse" {
|
||||
if err := disk.CreateFromImageFuse(ctx, snapshotUrl, diskSize); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("Unkown protocol %s", transferProtocol)
|
||||
}
|
||||
} else if utils.IsInStringArray(createParams.Storage.StorageType(), compute.SHARED_FILE_STORAGE) {
|
||||
if transferProtocol == "location" {
|
||||
if err := disk.CreateFromSnapshotLocation(ctx, snapshotUrl, diskSize); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("Unkown protocol %s", transferProtocol)
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("Unkown protocol %s", transferProtocol)
|
||||
}
|
||||
|
||||
return disk.GetDiskDesc(), nil
|
||||
}
|
||||
|
||||
func (s *SBaseStorage) DestinationPrepareMigrate(ctx context.Context, liveMigrate bool, disksUri string, snapshotsUri string, desc, disksBackingFile, srcSnapshots jsonutils.JSONObject) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
/*************************Background delete snapshot job****************************/
|
||||
|
||||
func StartSnapshotRecycle(storage IStorage) {
|
||||
log.Infof("Snapshot recyle job started")
|
||||
if !fileutils2.Exists(storage.GetSnapshotDir()) {
|
||||
procutils.NewCommand("mkdir", "-p", storage.GetSnapshotDir()).Run()
|
||||
}
|
||||
cronman.GetCronJobManager(false).AddJob1(
|
||||
"SnapshotRecycle", time.Hour*6,
|
||||
func(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
snapshotRecycle(ctx, userCred, isStart, storage)
|
||||
})
|
||||
}
|
||||
|
||||
func snapshotRecycle(ctx context.Context, userCred mcclient.TokenCredential, isStart bool, storage IStorage) {
|
||||
log.Infof("Snapshot Recycle Job Start, storage is %s, ss dir is %s", storage.GetStorageName(), storage.GetSnapshotDir())
|
||||
res, err := modules.Snapshots.GetById(hostutils.GetComputeSession(ctx), "max-count", nil)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
maxSnapshotCount, err := res.Int("max_count")
|
||||
if err != nil {
|
||||
log.Errorln("Request region get snapshot max count failed")
|
||||
return
|
||||
}
|
||||
files, err := ioutil.ReadDir(storage.GetSnapshotDir())
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
for _, file := range files {
|
||||
checkSnapshots(storage, file.Name(), int(maxSnapshotCount))
|
||||
}
|
||||
}
|
||||
|
||||
func checkSnapshots(storage IStorage, snapshotDir string, maxSnapshotCount int) {
|
||||
re := regexp.MustCompile(`^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}_snap$`)
|
||||
if !re.MatchString(snapshotDir) {
|
||||
log.Warningf("snapshot_dir got unexcept file %s", snapshotDir)
|
||||
return
|
||||
}
|
||||
diskId := snapshotDir[:len(snapshotDir)-len(options.HostOptions.SnapshotDirSuffix)]
|
||||
snapshotPath := path.Join(storage.GetSnapshotDir(), snapshotDir)
|
||||
|
||||
// If disk is Deleted, request delete this disk all snapshots
|
||||
if !fileutils2.Exists(path.Join(storage.GetPath(), diskId)) && fileutils2.Exists(snapshotPath) {
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("disk_id", jsonutils.NewString(diskId))
|
||||
_, err := modules.Snapshots.PerformClassAction(
|
||||
hostutils.GetComputeSession(context.Background()),
|
||||
"delete-disk-snapshots", params)
|
||||
if err != nil {
|
||||
log.Infof("Request delele disk %s snapshots failed %s", diskId, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
snapshots, err := ioutil.ReadDir(snapshotPath)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
|
||||
// if snapshot count greater than maxsnapshot count, do convert
|
||||
if len(snapshots) >= maxSnapshotCount {
|
||||
requestConvertSnapshot(snapshotPath, diskId)
|
||||
}
|
||||
}
|
||||
|
||||
func requestConvertSnapshot(snapshotPath, diskId string) {
|
||||
log.Infof("SNPASHOT path %s", snapshotPath)
|
||||
res, err := modules.Disks.GetSpecific(
|
||||
hostutils.GetComputeSession(context.Background()), diskId, "convert-snapshot", nil)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
deleteSnapshot, _ = res.GetString("delete_snapshot")
|
||||
convertSnapshot, _ = res.GetString("convert_snapshot")
|
||||
pendingDelete, _ = res.Bool("pending_delete")
|
||||
)
|
||||
log.Infof("start convert disk(%s) snapshot(%s), delete_snapshot is %s",
|
||||
diskId, convertSnapshot, deleteSnapshot)
|
||||
convertSnapshotPath := path.Join(snapshotPath, convertSnapshot)
|
||||
outfile := convertSnapshotPath + ".tmp"
|
||||
img, err := qemuimg.NewQemuImage(convertSnapshotPath)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
log.Infof("convertSnapshot path %s", convertSnapshotPath)
|
||||
err = img.Convert2Qcow2To(outfile, true)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
requestDeleteSnapshot(
|
||||
diskId, snapshotPath, deleteSnapshot, convertSnapshotPath, outfile, pendingDelete)
|
||||
}
|
||||
|
||||
func requestDeleteSnapshot(
|
||||
diskId, snapshotPath, deleteSnapshot, convertSnapshotPath,
|
||||
outfile string, pendingDelete bool,
|
||||
) {
|
||||
deleteSnapshotPath := path.Join(snapshotPath, deleteSnapshot)
|
||||
DELETEING_SNAPSHOTS.Store(diskId, true)
|
||||
defer DELETEING_SNAPSHOTS.Delete(diskId)
|
||||
_, err := modules.Snapshots.PerformAction(hostutils.GetComputeSession(context.Background()),
|
||||
deleteSnapshot, "deleted", nil)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
if out, err := procutils.NewCommand("rm", "-f", convertSnapshotPath).Run(); err != nil {
|
||||
log.Errorf("%s", out)
|
||||
return
|
||||
}
|
||||
if out, err := procutils.NewCommand("mv", "-f", outfile, convertSnapshotPath).Run(); err != nil {
|
||||
log.Errorf("%s", out)
|
||||
return
|
||||
}
|
||||
if !pendingDelete {
|
||||
if out, err := procutils.NewCommand("rm", "-f", deleteSnapshotPath).Run(); err != nil {
|
||||
log.Errorf("%s", out)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,5 +48,6 @@ func (s *SGPFSStorage) StorageType() string {
|
||||
func NewGPFSStorage(manager *SStorageManager, path string) *SGPFSStorage {
|
||||
ret := &SGPFSStorage{}
|
||||
ret.SNasStorage = *NewNasStorage(manager, path, ret)
|
||||
StartSnapshotRecycle(ret)
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -17,10 +17,8 @@ package storageman
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -28,12 +26,11 @@ import (
|
||||
"yunion.io/x/pkg/util/timeutils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/cronman"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman/remotefile"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
@@ -41,10 +38,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
_FUSE_MOUNT_PATH_ = "fusemnt"
|
||||
_FUSE_TMP_PATH_ = "fusetmp"
|
||||
_SNAPSHOT_PATH_ = "snapshots"
|
||||
DELETEING_SNAPSHOTS = map[string]bool{}
|
||||
_FUSE_MOUNT_PATH_ = "fusemnt"
|
||||
_FUSE_TMP_PATH_ = "fusetmp"
|
||||
)
|
||||
|
||||
type SLocalStorage struct {
|
||||
@@ -229,38 +224,9 @@ func (s *SLocalStorage) SaveToGlance(ctx context.Context, params interface{}) (j
|
||||
|
||||
func (s *SLocalStorage) saveToGlance(ctx context.Context, imageId, imagePath string,
|
||||
compress bool, format string) error {
|
||||
var (
|
||||
kvmDisk = NewKVMGuestDisk(imagePath)
|
||||
osInfo string
|
||||
relInfo *fsdriver.SReleaseInfo
|
||||
)
|
||||
|
||||
if err := func() error {
|
||||
defer kvmDisk.Disconnect()
|
||||
if kvmDisk.Connect() {
|
||||
var err error
|
||||
func() {
|
||||
if root := kvmDisk.MountKvmRootfs(); root != nil {
|
||||
defer kvmDisk.UmountKvmRootfs(root)
|
||||
|
||||
osInfo = root.GetOs()
|
||||
relInfo = root.GetReleaseInfo(root.GetPartition())
|
||||
if compress {
|
||||
err = root.PrepareFsForTemplate(root.GetPartition())
|
||||
}
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if compress {
|
||||
kvmDisk.Zerofree()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
ret, err := deployclient.GetDeployClient().SaveToGlance(context.Background(),
|
||||
&deployapi.SaveToGlanceParams{DiskPath: imagePath, Compress: compress})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -298,9 +264,10 @@ func (s *SLocalStorage) saveToGlance(ctx context.Context, imageId, imagePath str
|
||||
size := finfo.Size()
|
||||
|
||||
var params = jsonutils.NewDict()
|
||||
if len(osInfo) > 0 {
|
||||
params.Set("os_type", jsonutils.NewString(osInfo))
|
||||
if len(ret.OsInfo) > 0 {
|
||||
params.Set("os_type", jsonutils.NewString(ret.OsInfo))
|
||||
}
|
||||
relInfo := ret.ReleaseInfo
|
||||
if relInfo != nil {
|
||||
params.Set("os_distribution", jsonutils.NewString(relInfo.Distro))
|
||||
if len(relInfo.Version) > 0 {
|
||||
@@ -317,8 +284,6 @@ func (s *SLocalStorage) saveToGlance(ctx context.Context, imageId, imagePath str
|
||||
|
||||
_, err = modules.Images.Upload(hostutils.GetImageSession(ctx, s.GetZone()),
|
||||
params, f, size)
|
||||
// TODO
|
||||
// notify_template_ready
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -357,132 +322,6 @@ func (s *SLocalStorage) DeleteSnapshots(ctx context.Context, params interface{})
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
/*************************Background delete snapshot job****************************/
|
||||
|
||||
func (s *SLocalStorage) StartSnapshotRecycle() {
|
||||
log.Infof("Snapshot recyle job started")
|
||||
if !fileutils2.Exists(s.GetSnapshotDir()) {
|
||||
procutils.NewCommand("mkdir", "-p", s.GetSnapshotDir()).Run()
|
||||
}
|
||||
cronman.GetCronJobManager(false).AddJob2("SnapshotRecycle", options.HostOptions.SnapshotRecycleDay, 2, 0, 0, s.snapshotRecycle, true)
|
||||
}
|
||||
|
||||
func (s *SLocalStorage) snapshotRecycle(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
res, err := modules.Snapshots.GetById(hostutils.GetComputeSession(ctx), "max-count", nil)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
maxSnapshotCount, err := res.Int("max_count")
|
||||
if err != nil {
|
||||
log.Errorln("Request region get snapshot max count failed")
|
||||
return
|
||||
}
|
||||
files, err := ioutil.ReadDir(s.GetSnapshotDir())
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
for _, file := range files {
|
||||
s.checkSnapshots(file.Name(), int(maxSnapshotCount))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SLocalStorage) checkSnapshots(snapshotDir string, maxSnapshotCount int) {
|
||||
re := regexp.MustCompile(`^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}_snap$`)
|
||||
if !re.MatchString(snapshotDir) {
|
||||
log.Warningf("snapshot_dir got unexcept file %s", snapshotDir)
|
||||
return
|
||||
}
|
||||
|
||||
diskId := snapshotDir[:len(snapshotDir)-len(options.HostOptions.SnapshotDirSuffix)]
|
||||
snapshotPath := path.Join(s.GetSnapshotDir(), snapshotDir)
|
||||
|
||||
// If disk is Deleted, request delete this disk all snapshots
|
||||
if !fileutils2.Exists(path.Join(s.Path, diskId)) && fileutils2.Exists(snapshotPath) {
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("disk_id", jsonutils.NewString(diskId))
|
||||
_, err := modules.Snapshots.PerformClassAction(
|
||||
hostutils.GetComputeSession(context.Background()),
|
||||
"delete-disk-snapshots", params)
|
||||
if err != nil {
|
||||
log.Infof("Request delele disk %s snapshots failed %s", diskId, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
snapshots, err := ioutil.ReadDir(snapshotPath)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
|
||||
// if snapshot count greater than maxsnapshot count, do convert
|
||||
if len(snapshots) >= maxSnapshotCount {
|
||||
s.requestConvertSnapshot(snapshotPath, diskId)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SLocalStorage) requestConvertSnapshot(snapshotPath, diskId string) {
|
||||
res, err := modules.Disks.GetSpecific(
|
||||
hostutils.GetComputeSession(context.Background()), diskId, "convert-snapshot", nil)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
deleteSnapshot, _ = res.GetString("delete_snapshot")
|
||||
convertSnapshot, _ = res.GetString("convert_snapshot")
|
||||
pendingDelete, _ = res.Bool("pending_delete")
|
||||
)
|
||||
log.Infof("start convert disk(%s) snapshot(%s), delete_snapshot is %s",
|
||||
diskId, convertSnapshot, deleteSnapshot)
|
||||
convertSnapshotPath := path.Join(snapshotPath, convertSnapshot)
|
||||
outfile := convertSnapshotPath + ".tmp"
|
||||
img, err := qemuimg.NewQemuImage(convertSnapshot)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
err = img.Convert2Qcow2To(outfile, true)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
s.requestDeleteSnapshot(
|
||||
diskId, snapshotPath, deleteSnapshot, convertSnapshotPath, outfile, pendingDelete)
|
||||
}
|
||||
|
||||
func (s *SLocalStorage) requestDeleteSnapshot(
|
||||
diskId, snapshotPath, deleteSnapshot, convertSnapshotPath,
|
||||
outfile string, pendingDelete bool,
|
||||
) {
|
||||
deleteSnapshotPath := path.Join(snapshotPath, deleteSnapshot)
|
||||
DELETEING_SNAPSHOTS[diskId] = true
|
||||
defer delete(DELETEING_SNAPSHOTS, diskId)
|
||||
_, err := modules.Snapshots.PerformAction(hostutils.GetComputeSession(context.Background()),
|
||||
deleteSnapshot, "deleted", nil)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
if out, err := procutils.NewCommand("rm", "-f", convertSnapshotPath).Run(); err != nil {
|
||||
log.Errorf("%s", out)
|
||||
return
|
||||
}
|
||||
if out, err := procutils.NewCommand("mv", "-f", outfile, convertSnapshotPath).Run(); err != nil {
|
||||
log.Errorf("%s", out)
|
||||
return
|
||||
}
|
||||
if !pendingDelete {
|
||||
if out, err := procutils.NewCommand("rm", "-f", deleteSnapshotPath).Run(); err != nil {
|
||||
log.Errorf("%s", out)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SLocalStorage) DestinationPrepareMigrate(ctx context.Context, liveMigrate bool, disksUri string, snapshotsUri string, desc, disksBackingFile, srcSnapshots jsonutils.JSONObject) error {
|
||||
disks, _ := desc.GetArray("disks")
|
||||
for i, diskinfo := range disks {
|
||||
@@ -529,7 +368,7 @@ func (s *SLocalStorage) DestinationPrepareMigrate(ctx context.Context, liveMigra
|
||||
} else {
|
||||
// download disk form remote url
|
||||
diskUrl := fmt.Sprintf("%s/%s/%s", disksUri, diskStorageId, diskId)
|
||||
if err := disk.CreateFromUrl(ctx, diskUrl); err != nil {
|
||||
if err := disk.CreateFromUrl(ctx, diskUrl, 0); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package storageman
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -37,7 +38,16 @@ type SNasStorage struct {
|
||||
}
|
||||
|
||||
func NewNasStorage(manager *SStorageManager, path string, ins INasStorage) *SNasStorage {
|
||||
return &SNasStorage{*NewLocalStorage(manager, path, 0), ins}
|
||||
ret := &SNasStorage{*NewLocalStorage(manager, path, 0), ins}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *SNasStorage) GetComposedName() string {
|
||||
return fmt.Sprintf("host_%s_%s_storage_%d", s.Manager.host.GetMasterIp(), s.ins.StorageType(), s.Index)
|
||||
}
|
||||
|
||||
func (s *SNasStorage) GetSnapshotDir() string {
|
||||
return path.Join(s.Path, s.GetComposedName(), _SNAPSHOT_PATH_)
|
||||
}
|
||||
|
||||
func (s *SNasStorage) CreateDisk(diskId string) IDisk {
|
||||
|
||||
@@ -45,15 +45,16 @@ func (factory *SNFSStorageFactory) StorageType() string {
|
||||
}
|
||||
|
||||
type SNFSStorage struct {
|
||||
SLocalStorage
|
||||
SNasStorage
|
||||
}
|
||||
|
||||
func NewNFSStorage(manager *SStorageManager, path string) *SNFSStorage {
|
||||
ret := &SNFSStorage{}
|
||||
ret.SLocalStorage = *NewLocalStorage(manager, path, 0)
|
||||
ret.SNasStorage = *NewNasStorage(manager, path, ret)
|
||||
if !fileutils2.Exists(path) {
|
||||
procutils.NewCommand("mkdir", "-p", path).Run()
|
||||
}
|
||||
StartSnapshotRecycle(ret)
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ import (
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
@@ -476,34 +477,9 @@ func (s *SRbdStorage) onSaveToGlanceFailed(ctx context.Context, imageId string)
|
||||
}
|
||||
|
||||
func (s *SRbdStorage) saveToGlance(ctx context.Context, imageId, imagePath string, compress bool, format string) error {
|
||||
var (
|
||||
kvmDisk = NewKVMGuestDisk(imagePath)
|
||||
osInfo string
|
||||
relInfo *fsdriver.SReleaseInfo
|
||||
)
|
||||
|
||||
if err := func() error {
|
||||
defer kvmDisk.Disconnect()
|
||||
if kvmDisk.Connect() {
|
||||
if root := kvmDisk.MountKvmRootfs(); root != nil {
|
||||
defer kvmDisk.UmountKvmRootfs(root)
|
||||
|
||||
osInfo = root.GetOs()
|
||||
relInfo = root.GetReleaseInfo(root.GetPartition())
|
||||
if compress {
|
||||
if err := root.PrepareFsForTemplate(root.GetPartition()); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if compress {
|
||||
kvmDisk.Zerofree()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}(); err != nil {
|
||||
ret, err := deployclient.GetDeployClient().SaveToGlance(context.Background(),
|
||||
&deployapi.SaveToGlanceParams{DiskPath: imagePath, Compress: compress})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -512,7 +488,7 @@ func (s *SRbdStorage) saveToGlance(ctx context.Context, imageId, imagePath strin
|
||||
format = options.HostOptions.DefaultImageSaveFormat
|
||||
}
|
||||
|
||||
_, err := procutils.NewCommand(qemutils.GetQemuImg(), "convert", "-f", "raw", "-O", format, imagePath, tmpImageFile).Run()
|
||||
_, err = procutils.NewCommand(qemutils.GetQemuImg(), "convert", "-f", "raw", "-O", format, imagePath, tmpImageFile).Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -521,8 +497,8 @@ func (s *SRbdStorage) saveToGlance(ctx context.Context, imageId, imagePath strin
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer os.Remove(tmpImageFile)
|
||||
defer f.Close()
|
||||
|
||||
finfo, err := f.Stat()
|
||||
if err != nil {
|
||||
@@ -531,9 +507,10 @@ func (s *SRbdStorage) saveToGlance(ctx context.Context, imageId, imagePath strin
|
||||
size := finfo.Size()
|
||||
|
||||
var params = jsonutils.NewDict()
|
||||
if len(osInfo) > 0 {
|
||||
params.Set("os_type", jsonutils.NewString(osInfo))
|
||||
if len(ret.OsInfo) > 0 {
|
||||
params.Set("os_type", jsonutils.NewString(ret.OsInfo))
|
||||
}
|
||||
relInfo := ret.ReleaseInfo
|
||||
if relInfo != nil {
|
||||
params.Set("os_distribution", jsonutils.NewString(relInfo.Distro))
|
||||
if len(relInfo.Version) > 0 {
|
||||
@@ -550,9 +527,6 @@ func (s *SRbdStorage) saveToGlance(ctx context.Context, imageId, imagePath strin
|
||||
|
||||
_, err = modules.Images.Upload(hostutils.GetImageSession(ctx, s.GetZone()),
|
||||
params, f, size)
|
||||
f.Close()
|
||||
// TODO
|
||||
// notify_template_ready
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package storagehandler // import "yunion.io/x/onecloud/pkg/hostman/storageman/storagehandler"
|
||||
+10
-9
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package storageman
|
||||
package storagehandler
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
@@ -76,7 +77,7 @@ func storageAttach(ctx context.Context, body jsonutils.JSONObject) (interface{},
|
||||
}
|
||||
|
||||
storageType, _ := body.GetString("storage_type")
|
||||
storage := storageManager.NewSharedStorageInstance(mountPoint, storageType)
|
||||
storage := storageman.GetManager().NewSharedStorageInstance(mountPoint, storageType)
|
||||
if storage == nil {
|
||||
return nil, httperrors.NewBadRequestError("'Not Support Storage[%s] mount_point: %s", storageType, mountPoint)
|
||||
}
|
||||
@@ -92,8 +93,8 @@ func storageAttach(ctx context.Context, body jsonutils.JSONObject) (interface{},
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storageManager.InitSharedStorageImageCache(storageType, storagecacheId, imagecachePath, storage)
|
||||
storageManager.Storages = append(storageManager.Storages, storage)
|
||||
storageman.GetManager().InitSharedStorageImageCache(storageType, storagecacheId, imagecachePath, storage)
|
||||
storageman.GetManager().Storages = append(storageman.GetManager().Storages, storage)
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -102,13 +103,13 @@ func storageDetach(ctx context.Context, body jsonutils.JSONObject) (interface{},
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("mount_point")
|
||||
}
|
||||
storage := storageManager.GetStorageByPath(mountPoint)
|
||||
storage := storageman.GetManager().GetStorageByPath(mountPoint)
|
||||
|
||||
name, _ := body.GetString("name")
|
||||
if storage == nil {
|
||||
return nil, httperrors.NewBadRequestError("ShareStorage[%s] Has detach from host ...", name)
|
||||
}
|
||||
storageManager.Remove(storage)
|
||||
storageman.GetManager().Remove(storage)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -121,11 +122,11 @@ func storageUpdate(ctx context.Context, body jsonutils.JSONObject) (interface{},
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("storage_conf")
|
||||
}
|
||||
storage := storageManager.GetStorage(storageId)
|
||||
storage := storageman.GetManager().GetStorage(storageId)
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("details", jsonutils.JSONTrue)
|
||||
ret, err := modules.Hoststorages.Get(hostutils.GetComputeSession(context.Background()),
|
||||
storageManager.GetHostId(), storageId, params)
|
||||
storageman.GetManager().GetHostId(), storageId, params)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
@@ -143,7 +144,7 @@ func storageUpdate(ctx context.Context, body jsonutils.JSONObject) (interface{},
|
||||
func storageDeleteSnapshots(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||
params, _, body := appsrv.FetchEnv(ctx, w, r)
|
||||
var storageId = params["<storageId>"]
|
||||
storage := storageManager.GetStorage(storageId)
|
||||
storage := storageman.GetManager().GetStorage(storageId)
|
||||
if storage == nil {
|
||||
hostutils.Response(ctx, w, httperrors.NewNotFoundError("Stroage Not found"))
|
||||
return
|
||||
@@ -0,0 +1,17 @@
|
||||
package system_service
|
||||
|
||||
type SHostDeployer struct {
|
||||
*SBaseSystemService
|
||||
}
|
||||
|
||||
func NewHostDeployerService() *SHostDeployer {
|
||||
return &SHostDeployer{NewBaseSystemService("yunion-host-deployer", nil)}
|
||||
}
|
||||
|
||||
func (s *SHostDeployer) Reload(kwargs map[string]interface{}) error {
|
||||
return s.reload(s.GetConfig(kwargs), s.GetConfigFile())
|
||||
}
|
||||
|
||||
func (s *SHostDeployer) BgReload(kwargs map[string]interface{}) {
|
||||
go s.reload(s.GetConfig(kwargs), s.GetConfigFile())
|
||||
}
|
||||
@@ -45,6 +45,7 @@ var serviceMap = map[string]ISystemService{
|
||||
"kube_agent": NewKubeAgentService(),
|
||||
"lxcfs": NewLxcfsService(),
|
||||
"docker": NewDockerService(),
|
||||
"host-deployer": NewHostDeployerService(),
|
||||
}
|
||||
|
||||
func GetService(name string) ISystemService {
|
||||
|
||||
@@ -38,7 +38,8 @@ type SImageOptions struct {
|
||||
|
||||
TargetImageFormats []string `help:"target image formats that the system will automatically convert to" default:"qcow2,vmdk,vhd"`
|
||||
|
||||
TorrentClientPath string `help:"path to torrent executable" default:"/opt/yunion/bin/torrent"`
|
||||
TorrentClientPath string `help:"path to torrent executable" default:"/opt/yunion/bin/torrent"`
|
||||
DeployServerSocketPath string `help:"Deploy server listen socket path"`
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/cronman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman/nbd"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient"
|
||||
"yunion.io/x/onecloud/pkg/image/models"
|
||||
"yunion.io/x/onecloud/pkg/image/options"
|
||||
_ "yunion.io/x/onecloud/pkg/image/tasks"
|
||||
@@ -104,7 +104,9 @@ func StartService() {
|
||||
|
||||
go models.CheckImages()
|
||||
|
||||
nbd.Init() // init nbd module for image probe
|
||||
if len(options.Options.DeployServerSocketPath) > 0 {
|
||||
deployclient.Init(options.Options.DeployServerSocketPath)
|
||||
}
|
||||
|
||||
if !opts.IsSlaveNode {
|
||||
cron := cronman.GetCronJobManager(true)
|
||||
|
||||
@@ -25,8 +25,8 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/image"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient"
|
||||
"yunion.io/x/onecloud/pkg/image/models"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
@@ -48,6 +48,7 @@ func (self *ImageProbeTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
|
||||
func (self *ImageProbeTask) StartImageProbe(ctx context.Context, image *models.SImage) {
|
||||
probeErr := self.doProbe(ctx, image)
|
||||
|
||||
// save chksum first
|
||||
// if failed, set image unavailable, because size and chksum changed
|
||||
if err := self.updateImageMetadata(ctx, image); err != nil {
|
||||
image.SetStatus(self.UserCred, api.IMAGE_STATUS_KILLED,
|
||||
@@ -65,20 +66,13 @@ func (self *ImageProbeTask) StartImageProbe(ctx context.Context, image *models.S
|
||||
|
||||
func (self *ImageProbeTask) doProbe(ctx context.Context, image *models.SImage) error {
|
||||
diskPath := image.GetPath("")
|
||||
kvmDisk := storageman.NewKVMGuestDisk(diskPath)
|
||||
defer kvmDisk.DisconnectWithoutLvm()
|
||||
if !kvmDisk.ConnectWithoutDetectLvm() {
|
||||
return fmt.Errorf("Disk connector failed to connect image")
|
||||
if deployclient.GetDeployClient() == nil {
|
||||
return fmt.Errorf("deploy client not init")
|
||||
}
|
||||
|
||||
// Fsck is executed during mount
|
||||
rootfs := kvmDisk.MountKvmRootfs()
|
||||
if rootfs == nil {
|
||||
return fmt.Errorf("Failed mounting rootfs for kvm disk")
|
||||
imageInfo, err := deployclient.GetDeployClient().ProbeImageInfo(ctx, &deployapi.ProbeImageInfoPramas{DiskPath: diskPath})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer kvmDisk.UmountKvmRootfs(rootfs)
|
||||
|
||||
imageInfo := self.getImageInfo(kvmDisk, rootfs)
|
||||
self.updateImageInfo(ctx, image, imageInfo)
|
||||
return nil
|
||||
}
|
||||
@@ -120,15 +114,15 @@ func (self *ImageProbeTask) updateImageMetadata(
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ImageProbeTask) updateImageInfo(ctx context.Context, image *models.SImage, imageInfo *sImageInfo) {
|
||||
imageProperties := jsonutils.Marshal(imageInfo.osInfo).(*jsonutils.JSONDict)
|
||||
func (self *ImageProbeTask) updateImageInfo(ctx context.Context, image *models.SImage, imageInfo *deployapi.ImageInfo) {
|
||||
imageProperties := jsonutils.Marshal(imageInfo.OsInfo).(*jsonutils.JSONDict)
|
||||
if len(imageInfo.OsType) > 0 {
|
||||
imageProperties.Set(api.IMAGE_OS_TYPE, jsonutils.NewString(imageInfo.OsType))
|
||||
}
|
||||
if imageInfo.IsUEFISupport {
|
||||
if imageInfo.IsUefiSupport {
|
||||
imageProperties.Set(api.IMAGE_UEFI_SUPPORT, jsonutils.JSONTrue)
|
||||
}
|
||||
if imageInfo.IsLVMPartition {
|
||||
if imageInfo.IsLvmPartition {
|
||||
imageProperties.Set(api.IMAGE_IS_LVM_PARTITION, jsonutils.JSONTrue)
|
||||
}
|
||||
if imageInfo.IsReadonly {
|
||||
@@ -145,7 +139,7 @@ func (self *ImageProbeTask) updateImageInfo(ctx context.Context, image *models.S
|
||||
}
|
||||
|
||||
type sImageInfo struct {
|
||||
osInfo *fsdriver.SReleaseInfo
|
||||
osInfo *deployapi.ReleaseInfo
|
||||
|
||||
OsType string
|
||||
IsUEFISupport bool
|
||||
@@ -155,19 +149,6 @@ type sImageInfo struct {
|
||||
IsInstalledCloudInit bool
|
||||
}
|
||||
|
||||
func (self *ImageProbeTask) getImageInfo(kvmDisk *storageman.SKVMGuestDisk, rootfs fsdriver.IRootFsDriver) *sImageInfo {
|
||||
partition := rootfs.GetPartition()
|
||||
return &sImageInfo{
|
||||
osInfo: rootfs.GetReleaseInfo(partition),
|
||||
OsType: rootfs.GetOs(),
|
||||
IsUEFISupport: kvmDisk.DetectIsUEFISupport(rootfs),
|
||||
// IsLVMPartition: kvmDisk.IsLVMPartition(),
|
||||
IsReadonly: partition.IsReadonly(),
|
||||
PhysicalPartitionType: partition.GetPhysicalPartitionType(),
|
||||
IsInstalledCloudInit: rootfs.IsCloudinitInstall(),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *ImageProbeTask) OnProbeFailed(ctx context.Context, image *models.SImage, reason string) {
|
||||
log.Infof("Image %s Probe Failed: %s", image.Name, reason)
|
||||
db.OpsLog.LogEvent(image, db.ACT_PROBE_FAIL, reason, self.UserCred)
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
"yunion.io/x/onecloud/pkg/util/regutils2"
|
||||
)
|
||||
@@ -78,6 +79,28 @@ func GetPrivatePrefixes(privatePrefixes []string) []string {
|
||||
}
|
||||
}
|
||||
|
||||
func GetMainNicFromDeployApi(nics []*deployapi.Nic) (*deployapi.Nic, error) {
|
||||
var mainIp netutils.IPV4Addr
|
||||
var mainNic *deployapi.Nic
|
||||
for _, n := range nics {
|
||||
if len(n.Gateway) > 0 {
|
||||
ip := n.Ip
|
||||
ipInt, err := netutils.NewIPV4Addr(ip)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if mainIp == 0 {
|
||||
mainIp = ipInt
|
||||
mainNic = n
|
||||
} else if !netutils.IsPrivate(ipInt) && netutils.IsPrivate(mainIp) {
|
||||
mainIp = ipInt
|
||||
mainNic = n
|
||||
}
|
||||
}
|
||||
}
|
||||
return mainNic, nil
|
||||
}
|
||||
|
||||
func GetMainNic(nics []jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
var mainIp netutils.IPV4Addr
|
||||
var mainNic jsonutils.JSONObject
|
||||
@@ -136,9 +159,9 @@ func addRoute(routes *[][]string, net, gw string) {
|
||||
*routes = append(*routes, []string{net, gw})
|
||||
}
|
||||
|
||||
func extendRoutes(routes *[][]string, nicRoutes []types.SRoute) error {
|
||||
func extendRoutes(routes *[][]string, nicRoutes []*deployapi.Routes) error {
|
||||
for i := 0; i < len(nicRoutes); i++ {
|
||||
addRoute(routes, nicRoutes[i][0], nicRoutes[i][1])
|
||||
addRoute(routes, nicRoutes[i].Route[0], nicRoutes[i].Route[1])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package sysutils
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
@@ -191,3 +192,21 @@ func IsKernelModuleLoaded(name string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func SetSysConfig(cpath, val string) bool {
|
||||
if fileutils2.Exists(cpath) {
|
||||
oval, err := ioutil.ReadFile(cpath)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return false
|
||||
}
|
||||
if string(oval) != val {
|
||||
err = fileutils2.FilePutContents(cpath, val, false)
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
log.Errorln(err)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
-1
@@ -186,7 +186,6 @@ func (p *Buffer) DecodeVarint() (x uint64, err error) {
|
||||
if b&0x80 == 0 {
|
||||
goto done
|
||||
}
|
||||
// x -= 0x80 << 63 // Always zero.
|
||||
|
||||
return 0, errOverflow
|
||||
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto
|
||||
|
||||
import "errors"
|
||||
|
||||
// Deprecated: do not use.
|
||||
type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 }
|
||||
|
||||
// Deprecated: do not use.
|
||||
func GetStats() Stats { return Stats{} }
|
||||
|
||||
// Deprecated: do not use.
|
||||
func MarshalMessageSet(interface{}) ([]byte, error) {
|
||||
return nil, errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: do not use.
|
||||
func UnmarshalMessageSet([]byte, interface{}) error {
|
||||
return errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: do not use.
|
||||
func MarshalMessageSetJSON(interface{}) ([]byte, error) {
|
||||
return nil, errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: do not use.
|
||||
func UnmarshalMessageSetJSON([]byte, interface{}) error {
|
||||
return errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: do not use.
|
||||
func RegisterMessageSetType(Message, int32, string) {}
|
||||
+2
-1
@@ -246,7 +246,8 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
m1, m2 := e1.value, e2.value
|
||||
m1 := extensionAsLegacyType(e1.value)
|
||||
m2 := extensionAsLegacyType(e2.value)
|
||||
|
||||
if m1 == nil && m2 == nil {
|
||||
// Both have only encoded form.
|
||||
|
||||
+71
-7
@@ -185,9 +185,25 @@ type Extension struct {
|
||||
// extension will have only enc set. When such an extension is
|
||||
// accessed using GetExtension (or GetExtensions) desc and value
|
||||
// will be set.
|
||||
desc *ExtensionDesc
|
||||
desc *ExtensionDesc
|
||||
|
||||
// value is a concrete value for the extension field. Let the type of
|
||||
// desc.ExtensionType be the "API type" and the type of Extension.value
|
||||
// be the "storage type". The API type and storage type are the same except:
|
||||
// * For scalars (except []byte), the API type uses *T,
|
||||
// while the storage type uses T.
|
||||
// * For repeated fields, the API type uses []T, while the storage type
|
||||
// uses *[]T.
|
||||
//
|
||||
// The reason for the divergence is so that the storage type more naturally
|
||||
// matches what is expected of when retrieving the values through the
|
||||
// protobuf reflection APIs.
|
||||
//
|
||||
// The value may only be populated if desc is also populated.
|
||||
value interface{}
|
||||
enc []byte
|
||||
|
||||
// enc is the raw bytes for the extension field.
|
||||
enc []byte
|
||||
}
|
||||
|
||||
// SetRawExtension is for testing only.
|
||||
@@ -334,7 +350,7 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
|
||||
// descriptors with the same field number.
|
||||
return nil, errors.New("proto: descriptor conflict")
|
||||
}
|
||||
return e.value, nil
|
||||
return extensionAsLegacyType(e.value), nil
|
||||
}
|
||||
|
||||
if extension.ExtensionType == nil {
|
||||
@@ -349,11 +365,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
|
||||
|
||||
// Remember the decoded version and drop the encoded version.
|
||||
// That way it is safe to mutate what we return.
|
||||
e.value = v
|
||||
e.value = extensionAsStorageType(v)
|
||||
e.desc = extension
|
||||
e.enc = nil
|
||||
emap[extension.Field] = e
|
||||
return e.value, nil
|
||||
return extensionAsLegacyType(e.value), nil
|
||||
}
|
||||
|
||||
// defaultExtensionValue returns the default value for extension.
|
||||
@@ -488,7 +504,7 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
|
||||
}
|
||||
typ := reflect.TypeOf(extension.ExtensionType)
|
||||
if typ != reflect.TypeOf(value) {
|
||||
return errors.New("proto: bad extension value type")
|
||||
return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType)
|
||||
}
|
||||
// nil extension values need to be caught early, because the
|
||||
// encoder can't distinguish an ErrNil due to a nil extension
|
||||
@@ -500,7 +516,7 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
|
||||
}
|
||||
|
||||
extmap := epb.extensionsWrite()
|
||||
extmap[extension.Field] = Extension{desc: extension, value: value}
|
||||
extmap[extension.Field] = Extension{desc: extension, value: extensionAsStorageType(value)}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -541,3 +557,51 @@ func RegisterExtension(desc *ExtensionDesc) {
|
||||
func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
|
||||
return extensionMaps[reflect.TypeOf(pb).Elem()]
|
||||
}
|
||||
|
||||
// extensionAsLegacyType converts an value in the storage type as the API type.
|
||||
// See Extension.value.
|
||||
func extensionAsLegacyType(v interface{}) interface{} {
|
||||
switch rv := reflect.ValueOf(v); rv.Kind() {
|
||||
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
|
||||
// Represent primitive types as a pointer to the value.
|
||||
rv2 := reflect.New(rv.Type())
|
||||
rv2.Elem().Set(rv)
|
||||
v = rv2.Interface()
|
||||
case reflect.Ptr:
|
||||
// Represent slice types as the value itself.
|
||||
switch rv.Type().Elem().Kind() {
|
||||
case reflect.Slice:
|
||||
if rv.IsNil() {
|
||||
v = reflect.Zero(rv.Type().Elem()).Interface()
|
||||
} else {
|
||||
v = rv.Elem().Interface()
|
||||
}
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// extensionAsStorageType converts an value in the API type as the storage type.
|
||||
// See Extension.value.
|
||||
func extensionAsStorageType(v interface{}) interface{} {
|
||||
switch rv := reflect.ValueOf(v); rv.Kind() {
|
||||
case reflect.Ptr:
|
||||
// Represent slice types as the value itself.
|
||||
switch rv.Type().Elem().Kind() {
|
||||
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
|
||||
if rv.IsNil() {
|
||||
v = reflect.Zero(rv.Type().Elem()).Interface()
|
||||
} else {
|
||||
v = rv.Elem().Interface()
|
||||
}
|
||||
}
|
||||
case reflect.Slice:
|
||||
// Represent slice types as a pointer to the value.
|
||||
if rv.Type().Elem().Kind() != reflect.Uint8 {
|
||||
rv2 := reflect.New(rv.Type())
|
||||
rv2.Elem().Set(rv)
|
||||
v = rv2.Interface()
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
+12
-26
@@ -341,26 +341,6 @@ type Message interface {
|
||||
ProtoMessage()
|
||||
}
|
||||
|
||||
// Stats records allocation details about the protocol buffer encoders
|
||||
// and decoders. Useful for tuning the library itself.
|
||||
type Stats struct {
|
||||
Emalloc uint64 // mallocs in encode
|
||||
Dmalloc uint64 // mallocs in decode
|
||||
Encode uint64 // number of encodes
|
||||
Decode uint64 // number of decodes
|
||||
Chit uint64 // number of cache hits
|
||||
Cmiss uint64 // number of cache misses
|
||||
Size uint64 // number of sizes
|
||||
}
|
||||
|
||||
// Set to true to enable stats collection.
|
||||
const collectStats = false
|
||||
|
||||
var stats Stats
|
||||
|
||||
// GetStats returns a copy of the global Stats structure.
|
||||
func GetStats() Stats { return stats }
|
||||
|
||||
// A Buffer is a buffer manager for marshaling and unmarshaling
|
||||
// protocol buffers. It may be reused between invocations to
|
||||
// reduce memory usage. It is not necessary to use a Buffer;
|
||||
@@ -960,13 +940,19 @@ func isProto3Zero(v reflect.Value) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
const ProtoPackageIsVersion2 = true
|
||||
const (
|
||||
// ProtoPackageIsVersion3 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
ProtoPackageIsVersion3 = true
|
||||
|
||||
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
const ProtoPackageIsVersion1 = true
|
||||
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
ProtoPackageIsVersion2 = true
|
||||
|
||||
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
ProtoPackageIsVersion1 = true
|
||||
)
|
||||
|
||||
// InternalMessageInfo is a type used internally by generated .pb.go files.
|
||||
// This type is not intended to be used by non-generated code.
|
||||
|
||||
+2
-135
@@ -36,13 +36,7 @@ package proto
|
||||
*/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
|
||||
@@ -145,46 +139,9 @@ func skipVarint(buf []byte) []byte {
|
||||
return buf[i+1:]
|
||||
}
|
||||
|
||||
// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
|
||||
// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
|
||||
func MarshalMessageSet(exts interface{}) ([]byte, error) {
|
||||
return marshalMessageSet(exts, false)
|
||||
}
|
||||
|
||||
// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal.
|
||||
func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) {
|
||||
switch exts := exts.(type) {
|
||||
case *XXX_InternalExtensions:
|
||||
var u marshalInfo
|
||||
siz := u.sizeMessageSet(exts)
|
||||
b := make([]byte, 0, siz)
|
||||
return u.appendMessageSet(b, exts, deterministic)
|
||||
|
||||
case map[int32]Extension:
|
||||
// This is an old-style extension map.
|
||||
// Wrap it in a new-style XXX_InternalExtensions.
|
||||
ie := XXX_InternalExtensions{
|
||||
p: &struct {
|
||||
mu sync.Mutex
|
||||
extensionMap map[int32]Extension
|
||||
}{
|
||||
extensionMap: exts,
|
||||
},
|
||||
}
|
||||
|
||||
var u marshalInfo
|
||||
siz := u.sizeMessageSet(&ie)
|
||||
b := make([]byte, 0, siz)
|
||||
return u.appendMessageSet(b, &ie, deterministic)
|
||||
|
||||
default:
|
||||
return nil, errors.New("proto: not an extension map")
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
|
||||
// unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
|
||||
// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
|
||||
func UnmarshalMessageSet(buf []byte, exts interface{}) error {
|
||||
func unmarshalMessageSet(buf []byte, exts interface{}) error {
|
||||
var m map[int32]Extension
|
||||
switch exts := exts.(type) {
|
||||
case *XXX_InternalExtensions:
|
||||
@@ -222,93 +179,3 @@ func UnmarshalMessageSet(buf []byte, exts interface{}) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
|
||||
// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
|
||||
func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
|
||||
var m map[int32]Extension
|
||||
switch exts := exts.(type) {
|
||||
case *XXX_InternalExtensions:
|
||||
var mu sync.Locker
|
||||
m, mu = exts.extensionsRead()
|
||||
if m != nil {
|
||||
// Keep the extensions map locked until we're done marshaling to prevent
|
||||
// races between marshaling and unmarshaling the lazily-{en,de}coded
|
||||
// values.
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
}
|
||||
case map[int32]Extension:
|
||||
m = exts
|
||||
default:
|
||||
return nil, errors.New("proto: not an extension map")
|
||||
}
|
||||
var b bytes.Buffer
|
||||
b.WriteByte('{')
|
||||
|
||||
// Process the map in key order for deterministic output.
|
||||
ids := make([]int32, 0, len(m))
|
||||
for id := range m {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
|
||||
|
||||
for i, id := range ids {
|
||||
ext := m[id]
|
||||
msd, ok := messageSetMap[id]
|
||||
if !ok {
|
||||
// Unknown type; we can't render it, so skip it.
|
||||
continue
|
||||
}
|
||||
|
||||
if i > 0 && b.Len() > 1 {
|
||||
b.WriteByte(',')
|
||||
}
|
||||
|
||||
fmt.Fprintf(&b, `"[%s]":`, msd.name)
|
||||
|
||||
x := ext.value
|
||||
if x == nil {
|
||||
x = reflect.New(msd.t.Elem()).Interface()
|
||||
if err := Unmarshal(ext.enc, x.(Message)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
d, err := json.Marshal(x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.Write(d)
|
||||
}
|
||||
b.WriteByte('}')
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
|
||||
// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
|
||||
func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
|
||||
// Common-case fast path.
|
||||
if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// This is fairly tricky, and it's not clear that it is needed.
|
||||
return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
|
||||
}
|
||||
|
||||
// A global registry of types that can be used in a MessageSet.
|
||||
|
||||
var messageSetMap = make(map[int32]messageSetDesc)
|
||||
|
||||
type messageSetDesc struct {
|
||||
t reflect.Type // pointer to struct
|
||||
name string
|
||||
}
|
||||
|
||||
// RegisterMessageSetType is called from the generated code.
|
||||
func RegisterMessageSetType(m Message, fieldNum int32, name string) {
|
||||
messageSetMap[fieldNum] = messageSetDesc{
|
||||
t: reflect.TypeOf(m),
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -79,10 +79,13 @@ func toPointer(i *Message) pointer {
|
||||
|
||||
// toAddrPointer converts an interface to a pointer that points to
|
||||
// the interface data.
|
||||
func toAddrPointer(i *interface{}, isptr bool) pointer {
|
||||
func toAddrPointer(i *interface{}, isptr, deref bool) pointer {
|
||||
v := reflect.ValueOf(*i)
|
||||
u := reflect.New(v.Type())
|
||||
u.Elem().Set(v)
|
||||
if deref {
|
||||
u = u.Elem()
|
||||
}
|
||||
return pointer{v: u}
|
||||
}
|
||||
|
||||
|
||||
+10
-5
@@ -85,16 +85,21 @@ func toPointer(i *Message) pointer {
|
||||
|
||||
// toAddrPointer converts an interface to a pointer that points to
|
||||
// the interface data.
|
||||
func toAddrPointer(i *interface{}, isptr bool) pointer {
|
||||
func toAddrPointer(i *interface{}, isptr, deref bool) (p pointer) {
|
||||
// Super-tricky - read or get the address of data word of interface value.
|
||||
if isptr {
|
||||
// The interface is of pointer type, thus it is a direct interface.
|
||||
// The data word is the pointer data itself. We take its address.
|
||||
return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
|
||||
p = pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
|
||||
} else {
|
||||
// The interface is not of pointer type. The data word is the pointer
|
||||
// to the data.
|
||||
p = pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
|
||||
}
|
||||
// The interface is not of pointer type. The data word is the pointer
|
||||
// to the data.
|
||||
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
|
||||
if deref {
|
||||
p.p = *(*unsafe.Pointer)(p.p)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// valToPointer converts v to a pointer. v must be of pointer type.
|
||||
|
||||
+16
-15
@@ -334,9 +334,6 @@ func GetProperties(t reflect.Type) *StructProperties {
|
||||
sprop, ok := propertiesMap[t]
|
||||
propertiesMu.RUnlock()
|
||||
if ok {
|
||||
if collectStats {
|
||||
stats.Chit++
|
||||
}
|
||||
return sprop
|
||||
}
|
||||
|
||||
@@ -346,17 +343,20 @@ func GetProperties(t reflect.Type) *StructProperties {
|
||||
return sprop
|
||||
}
|
||||
|
||||
type (
|
||||
oneofFuncsIface interface {
|
||||
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
|
||||
}
|
||||
oneofWrappersIface interface {
|
||||
XXX_OneofWrappers() []interface{}
|
||||
}
|
||||
)
|
||||
|
||||
// getPropertiesLocked requires that propertiesMu is held.
|
||||
func getPropertiesLocked(t reflect.Type) *StructProperties {
|
||||
if prop, ok := propertiesMap[t]; ok {
|
||||
if collectStats {
|
||||
stats.Chit++
|
||||
}
|
||||
return prop
|
||||
}
|
||||
if collectStats {
|
||||
stats.Cmiss++
|
||||
}
|
||||
|
||||
prop := new(StructProperties)
|
||||
// in case of recursive protos, fill this in now.
|
||||
@@ -391,13 +391,14 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
||||
// Re-order prop.order.
|
||||
sort.Sort(prop)
|
||||
|
||||
type oneofMessage interface {
|
||||
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
|
||||
var oots []interface{}
|
||||
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
|
||||
case oneofFuncsIface:
|
||||
_, _, _, oots = m.XXX_OneofFuncs()
|
||||
case oneofWrappersIface:
|
||||
oots = m.XXX_OneofWrappers()
|
||||
}
|
||||
if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
|
||||
var oots []interface{}
|
||||
_, _, _, oots = om.XXX_OneofFuncs()
|
||||
|
||||
if len(oots) > 0 {
|
||||
// Interpret oneof metadata.
|
||||
prop.OneofTypes = make(map[string]*OneofProperties)
|
||||
for _, oot := range oots {
|
||||
|
||||
+27
-18
@@ -87,6 +87,7 @@ type marshalElemInfo struct {
|
||||
sizer sizer
|
||||
marshaler marshaler
|
||||
isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only)
|
||||
deref bool // dereference the pointer before operating on it; implies isptr
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -320,8 +321,11 @@ func (u *marshalInfo) computeMarshalInfo() {
|
||||
|
||||
// get oneof implementers
|
||||
var oneofImplementers []interface{}
|
||||
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
|
||||
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
|
||||
case oneofFuncsIface:
|
||||
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
|
||||
case oneofWrappersIface:
|
||||
oneofImplementers = m.XXX_OneofWrappers()
|
||||
}
|
||||
|
||||
n := t.NumField()
|
||||
@@ -407,13 +411,22 @@ func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo {
|
||||
panic("tag is not an integer")
|
||||
}
|
||||
wt := wiretype(tags[0])
|
||||
if t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct {
|
||||
t = t.Elem()
|
||||
}
|
||||
sizer, marshaler := typeMarshaler(t, tags, false, false)
|
||||
var deref bool
|
||||
if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
|
||||
t = reflect.PtrTo(t)
|
||||
deref = true
|
||||
}
|
||||
e = &marshalElemInfo{
|
||||
wiretag: uint64(tag)<<3 | wt,
|
||||
tagsize: SizeVarint(uint64(tag) << 3),
|
||||
sizer: sizer,
|
||||
marshaler: marshaler,
|
||||
isptr: t.Kind() == reflect.Ptr,
|
||||
deref: deref,
|
||||
}
|
||||
|
||||
// update cache
|
||||
@@ -448,7 +461,7 @@ func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) {
|
||||
|
||||
func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) {
|
||||
fi.field = toField(f)
|
||||
fi.wiretag = 1<<31 - 1 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
|
||||
fi.wiretag = math.MaxInt32 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
|
||||
fi.isPointer = true
|
||||
fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f)
|
||||
fi.oneofElems = make(map[reflect.Type]*marshalElemInfo)
|
||||
@@ -476,10 +489,6 @@ func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofI
|
||||
}
|
||||
}
|
||||
|
||||
type oneofMessage interface {
|
||||
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
|
||||
}
|
||||
|
||||
// wiretype returns the wire encoding of the type.
|
||||
func wiretype(encoding string) uint64 {
|
||||
switch encoding {
|
||||
@@ -2310,8 +2319,8 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
|
||||
for _, k := range m.MapKeys() {
|
||||
ki := k.Interface()
|
||||
vi := m.MapIndex(k).Interface()
|
||||
kaddr := toAddrPointer(&ki, false) // pointer to key
|
||||
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
|
||||
kaddr := toAddrPointer(&ki, false, false) // pointer to key
|
||||
vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
|
||||
siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
|
||||
n += siz + SizeVarint(uint64(siz)) + tagsize
|
||||
}
|
||||
@@ -2329,8 +2338,8 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
|
||||
for _, k := range keys {
|
||||
ki := k.Interface()
|
||||
vi := m.MapIndex(k).Interface()
|
||||
kaddr := toAddrPointer(&ki, false) // pointer to key
|
||||
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
|
||||
kaddr := toAddrPointer(&ki, false, false) // pointer to key
|
||||
vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
|
||||
b = appendVarint(b, tag)
|
||||
siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
|
||||
b = appendVarint(b, uint64(siz))
|
||||
@@ -2399,7 +2408,7 @@ func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int {
|
||||
// the last time this function was called.
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
n += ei.sizer(p, ei.tagsize)
|
||||
}
|
||||
mu.Unlock()
|
||||
@@ -2434,7 +2443,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
|
||||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
@@ -2465,7 +2474,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
|
||||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
@@ -2510,7 +2519,7 @@ func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int {
|
||||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
n += ei.sizer(p, 1) // message, tag = 3 (size=1)
|
||||
}
|
||||
mu.Unlock()
|
||||
@@ -2553,7 +2562,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
|
||||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
@@ -2591,7 +2600,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
|
||||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
|
||||
b = append(b, 1<<3|WireEndGroup)
|
||||
if !nerr.Merge(err) {
|
||||
@@ -2621,7 +2630,7 @@ func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int {
|
||||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
n += ei.sizer(p, ei.tagsize)
|
||||
}
|
||||
return n
|
||||
@@ -2656,7 +2665,7 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ
|
||||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
|
||||
+38
-36
@@ -136,7 +136,7 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
|
||||
u.computeUnmarshalInfo()
|
||||
}
|
||||
if u.isMessageSet {
|
||||
return UnmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
|
||||
return unmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
|
||||
}
|
||||
var reqMask uint64 // bitmask of required fields we've seen.
|
||||
var errLater error
|
||||
@@ -362,46 +362,48 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
|
||||
}
|
||||
|
||||
// Find any types associated with oneof fields.
|
||||
// TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it?
|
||||
fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs")
|
||||
if fn.IsValid() {
|
||||
res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{}
|
||||
for i := res.Len() - 1; i >= 0; i-- {
|
||||
v := res.Index(i) // interface{}
|
||||
tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X
|
||||
typ := tptr.Elem() // Msg_X
|
||||
var oneofImplementers []interface{}
|
||||
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
|
||||
case oneofFuncsIface:
|
||||
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
|
||||
case oneofWrappersIface:
|
||||
oneofImplementers = m.XXX_OneofWrappers()
|
||||
}
|
||||
for _, v := range oneofImplementers {
|
||||
tptr := reflect.TypeOf(v) // *Msg_X
|
||||
typ := tptr.Elem() // Msg_X
|
||||
|
||||
f := typ.Field(0) // oneof implementers have one field
|
||||
baseUnmarshal := fieldUnmarshaler(&f)
|
||||
tags := strings.Split(f.Tag.Get("protobuf"), ",")
|
||||
fieldNum, err := strconv.Atoi(tags[1])
|
||||
if err != nil {
|
||||
panic("protobuf tag field not an integer: " + tags[1])
|
||||
}
|
||||
var name string
|
||||
for _, tag := range tags {
|
||||
if strings.HasPrefix(tag, "name=") {
|
||||
name = strings.TrimPrefix(tag, "name=")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Find the oneof field that this struct implements.
|
||||
// Might take O(n^2) to process all of the oneofs, but who cares.
|
||||
for _, of := range oneofFields {
|
||||
if tptr.Implements(of.ityp) {
|
||||
// We have found the corresponding interface for this struct.
|
||||
// That lets us know where this struct should be stored
|
||||
// when we encounter it during unmarshaling.
|
||||
unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
|
||||
u.setTag(fieldNum, of.field, unmarshal, 0, name)
|
||||
}
|
||||
f := typ.Field(0) // oneof implementers have one field
|
||||
baseUnmarshal := fieldUnmarshaler(&f)
|
||||
tags := strings.Split(f.Tag.Get("protobuf"), ",")
|
||||
fieldNum, err := strconv.Atoi(tags[1])
|
||||
if err != nil {
|
||||
panic("protobuf tag field not an integer: " + tags[1])
|
||||
}
|
||||
var name string
|
||||
for _, tag := range tags {
|
||||
if strings.HasPrefix(tag, "name=") {
|
||||
name = strings.TrimPrefix(tag, "name=")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Find the oneof field that this struct implements.
|
||||
// Might take O(n^2) to process all of the oneofs, but who cares.
|
||||
for _, of := range oneofFields {
|
||||
if tptr.Implements(of.ityp) {
|
||||
// We have found the corresponding interface for this struct.
|
||||
// That lets us know where this struct should be stored
|
||||
// when we encounter it during unmarshaling.
|
||||
unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
|
||||
u.setTag(fieldNum, of.field, unmarshal, 0, name)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Get extension ranges, if any.
|
||||
fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
|
||||
fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
|
||||
if fn.IsValid() {
|
||||
if !u.extensions.IsValid() && !u.oldExtensions.IsValid() {
|
||||
panic("a message with extensions, but no extensions field in " + t.Name())
|
||||
@@ -1948,7 +1950,7 @@ func encodeVarint(b []byte, x uint64) []byte {
|
||||
// If there is an error, it returns 0,0.
|
||||
func decodeVarint(b []byte) (uint64, int) {
|
||||
var x, y uint64
|
||||
if len(b) <= 0 {
|
||||
if len(b) == 0 {
|
||||
goto bad
|
||||
}
|
||||
x = uint64(b[0])
|
||||
|
||||
+27
-18
@@ -1,11 +1,13 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
package any // import "github.com/golang/protobuf/ptypes/any"
|
||||
package any
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
@@ -16,7 +18,7 @@ var _ = math.Inf
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// `Any` contains an arbitrary serialized protocol buffer message along with a
|
||||
// URL that describes the type of the serialized message.
|
||||
@@ -99,17 +101,18 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
// }
|
||||
//
|
||||
type Any struct {
|
||||
// A URL/resource name whose content describes the type of the
|
||||
// serialized protocol buffer message.
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// protocol buffer message. The last segment of the URL's path must represent
|
||||
// the fully qualified name of the type (as in
|
||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
// (e.g., leading "." is not accepted).
|
||||
//
|
||||
// For URLs which use the scheme `http`, `https`, or no scheme, the
|
||||
// following restrictions and interpretations apply:
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// expect it to use in the context of Any. However, for URLs which use the
|
||||
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
// server that maps type URLs to message definitions as follows:
|
||||
//
|
||||
// * If no scheme is provided, `https` is assumed.
|
||||
// * The last segment of the URL's path must represent the fully
|
||||
// qualified name of the type (as in `path/google.protobuf.Duration`).
|
||||
// The name should be in a canonical form (e.g., leading "." is
|
||||
// not accepted).
|
||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
// value in binary format, or produce an error.
|
||||
// * Applications are allowed to cache lookup results based on the
|
||||
@@ -118,6 +121,10 @@ type Any struct {
|
||||
// on changes to types. (Use versioned type names to manage
|
||||
// breaking changes.)
|
||||
//
|
||||
// Note: this functionality is not currently available in the official
|
||||
// protobuf release, and it is not used for type URLs beginning with
|
||||
// type.googleapis.com.
|
||||
//
|
||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
// used with implementation specific semantics.
|
||||
//
|
||||
@@ -133,17 +140,19 @@ func (m *Any) Reset() { *m = Any{} }
|
||||
func (m *Any) String() string { return proto.CompactTextString(m) }
|
||||
func (*Any) ProtoMessage() {}
|
||||
func (*Any) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_any_744b9ca530f228db, []int{0}
|
||||
return fileDescriptor_b53526c13ae22eb4, []int{0}
|
||||
}
|
||||
|
||||
func (*Any) XXX_WellKnownType() string { return "Any" }
|
||||
|
||||
func (m *Any) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Any.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Any) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Any.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Any) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Any.Merge(dst, src)
|
||||
func (m *Any) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Any.Merge(m, src)
|
||||
}
|
||||
func (m *Any) XXX_Size() int {
|
||||
return xxx_messageInfo_Any.Size(m)
|
||||
@@ -172,9 +181,9 @@ func init() {
|
||||
proto.RegisterType((*Any)(nil), "google.protobuf.Any")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_any_744b9ca530f228db) }
|
||||
func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_b53526c13ae22eb4) }
|
||||
|
||||
var fileDescriptor_any_744b9ca530f228db = []byte{
|
||||
var fileDescriptor_b53526c13ae22eb4 = []byte{
|
||||
// 185 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4,
|
||||
|
||||
+13
-8
@@ -120,17 +120,18 @@ option objc_class_prefix = "GPB";
|
||||
// }
|
||||
//
|
||||
message Any {
|
||||
// A URL/resource name whose content describes the type of the
|
||||
// serialized protocol buffer message.
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// protocol buffer message. The last segment of the URL's path must represent
|
||||
// the fully qualified name of the type (as in
|
||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
// (e.g., leading "." is not accepted).
|
||||
//
|
||||
// For URLs which use the scheme `http`, `https`, or no scheme, the
|
||||
// following restrictions and interpretations apply:
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// expect it to use in the context of Any. However, for URLs which use the
|
||||
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
// server that maps type URLs to message definitions as follows:
|
||||
//
|
||||
// * If no scheme is provided, `https` is assumed.
|
||||
// * The last segment of the URL's path must represent the fully
|
||||
// qualified name of the type (as in `path/google.protobuf.Duration`).
|
||||
// The name should be in a canonical form (e.g., leading "." is
|
||||
// not accepted).
|
||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
// value in binary format, or produce an error.
|
||||
// * Applications are allowed to cache lookup results based on the
|
||||
@@ -139,6 +140,10 @@ message Any {
|
||||
// on changes to types. (Use versioned type names to manage
|
||||
// breaking changes.)
|
||||
//
|
||||
// Note: this functionality is not currently available in the official
|
||||
// protobuf release, and it is not used for type URLs beginning with
|
||||
// type.googleapis.com.
|
||||
//
|
||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
// used with implementation specific semantics.
|
||||
//
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ func Duration(p *durpb.Duration) (time.Duration, error) {
|
||||
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
|
||||
}
|
||||
if p.Nanos != 0 {
|
||||
d += time.Duration(p.Nanos)
|
||||
d += time.Duration(p.Nanos) * time.Nanosecond
|
||||
if (d < 0) != (p.Nanos < 0) {
|
||||
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
|
||||
}
|
||||
|
||||
+14
-12
@@ -1,11 +1,13 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: google/protobuf/duration.proto
|
||||
|
||||
package duration // import "github.com/golang/protobuf/ptypes/duration"
|
||||
package duration
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
@@ -16,7 +18,7 @@ var _ = math.Inf
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// A Duration represents a signed, fixed-length span of time represented
|
||||
// as a count of seconds and fractions of seconds at nanosecond
|
||||
@@ -99,17 +101,19 @@ func (m *Duration) Reset() { *m = Duration{} }
|
||||
func (m *Duration) String() string { return proto.CompactTextString(m) }
|
||||
func (*Duration) ProtoMessage() {}
|
||||
func (*Duration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_duration_e7d612259e3f0613, []int{0}
|
||||
return fileDescriptor_23597b2ebd7ac6c5, []int{0}
|
||||
}
|
||||
|
||||
func (*Duration) XXX_WellKnownType() string { return "Duration" }
|
||||
|
||||
func (m *Duration) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Duration.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Duration.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Duration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Duration.Merge(dst, src)
|
||||
func (m *Duration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Duration.Merge(m, src)
|
||||
}
|
||||
func (m *Duration) XXX_Size() int {
|
||||
return xxx_messageInfo_Duration.Size(m)
|
||||
@@ -138,11 +142,9 @@ func init() {
|
||||
proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_duration_e7d612259e3f0613)
|
||||
}
|
||||
func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_23597b2ebd7ac6c5) }
|
||||
|
||||
var fileDescriptor_duration_e7d612259e3f0613 = []byte{
|
||||
var fileDescriptor_23597b2ebd7ac6c5 = []byte{
|
||||
// 190 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a,
|
||||
|
||||
+2
-4
@@ -111,11 +111,9 @@ func TimestampNow() *tspb.Timestamp {
|
||||
// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
|
||||
// It returns an error if the resulting Timestamp is invalid.
|
||||
func TimestampProto(t time.Time) (*tspb.Timestamp, error) {
|
||||
seconds := t.Unix()
|
||||
nanos := int32(t.Sub(time.Unix(seconds, 0)))
|
||||
ts := &tspb.Timestamp{
|
||||
Seconds: seconds,
|
||||
Nanos: nanos,
|
||||
Seconds: t.Unix(),
|
||||
Nanos: int32(t.Nanosecond()),
|
||||
}
|
||||
if err := validateTimestamp(ts); err != nil {
|
||||
return nil, err
|
||||
|
||||
+19
-15
@@ -1,11 +1,13 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: google/protobuf/timestamp.proto
|
||||
|
||||
package timestamp // import "github.com/golang/protobuf/ptypes/timestamp"
|
||||
package timestamp
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
@@ -16,7 +18,7 @@ var _ = math.Inf
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// A Timestamp represents a point in time independent of any time zone
|
||||
// or calendar, represented as seconds and fractions of seconds at
|
||||
@@ -81,7 +83,9 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
|
||||
// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
|
||||
// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
|
||||
// is required, though only UTC (as indicated by "Z") is presently supported.
|
||||
// is required. A proto3 JSON serializer should always use UTC (as indicated by
|
||||
// "Z") when printing the Timestamp type and a proto3 JSON parser should be
|
||||
// able to accept both UTC and other timezones (as indicated by an offset).
|
||||
//
|
||||
// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
|
||||
// 01:30 UTC on January 15, 2017.
|
||||
@@ -92,8 +96,8 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
||||
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
||||
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--)
|
||||
// to obtain a formatter capable of generating timestamps in this format.
|
||||
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
|
||||
// ) to obtain a formatter capable of generating timestamps in this format.
|
||||
//
|
||||
//
|
||||
type Timestamp struct {
|
||||
@@ -115,17 +119,19 @@ func (m *Timestamp) Reset() { *m = Timestamp{} }
|
||||
func (m *Timestamp) String() string { return proto.CompactTextString(m) }
|
||||
func (*Timestamp) ProtoMessage() {}
|
||||
func (*Timestamp) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_timestamp_b826e8e5fba671a8, []int{0}
|
||||
return fileDescriptor_292007bbfe81227e, []int{0}
|
||||
}
|
||||
|
||||
func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" }
|
||||
|
||||
func (m *Timestamp) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Timestamp.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Timestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Timestamp.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Timestamp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Timestamp.Merge(dst, src)
|
||||
func (m *Timestamp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Timestamp.Merge(m, src)
|
||||
}
|
||||
func (m *Timestamp) XXX_Size() int {
|
||||
return xxx_messageInfo_Timestamp.Size(m)
|
||||
@@ -154,11 +160,9 @@ func init() {
|
||||
proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_timestamp_b826e8e5fba671a8)
|
||||
}
|
||||
func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_292007bbfe81227e) }
|
||||
|
||||
var fileDescriptor_timestamp_b826e8e5fba671a8 = []byte{
|
||||
var fileDescriptor_292007bbfe81227e = []byte{
|
||||
// 191 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d,
|
||||
|
||||
+5
-3
@@ -103,7 +103,9 @@ option objc_class_prefix = "GPB";
|
||||
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
|
||||
// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
|
||||
// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
|
||||
// is required, though only UTC (as indicated by "Z") is presently supported.
|
||||
// is required. A proto3 JSON serializer should always use UTC (as indicated by
|
||||
// "Z") when printing the Timestamp type and a proto3 JSON parser should be
|
||||
// able to accept both UTC and other timezones (as indicated by an offset).
|
||||
//
|
||||
// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
|
||||
// 01:30 UTC on January 15, 2017.
|
||||
@@ -114,8 +116,8 @@ option objc_class_prefix = "GPB";
|
||||
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
||||
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
||||
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--)
|
||||
// to obtain a formatter capable of generating timestamps in this format.
|
||||
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
|
||||
// ) to obtain a formatter capable of generating timestamps in this format.
|
||||
//
|
||||
//
|
||||
message Timestamp {
|
||||
|
||||
Vendored
+7
-7
@@ -270,7 +270,7 @@ github.com/golang-plus/uuid/internal/random
|
||||
github.com/golang-plus/uuid/internal/timebased
|
||||
# github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
|
||||
github.com/golang/glog
|
||||
# github.com/golang/protobuf v1.2.0
|
||||
# github.com/golang/protobuf v1.3.1
|
||||
github.com/golang/protobuf/proto
|
||||
github.com/golang/protobuf/ptypes
|
||||
github.com/golang/protobuf/ptypes/any
|
||||
@@ -509,16 +509,16 @@ golang.org/x/net/bpf
|
||||
golang.org/x/net/ipv4
|
||||
golang.org/x/net/proxy
|
||||
golang.org/x/net/ipv6
|
||||
golang.org/x/net/trace
|
||||
golang.org/x/net/internal/iana
|
||||
golang.org/x/net/internal/socket
|
||||
golang.org/x/net/http2
|
||||
golang.org/x/net/context
|
||||
golang.org/x/net/trace
|
||||
golang.org/x/net/internal/socks
|
||||
golang.org/x/net/http/httpguts
|
||||
golang.org/x/net/http2/hpack
|
||||
golang.org/x/net/idna
|
||||
golang.org/x/net/internal/timeseries
|
||||
golang.org/x/net/http2/hpack
|
||||
golang.org/x/net/http/httpguts
|
||||
golang.org/x/net/idna
|
||||
golang.org/x/net/context/ctxhttp
|
||||
# golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890
|
||||
golang.org/x/oauth2
|
||||
@@ -551,14 +551,14 @@ google.golang.org/appengine/internal/urlfetch
|
||||
google.golang.org/genproto/googleapis/rpc/status
|
||||
# google.golang.org/grpc v1.19.0
|
||||
google.golang.org/grpc
|
||||
google.golang.org/grpc/codes
|
||||
google.golang.org/grpc/status
|
||||
google.golang.org/grpc/peer
|
||||
google.golang.org/grpc/credentials
|
||||
google.golang.org/grpc/codes
|
||||
google.golang.org/grpc/grpclog
|
||||
google.golang.org/grpc/health/grpc_health_v1
|
||||
google.golang.org/grpc/keepalive
|
||||
google.golang.org/grpc/metadata
|
||||
google.golang.org/grpc/status
|
||||
google.golang.org/grpc/balancer
|
||||
google.golang.org/grpc/balancer/roundrobin
|
||||
google.golang.org/grpc/connectivity
|
||||
|
||||
Reference in New Issue
Block a user