mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-30 17:13:08 +08:00
diskhandler: local disk create, delete, resize
This commit is contained in:
@@ -0,0 +1 @@
|
||||
package storagetypes // import "yunion.io/x/onecloud/pkg/cloudcommon/storagetypes"
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/netutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/timeutils2"
|
||||
)
|
||||
|
||||
@@ -376,7 +377,6 @@ func (m *SGuestManager) GetFreeVncPort() int64 {
|
||||
}
|
||||
var port = 1
|
||||
for {
|
||||
// TODO: IsTcpPortUsed
|
||||
if _, ok := vncPorts[port]; !ok && !netutils2.IsTcpPortUsed("0.0.0.0", VNC_PORT_BASE+port) &&
|
||||
!netutils2.IsTcpPortUsed("0.0.0.0", MONITOR_PORT_BASE+port) {
|
||||
break
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
package guestman
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostinfo"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman"
|
||||
"yunion.io/x/onecloud/pkg/util/qemutils"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -13,6 +18,10 @@ var (
|
||||
OS_NAME_VMWARE = "VMWare"
|
||||
)
|
||||
|
||||
func IsKvmSupport() bool {
|
||||
return hostinfo.Instance().IsKvmSupport()
|
||||
}
|
||||
|
||||
func (s *SKVMGuestInstance) getOsname() string {
|
||||
if s.Desc.Contains("metadata") {
|
||||
metadata, _ := s.Desc.Get("metadata")
|
||||
@@ -42,4 +51,88 @@ func (s *SKVMGuestInstance) generateStartScript(data *jsonutils.JSONDict) (strin
|
||||
}
|
||||
|
||||
// TODO: isolatedDevsParams := hostinfo.Instance()...
|
||||
|
||||
nics, _ := s.Desc.GetArray("nics")
|
||||
for _, nic := range nics {
|
||||
downscript := s.getNicDownScriptPath(nic)
|
||||
ifname, _ := nic.GetString("ifnam")
|
||||
cmd += fmt.Sprintf("%s %s\n", downscript, ifname)
|
||||
}
|
||||
|
||||
if options.HostOptions.HugepagesOption == "native" {
|
||||
uuid, _ := s.Desc.GetString("uuid")
|
||||
mem, _ := s.Desc.Int("mem")
|
||||
cmd += fmt.Sprintf("mkdir -p /dev/hugepages/%s\n", uuid)
|
||||
cmd += fmt.Sprintf("mount -t hugetlbfs -o size=%dM hugetlbfs-%s /dev/hugepages/%s\n",
|
||||
mem, uuid, uuid)
|
||||
}
|
||||
|
||||
cmd += "sleep 1\n"
|
||||
cmd += fmt.Sprintf("echo %d > %s\n", vncPort, s.GetVncFilePath())
|
||||
|
||||
disks, _ := s.Desc.GetArray("disks")
|
||||
for _, disk := range disks {
|
||||
diskPath, _ := disk.GetString("path")
|
||||
d := storageman.GetManager().GetDiskByPath(diskPath)
|
||||
if d == nil {
|
||||
return fmt.Errorf("get disk %s by storage error", diskPath)
|
||||
}
|
||||
|
||||
diskIndex, _ := disk.Int("index")
|
||||
// TODO
|
||||
cmd += d.GetDiskSetupScripts(diskIndex)
|
||||
}
|
||||
|
||||
cmd += fmt.Sprintf("STATE_FILE=`ls -d %s* | head -n 1`\n", s.getStateFilePathRootPrefix())
|
||||
|
||||
var qemuCmd = qemutils.GetQemu(qemuVersion)
|
||||
cmd += fmt.Sprintf("DEFAULT_QEMU_CMD='%s'\n", qemu_cmd)
|
||||
cmd += `if [ -n "$STATE_FILE" ]; then\n`
|
||||
cmd += " QEMU_VER=`echo $STATE_FILE" +
|
||||
` | grep -o '_[[:digit:]]\+\.[[:digit:]]\+.*'` + "`\n"
|
||||
cmd += ` QEMU_CMD="qemu-system-x86_64"\n`
|
||||
cmd += ` QEMU_LOCAL_PATH="/usr/local/bin/$QEMU_CMD"\n`
|
||||
cmd += ` QEMU_LOCAL_PATH_VER="/usr/local/qemu-$QEMU_VER/bin/$QEMU_CMD"\n`
|
||||
cmd += ` QEMU_BIN_PATH="/usr/bin/$QEMU_CMD"\n`
|
||||
cmd += ` if [ -f "$QEMU_LOCAL_PATH_VER" ]; then\n`
|
||||
cmd += ` QEMU_CMD=$QEMU_LOCAL_PATH_VER\n`
|
||||
cmd += ` elif [ -f "$QEMU_LOCAL_PATH" ]; then\n`
|
||||
cmd += ` QEMU_CMD=$QEMU_LOCAL_PATH\n`
|
||||
cmd += ` elif [ -f "$QEMU_BIN_PATH" ]; then\n`
|
||||
cmd += ` QEMU_CMD=$QEMU_BIN_PATH\n`
|
||||
cmd += ` fi\n`
|
||||
cmd += `else\n`
|
||||
cmd += ` QEMU_CMD=$DEFAULT_QEMU_CMD\n`
|
||||
cmd += `fi\n`
|
||||
cmd += `function nic_speed() {\n`
|
||||
cmd += ` $QEMU_CMD `
|
||||
|
||||
var accel, cpuType string
|
||||
if s.IsKvmSupport() {
|
||||
cmd += " -enable-kvm"
|
||||
accel = "kvm"
|
||||
cpuType = ""
|
||||
if osname == OS_NAME_MACOS {
|
||||
cpuType = "Penryn,vendor=GenuineIntel"
|
||||
} else {
|
||||
cpuType = "host"
|
||||
}
|
||||
|
||||
if !hostinfo.Instance().IsNestedVirtualization() {
|
||||
cpu_type += ",kvm=off"
|
||||
}
|
||||
|
||||
// TODO
|
||||
// if isolated_devs_params.get('cpu', None):
|
||||
// cpu_type = isolated_devs_params['cpu']
|
||||
} else {
|
||||
cmd += " -no-kvm"
|
||||
accel = "tcg"
|
||||
cpu_type = "qemu64"
|
||||
}
|
||||
|
||||
cmd += fmt.Sprintf(" -cpu %s", cpu_type)
|
||||
|
||||
// TODO hmp - -
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package hostdhcp // import "yunion.io/x/onecloud/pkg/hostman/hostinfo/hostdhcp"
|
||||
@@ -47,6 +47,17 @@ type SHostInfo struct {
|
||||
Nics []*SNIC
|
||||
}
|
||||
|
||||
func (h *SHostInfo) IsKvmSupport() bool {
|
||||
if h.kvmModuleSupport == KVM_MODULE_UNSUPPORT {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (h *SHostInfo) IsNestedVirtualization() bool {
|
||||
return utils.IsInStringArray("hypervisor", h.Cpu.cpuFeatures)
|
||||
}
|
||||
|
||||
func (h *SHostInfo) Start() error {
|
||||
if err := h.prepareEnv(); err != nil {
|
||||
return err
|
||||
@@ -65,7 +76,6 @@ func (h *SHostInfo) parseConfig() error {
|
||||
return fmt.Errorf("Not enough memory!")
|
||||
}
|
||||
if len(options.HostOptions.ListenInterface) > 0 {
|
||||
// TODO netutils.NetInterface netutils未实现
|
||||
h.MasterNic = netutils2.NewNetInterface(options.HostOptions.ListenInterface)
|
||||
} else {
|
||||
h.MasterNic = nil
|
||||
@@ -246,7 +256,6 @@ func (h *SHostInfo) fixPathEnv() error {
|
||||
"/usr/sbin",
|
||||
"/usr/bin",
|
||||
}
|
||||
// env := os.Getenv("PATH")
|
||||
return os.Setenv("PATH", strings.Join(paths, ":"))
|
||||
}
|
||||
|
||||
@@ -607,9 +616,8 @@ func Init() error {
|
||||
}
|
||||
|
||||
func Instance() *SHostInfo {
|
||||
if hostInfo == nil {
|
||||
panic("Get nil hostinfo, Init first")
|
||||
}
|
||||
return hostInfo
|
||||
}
|
||||
|
||||
// func GetStorageManager() *storageman.SStorageManager {
|
||||
// return hostInfo.storageManager
|
||||
// }
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package hostutils // import "yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
@@ -0,0 +1,26 @@
|
||||
package isolated_device
|
||||
|
||||
const (
|
||||
// TODO: merge models/isolated_devices in new file
|
||||
DIRECT_PCI_TYPE = "PCI"
|
||||
GPU_HPC_TYPE = "GPU-HPC" // # for compute
|
||||
GPU_VGA_TYPE = "GPU-VGA" // # for display
|
||||
USB_TYPE = "USB"
|
||||
)
|
||||
|
||||
const (
|
||||
BUSID_REGEX = `[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F]`
|
||||
CODE_REGEX = `[0-9a-fA-F]{4}`
|
||||
LABEL_REGEX = `[\w+\ \.\,\:\+\&\-\/\[\]\(\)]+`
|
||||
|
||||
VFIO_PCI_KERNEL_DRIVER = "vfio-pci"
|
||||
DEFAULT_VGA_CMD = " -vga std"
|
||||
DEFAULT_CPU_CMD = "host,kvm=off"
|
||||
|
||||
RESOURCE = "isolated_devices"
|
||||
)
|
||||
|
||||
// # 在qemu/kvm下模拟Windows Hyper-V的一些半虚拟化特性,以便更好地使用Win虚拟机
|
||||
// # http://blog.wikichoon.com/2014/07/enabling-hyper-v-enlightenments-with-kvm.html
|
||||
// 但实际测试不行,虚拟机不能运行nvidia驱动
|
||||
// #DEFAULT_CPU_CMD = "host,kvm=off,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time"
|
||||
@@ -24,9 +24,9 @@ func (host *SHostService) StartService() {
|
||||
cloudcommon.ParseOptions(&options.HostOptions, &options.HostOptions.CommonOptions, os.Args, "host.conf")
|
||||
|
||||
// TODO
|
||||
// Hostinfo.Init()
|
||||
// storageman.Init()
|
||||
// isolatedman.Init()
|
||||
// Hostinfo.Init()
|
||||
// Firewall.Init()
|
||||
// hostman.Init()
|
||||
|
||||
|
||||
@@ -13,13 +13,14 @@ import (
|
||||
|
||||
type IDisk interface {
|
||||
GetId() string
|
||||
Probe() bool
|
||||
Probe() error
|
||||
|
||||
GetDiskDesc() jsonutils.JSONObject
|
||||
|
||||
// TODO
|
||||
// DeleteAllSnapshot() error
|
||||
Delete() error
|
||||
Delete(ctx context.Context, params interface{}) (jsonutils.JSONObject, error)
|
||||
Resize(ctx context.Context, params interface{}) (jsonutils.JSONObject, error)
|
||||
|
||||
GetPath() string
|
||||
CreateFromUrl(context.Context, string) error
|
||||
@@ -29,8 +30,6 @@ type IDisk interface {
|
||||
CreateRaw(ctx context.Context, sizeMb int, diskFromat string, fsFormat string,
|
||||
encryption bool, diskId string, back string) (jsonutils.JSONObject, error)
|
||||
|
||||
Resize(context.Context, int64) error
|
||||
|
||||
// @params: diskPath, guestDesc, deployInfo
|
||||
DeployGuestFs(string, *jsonutils.JSONDict, *guestfs.SDeployInfo) (jsonutils.JSONObject, error)
|
||||
}
|
||||
@@ -59,8 +58,8 @@ func (d *SBaseDisk) Probe() error {
|
||||
return fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (d *SBaseDisk) Delete() error {
|
||||
return fmt.Errorf("Not implemented")
|
||||
func (d *SBaseDisk) Delete(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (d *SBaseDisk) CreateFromUrl(context.Context, string) error {
|
||||
@@ -71,8 +70,8 @@ func (d *SBaseDisk) CreateFromTemplate(context.Context, string, string, int64) (
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (d *SBaseDisk) Resize(context.Context, int64) error {
|
||||
return fmt.Errorf("Not implemented")
|
||||
func (d *SBaseDisk) Resize(context.Context, interface{}) (jsonutils.JSONObject, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (d *SBaseDisk) GetZone() string {
|
||||
|
||||
@@ -86,11 +86,17 @@ func diskCreate(ctx context.Context, storage IStorage, diskId string, disk IDisk
|
||||
}
|
||||
|
||||
func diskDelete(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) {
|
||||
hostutils.DelayTask(ctx, storage.DeleteDisk, disk)
|
||||
hostutils.DelayTask(ctx, disk.Delete, nil)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func diskResize(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) {
|
||||
diskInfo, err := body.Get("disk")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Missing disk")
|
||||
}
|
||||
hostutils.DelayTask(ctx, disk.Resize, diskInfo)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var actionFuncs = map[string]actionFunc{
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -56,14 +57,23 @@ func (d *SLocalDisk) Probe() error {
|
||||
return fmt.Errorf("Disk not found")
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) Delete() error {
|
||||
func (d *SLocalDisk) UmountFuseImage() {
|
||||
mntPath := path.Join(d.Storage.GetFuseMountPath(), d.Id)
|
||||
if err := exec.Command("umount", mntPath).Run(); err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
if err := exec.Command("rm", "-rf", mntPath); err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) Delete(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
|
||||
dpath := d.GetPath()
|
||||
log.Infof("Delete guest disk %s", dpath)
|
||||
if err := d.Storage.DeleteDiskfile(dpath); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
// TODO: PostCreateFromImageFuse umount fuse fs
|
||||
// d.UmountImageFuse()
|
||||
d.UmountFuseImage()
|
||||
|
||||
/* ????????????????
|
||||
files = os.listdir(self.storage.path)
|
||||
@@ -76,6 +86,44 @@ func (d *SLocalDisk) Delete() error {
|
||||
*/
|
||||
|
||||
d.Storage.RemoveDisk(d)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) Resize(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
|
||||
diskInfo, ok := params.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Disk Resize Unknown Params")
|
||||
}
|
||||
|
||||
sizeMb, _ := diskInfo.Int("size")
|
||||
disk, err := qemuimg.NewQemuImage(d.GetPath())
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
if err := disk.Resize(int(sizeMb)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if options.HostOptions.EnableFallocateDisk {
|
||||
// TODO
|
||||
// d.Fallocate()
|
||||
}
|
||||
|
||||
if err = d.ResizeFs(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return d.GetDiskDesc(), nil
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) ResizeFs() error {
|
||||
disk := NewKVMGuestDisk(d.GetPath())
|
||||
if disk.Connect() {
|
||||
defer disk.Disconnect()
|
||||
if err := disk.ResizePartition(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -147,3 +147,7 @@ func (d *SKVMGuestDisk) MakePartition(fs string) error {
|
||||
func (d *SKVMGuestDisk) FormatPartition(fs, uuid string) error {
|
||||
return fileutils2.FormatPartition(fmt.Sprintf("%sp1", d.nbdDev), fs, uuid)
|
||||
}
|
||||
|
||||
func (d *SKVMGuestDisk) ResizePartition() error {
|
||||
return fileutils2.ResizeDiskFs(d.nbdDev, 0)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ type IStorage interface {
|
||||
// *SDiskCreateByDiskinfo
|
||||
CreateDiskByDiskinfo(context.Context, interface{}) (jsonutils.JSONObject, error)
|
||||
|
||||
// DeleteDiskfile(diskPath string) error
|
||||
DeleteDiskfile(diskPath string) error
|
||||
GetFuseTmpPath() string
|
||||
GetFuseMountPath() string
|
||||
}
|
||||
@@ -80,6 +80,10 @@ func (s *SBaseStorage) RemoveDisk(d IDisk) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SBaseStorage) DeleteDiskfile(diskpath string) error {
|
||||
return fmt.Sprintf("Not Implement")
|
||||
}
|
||||
|
||||
func (s *SBaseStorage) CreateDiskByDiskinfo(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
|
||||
createParams, ok := params.(*SDiskCreateByDiskinfo)
|
||||
if !ok {
|
||||
@@ -159,11 +163,3 @@ func (s *SBaseStorage) CreateDiskFromSnpashot(ctx context.Context, disk IDisk, c
|
||||
}
|
||||
return disk.GetDiskDesc(), nil
|
||||
}
|
||||
|
||||
func (s *SBaseStorage) DeleteDisk(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
|
||||
disk, ok := params.(IDisk)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Storage DeleteDisk Unknown params")
|
||||
}
|
||||
return nil, disk.Delete()
|
||||
}
|
||||
|
||||
@@ -3,16 +3,20 @@ package fileutils2
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/util/regutils2"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
func Cleandir(sPath string, keepdir bool) error {
|
||||
@@ -322,3 +326,266 @@ func FormatPartition(path, fs, uuid string) error {
|
||||
}
|
||||
return fmt.Errorf("Unknown fs %s", fs)
|
||||
}
|
||||
|
||||
func IsPartedFsString(fsstr string) bool {
|
||||
return utils.IsInStringArray(strings.ToLower(fsstr), []string{
|
||||
"ext2", "ext3", "ext4", "xfs",
|
||||
"fat16", "fat32",
|
||||
"hfs", "hfs+", "hfsx",
|
||||
"linux-swap", "linux-swap(v1)",
|
||||
"ntfs", "reiserfs", "ufs", "btrfs",
|
||||
})
|
||||
}
|
||||
|
||||
func ParseDiskPartition(dev string, lines []byte) ([][]string, string) {
|
||||
var (
|
||||
parts = [][]string{}
|
||||
label string
|
||||
labelPartten = regexp.MustCompile(`Partition Table:\s+(?P<label>\w+)`)
|
||||
partten = regexp.MustCompile(`(?P<idx>\d+)\s+(?P<start>\d+)s\s+(?P<end>\d+)s\s+(?P<count>\d+)s`)
|
||||
)
|
||||
|
||||
for _, line := range strings.Split(string(lines), "\n") {
|
||||
if len(label) == 0 {
|
||||
m := regutils2.GetParams(labelPartten, line)
|
||||
if len(m) > 0 {
|
||||
label = m["label"]
|
||||
}
|
||||
}
|
||||
m := regutils2.GetParams(partten, line)
|
||||
if len(m) > 0 {
|
||||
var (
|
||||
idx = m["idx"]
|
||||
start = m["start"]
|
||||
end = m["end"]
|
||||
count = m["count"]
|
||||
devname = dev
|
||||
)
|
||||
if '0' <= dev[len(dev)-1] && dev[len(dev)-1] <= '9' {
|
||||
devname += "p"
|
||||
}
|
||||
devname += idx
|
||||
data := regexp.MustCompile(`\s+`).Split(strings.TrimSpace(line), -1)
|
||||
|
||||
var disktype, fs, flag string
|
||||
var offset = 0
|
||||
if len(data) > 4 {
|
||||
if label == "msdos" {
|
||||
disktype = data[4]
|
||||
if len(data) > 5 && IsPartedFsString(data[5]) {
|
||||
fs = data[5]
|
||||
offset += 1
|
||||
}
|
||||
if len(data) > 5+offset {
|
||||
flag = data[5+offset]
|
||||
}
|
||||
} else if label == "gpt" {
|
||||
if IsPartedFsString(data[4]) {
|
||||
fs = data[4]
|
||||
offset += 1
|
||||
}
|
||||
if len(data) > 4+offset {
|
||||
disktype = data[4+offset]
|
||||
}
|
||||
if len(data) > 4+offset+1 {
|
||||
flag = data[4+offset+1]
|
||||
}
|
||||
}
|
||||
}
|
||||
var bootable = ""
|
||||
if len(flag) > 0 && strings.Index(flag, "boot") >= 0 {
|
||||
bootable = "true"
|
||||
}
|
||||
parts = append(parts, []string{idx, bootable, start, end, count, disktype, fs,
|
||||
devname})
|
||||
}
|
||||
}
|
||||
return parts, label
|
||||
}
|
||||
|
||||
func GetDevSector512Count(dev string) int {
|
||||
sizeStr, _ := FileGetContents(fmt.Sprintf("/sys/block/%s/size", dev))
|
||||
size, _ := strconv.Atoi(sizeStr)
|
||||
return size
|
||||
}
|
||||
|
||||
// TODO test
|
||||
func ResizeDiskFs(diskPath string, sizeMb int) error {
|
||||
var cmds = []string{"parted", "-a", "none", "-s", diskPath, "--", "unit", "s", "print"}
|
||||
lines, err := exec.Command(cmds[0], cmds[1:]...).Output()
|
||||
if err != nil {
|
||||
log.Errorf("resize disk fs fail: %s", err)
|
||||
return err
|
||||
}
|
||||
parts, label := ParseDiskPartition(diskPath, lines)
|
||||
log.Infof("Parts: %v label: %s", parts, label)
|
||||
maxSector := GetDevSector512Count(path.Base(diskPath))
|
||||
if label == "gpt" {
|
||||
proc := exec.Command("gdisk", diskPath)
|
||||
stdin, err := proc.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stdin.Close()
|
||||
|
||||
outb, err := proc.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outb.Close()
|
||||
|
||||
errb, err := proc.StderrPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer errb.Close()
|
||||
|
||||
if err := proc.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, s := range []string{"r", "e", "Y", "w", "Y", "Y"} {
|
||||
io.WriteString(stdin, s)
|
||||
}
|
||||
stdoutPut, err := ioutil.ReadAll(outb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stderrOutPut, err := ioutil.ReadAll(errb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof("gdisk: %s %s", stdoutPut, stderrOutPut)
|
||||
proc.Wait()
|
||||
}
|
||||
if len(parts) > 0 && (label == "gpt" ||
|
||||
(label == "msdos" && parts[len(parts)-1][5] == "primary")) {
|
||||
var (
|
||||
part = parts[len(parts)]
|
||||
end int
|
||||
)
|
||||
if sizeMb > 0 {
|
||||
end = sizeMb * 1024 * 2
|
||||
} else if label == "gpt" {
|
||||
end = maxSector - 35
|
||||
} else {
|
||||
end = maxSector - 1
|
||||
}
|
||||
if label == "msdos" && end >= 4294967296 {
|
||||
end = 4294967295
|
||||
}
|
||||
cmds = []string{"parted", "-a", "none", "-s", diskPath, "--",
|
||||
"unit", "s", "rm", part[0], "mkpart", part[5]}
|
||||
if len(part[6]) > 0 {
|
||||
cmds = append(cmds, part[6])
|
||||
}
|
||||
cmds = append(cmds, part[2], fmt.Sprintf("%ds", end))
|
||||
if len(part[1]) > 0 {
|
||||
cmds = append(cmds, "set", part[0], "boot", "on")
|
||||
}
|
||||
err := exec.Command(cmds[0], cmds[1:]...).Run()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
if len(part[6]) > 0 {
|
||||
err := ResizePartitionFs(part[7], part[6])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FsckExtFs(fpath string) bool {
|
||||
cmd := []string{"e2fsck", "-f", "-p", fpath}
|
||||
if err := exec.Command(cmd[0], cmd[1:]...).Run(); err != nil {
|
||||
log.Errorln(err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func FsckXfsFs(fpath string) bool {
|
||||
if err := exec.Command("xfs_check", fpath).Run(); err != nil {
|
||||
log.Errorln(err)
|
||||
exec.Command("xfs_repair", fpath).Run()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func ResizePartitionFs(fpath, fs string) error {
|
||||
if len(fs) == 0 {
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
cmds = [][]string{}
|
||||
uuids = GetDevUuid(fpath)
|
||||
)
|
||||
if strings.HasPrefix(fs, "linux-swap") {
|
||||
if v, ok := uuids["UUID"]; ok {
|
||||
cmds = [][]string{[]string{"mkswap", "-U", v, fpath}}
|
||||
} else {
|
||||
cmds = [][]string{[]string{"mkswap", fpath}}
|
||||
}
|
||||
} else if strings.HasPrefix(fs, "ext") {
|
||||
if !FsckExtFs(fpath) {
|
||||
return fmt.Errorf("Failed to fsck ext fs %s", fpath)
|
||||
}
|
||||
cmds = [][]string{[]string{"resize2fs", fpath}}
|
||||
} else if fs == "xfs" {
|
||||
var tmpPoint = fmt.Sprintf("/tmp/%s", strings.Replace(fpath, "/", "_", -1))
|
||||
if err := exec.Command("mountpoint", tmpPoint).Run(); err == nil {
|
||||
err = exec.Command("umount", "-f", tmpPoint).Run()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
FsckXfsFs(fpath)
|
||||
cmds = [][]string{[]string{"mkdir", "-p", tmpPoint},
|
||||
[]string{"mount", fpath, tmpPoint},
|
||||
[]string{"sleep", "2"},
|
||||
[]string{"xfs_growfs", tmpPoint},
|
||||
[]string{"sleep", "2"},
|
||||
[]string{"umount", tmpPoint},
|
||||
[]string{"sleep", "2"},
|
||||
[]string{"rm", "-fr", tmpPoint}}
|
||||
}
|
||||
|
||||
if len(cmds) > 0 {
|
||||
for _, cmd := range cmds {
|
||||
err := exec.Command(cmd[0], cmd[1:]...).Run()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetDevUuid(dev string) map[string]string {
|
||||
lines, err := exec.Command("blkid", dev).Output()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, l := range strings.Split(string(lines), "\n") {
|
||||
if strings.HasPrefix(l, dev) {
|
||||
var ret = map[string]string{}
|
||||
for _, part := range strings.Split(l, " ") {
|
||||
data := strings.Split(part, "=")
|
||||
if len(data) == 2 && strings.HasSuffix(data[0], "UUID") {
|
||||
if data[1][0] == '"' || data[1][0] == '\'' {
|
||||
ret[data[0]] = data[1][1 : len(data[1])-1]
|
||||
} else {
|
||||
ret[data[0]] = data[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package fstabutils // import "yunion.io/x/onecloud/pkg/util/fstabutils"
|
||||
@@ -0,0 +1 @@
|
||||
package fuseutils // import "yunion.io/x/onecloud/pkg/util/fuseutils"
|
||||
@@ -0,0 +1 @@
|
||||
package netutils2 // import "yunion.io/x/onecloud/pkg/util/netutils2"
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
"yunion.io/x/onecloud/pkg/util/regutils2"
|
||||
)
|
||||
|
||||
var PSEUDO_VIP = "169.254.169.231"
|
||||
@@ -25,6 +26,17 @@ var PRIVATE_PREFIXES = []string{
|
||||
"192.168.0.0/16",
|
||||
}
|
||||
|
||||
func IsTcpPortUsed(addr string, port int) bool {
|
||||
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", addr, port))
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
return true
|
||||
} else {
|
||||
log.Infof("IsTcpPortUsed: %s %d %s", addr, port, err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func GetPrivatePrefixes(privatePrefixes []string) []string {
|
||||
if privatePrefixes != nil {
|
||||
return privatePrefixes
|
||||
@@ -238,22 +250,6 @@ func GetSecretInterfaceAddress() (string, []byte) {
|
||||
return addr, SECRET_MASK
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses url with the given regular expression and returns the
|
||||
* group values defined in the expression.
|
||||
*/
|
||||
func getParams(compRegEx *regexp.Regexp, url string) map[string]string {
|
||||
match := compRegEx.FindStringSubmatch(url)
|
||||
|
||||
paramsMap := make(map[string]string, 0)
|
||||
for i, name := range compRegEx.SubexpNames() {
|
||||
if i > 0 && i <= len(match) {
|
||||
paramsMap[name] = match[i]
|
||||
}
|
||||
}
|
||||
return paramsMap
|
||||
}
|
||||
|
||||
func (n *SNetInterface) GetRoutes(gwOnly bool) [][]string {
|
||||
output, err := exec.Command("route", "-n").Output()
|
||||
if err != nil {
|
||||
@@ -268,7 +264,7 @@ func (n *SNetInterface) getRoutes(gwOnly bool, outputs []string) [][]string {
|
||||
|
||||
var res [][]string = make([][]string, 0)
|
||||
for _, line := range outputs {
|
||||
m := getParams(re, line)
|
||||
m := regutils2.GetParams(re, line)
|
||||
if len(m) > 0 && (!gwOnly || m["gw"] != "0.0.0.0") {
|
||||
res = append(res, []string{m["dest"], m["gw"], m["mask"]})
|
||||
}
|
||||
@@ -280,7 +276,7 @@ func (n *SNetInterface) getAddresses(output []string) [][]string {
|
||||
var addrs = make([][]string, 0)
|
||||
re := regexp.MustCompile(`inet (?P<addr>[0-9.]+)/(?P<mask>[0-9]+) `)
|
||||
for _, line := range output {
|
||||
m := getParams(re, line)
|
||||
m := regutils2.GetParams(re, line)
|
||||
if len(m) > 0 {
|
||||
addrs = append(addrs, []string{m["addr"], m["mask"]})
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package regutils2 // import "yunion.io/x/onecloud/pkg/util/regutils2"
|
||||
@@ -0,0 +1,19 @@
|
||||
package regutils2
|
||||
|
||||
import "regexp"
|
||||
|
||||
/**
|
||||
* Parses val with the given regular expression and returns the
|
||||
* group values defined in the expression.
|
||||
*/
|
||||
func GetParams(compRegEx *regexp.Regexp, val string) map[string]string {
|
||||
match := compRegEx.FindStringSubmatch(val)
|
||||
|
||||
paramsMap := make(map[string]string, 0)
|
||||
for i, name := range compRegEx.SubexpNames() {
|
||||
if i > 0 && i <= len(match) {
|
||||
paramsMap[name] = match[i]
|
||||
}
|
||||
}
|
||||
return paramsMap
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package timeutils2 // import "yunion.io/x/onecloud/pkg/util/timeutils2"
|
||||
Reference in New Issue
Block a user