From 02835fcf2e7d28e92752e90bb26f24ed048b227d Mon Sep 17 00:00:00 2001 From: wanyaoqi Date: Wed, 19 Dec 2018 11:07:38 +0800 Subject: [PATCH] temp commit --- pkg/hostman/guestfs/core.go | 2 + pkg/hostman/guestfs/linux.go | 94 ++++++++++++++++++++++++-- pkg/hostman/guestfs/localfs.go | 5 +- pkg/hostman/utils.go | 117 +++++++++++++++++++++++++++++++++ 4 files changed, 210 insertions(+), 8 deletions(-) diff --git a/pkg/hostman/guestfs/core.go b/pkg/hostman/guestfs/core.go index e6f183357d..e5c0cc2e62 100644 --- a/pkg/hostman/guestfs/core.go +++ b/pkg/hostman/guestfs/core.go @@ -75,6 +75,8 @@ type IRootFsDriver interface { CommitChanges() error DeployGuestFs(IRootFsDriver, *jsonutils.JSONDict, *SDeployInfo) (jsonutils.JSONObject, error) + + // PrepareFsForTemplate() error } type SGuestRootFsDriver struct { diff --git a/pkg/hostman/guestfs/linux.go b/pkg/hostman/guestfs/linux.go index 11a37cfae5..5743c076fc 100644 --- a/pkg/hostman/guestfs/linux.go +++ b/pkg/hostman/guestfs/linux.go @@ -21,7 +21,7 @@ type SLinuxRootFs struct { } func NewLinuxRootFs(part *SKVMGuestDiskPartition) IRootFsDriver { - return &SAndroidRootFs{SGuestRootFsDriver: NewGuestRootFsDriver(part).(*SGuestRootFsDriver)} + return &SLinuxRootFs{SGuestRootFsDriver: NewGuestRootFsDriver(part).(*SGuestRootFsDriver)} } func (l *SLinuxRootFs) String() string { @@ -260,14 +260,16 @@ func (l *SLinuxRootFs) GetArch() string { } } -func (l *SLinuxRootFs) PrepareFsForTemplate() { +func (l *SLinuxRootFs) PrepareFsForTemplate() error { // clean /etc/fstab if l.rootFs.Exists("/etc/fstab", false) { fstabcont, _ := l.rootFs.FileGetContents("/etc/fstab", false) fstab := fstabutils.FSTabFile(string(fstabcont)) fstab.RemoveDevices(1) cf := fstab.ToConf() - l.rootFs.FilePutContents("/etc/fstab", cf, false, false) + if err := l.rootFs.FilePutContents("/etc/fstab", cf, false, false); err != nil { + return err + } } // rm /etc/ssh/*_key.* if l.rootFs.Exists("/etc/ssh", false) { @@ -279,7 +281,9 @@ func (l *SLinuxRootFs) PrepareFsForTemplate() { } // clean cloud-init if l.rootFs.Exists("/var/lib/cloud", false) { - l.rootFs.Cleandir("/var/lib/cloud", false, false) + if err := l.rootFs.Cleandir("/var/lib/cloud", false, false); err != nil { + return err + } } cloudDisableFile := "/etc/cloud/cloud-init.disabled" if l.rootFs.Exists(cloudDisableFile, false) { @@ -288,19 +292,36 @@ func (l *SLinuxRootFs) PrepareFsForTemplate() { // clean /tmp /var/log /var/cache /var/spool /var/run for _, dir := range []string{"/tmp", "/var/tmp"} { if l.rootFs.Exists(dir, false) { - l.rootFs.Cleandir(dir, false, false) + if err := l.rootFs.Cleandir(dir, false, false); err != nil { + return err + } } } for _, dir := range []string{"/var/log", "/var/cache", "/usr/local/var/log", "/usr/local/var/cache"} { if l.rootFs.Exists(dir, false) { - l.rootFs.Zerofiles(dir, false) + if err := l.rootFs.Zerofiles(dir, false); err != nil { + return err + } } } for _, dir := range []string{"/var/spool", "/var/run", "/run", "/usr/local/var/spool", "/usr/local/var/run"} { if l.rootFs.Exists(dir, false) { - l.rootFs.Cleandir(dir, true, true) + if err := l.rootFs.Cleandir(dir, true, true); err != nil { + return err + } } } + return nil +} + +func (l *SLinuxRootFs) GetSerialPorts() []string { + var confpath = "/proc/tty/driver/serial" + if l.rootFs.SupportOsPathExists() { + // TODO: with sshpart utils + return nil + } else { + return nil + } } type SDebianLikeRootFs struct { @@ -311,6 +332,65 @@ func NewDebianLikeRootFs(part *SKVMGuestDiskPartition) IRootFsDriver { return &SDebianLikeRootFs{SLinuxRootFs: NewLinuxRootFs(part).(*SLinuxRootFs)} } +func (d *SDebianLikeRootFs) RootSignatures() []string { + sig := d.SLinuxRootFs.RootSignatures() + return append([]string{"/etc/hostname"}, sig...) +} + +func (d *SDebianLikeRootFs) DeployHostname(hn, domain string) error { + return d.rootFs.FilePutContents("/etc/hostname", hn, false, false) +} + +func (d *SDebianLikeRootFs) DeployNetworkingScripts(nics []jsonutils.JSONObject) error { + if err := d.SLinuxRootFs.DeployNetworkingScripts(nics); err != nil { + return err + } + fn := "/etc/network/interfaces" + cmds := "" + cmds += "auto lo\n" + cmds += "iface lo inet loopback\n\n" + mainNic, err := hostman.GetMainNic(nics) + if err != nil { + return err + } + var mainIp string + if mainNic != nil { + mainIp, _ := mainNic.GetString("ip") + } + for _, nic := range nics { + nicIdx, err := nic.Int("index") + if err != nil { + return err + } + cmds += fmt.Sprintf("auto eth%d\n", nicIdx) + if jsonutils.QueryBoolean(nic, "virtual", false) { + cmds += fmt.Sprintf("iface eth%d inet static\n", nicIdx) + cmds += fmt.Sprintf(" address %s\n", hostman.PSEUDO_VIP) + cmds += " netmask 255.255.255.255\n" + cmds += "\n" + } else if jsonutils.QueryBoolean(nic, "manual", false) { + masklen, err := nic.Int("masklen") + if err != nil { + return err + } + netmask := hostman.Netlen2Mask(masklen) + ip, err := nic.GetString("ip") + if err != nil { + return err + } + cmds += fmt.Sprintf("iface eth%d inet static\n", nicIdx) + cmds += fmt.Sprintf(" address %s\n", ip) + cmds += fmt.Sprintf(" netmask %s\n", netmask) + if nic.Contains("gateway") && ip == mainIp { + gateway, _ := nic.GetString("gateway") + cmds += fmt.Sprintf(" gateway %s\n", gateway) + } + var routes = make([]string, 0) + hostman.AddNicRoutes(routes, nic, mainIp, len(nics)) + } + } +} + type SDebianRootFs struct { *SDebianLikeRootFs } diff --git a/pkg/hostman/guestfs/localfs.go b/pkg/hostman/guestfs/localfs.go index 0eca5bcb45..f083dcc357 100644 --- a/pkg/hostman/guestfs/localfs.go +++ b/pkg/hostman/guestfs/localfs.go @@ -21,6 +21,10 @@ type SLocalGuestFS struct { readOnly bool } +func (f *SLocalGuestFS) SupportOsPathExists() bool { + return false +} + func (f *SLocalGuestFS) IsReadonly() bool { log.Infof("Test if read-only fs ...") var filename = fmt.Sprint("./%f", rand.Float32()) @@ -122,7 +126,6 @@ func (f *SLocalGuestFS) Cleandir(dir string, keepdir, caseInsensitive bool) erro func (f *SLocalGuestFS) Zerofiles(dir string, caseInsensitive bool) error { sPath := f.getLocalPath(dir, caseInsensitive) if len(sPath) > 0 { - //写到这里了。。。 return hostman.Zerofiles(sPath) } return fmt.Errorf("No such file %s", sPath) diff --git a/pkg/hostman/utils.go b/pkg/hostman/utils.go index f81c43e0c6..66931a1246 100644 --- a/pkg/hostman/utils.go +++ b/pkg/hostman/utils.go @@ -11,7 +11,9 @@ import ( "strings" "time" + "yunion.io/x/jsonutils" "yunion.io/x/log" + "yunion.io/x/pkg/util/netutils" ) // timer utils @@ -62,6 +64,37 @@ func Cleandir(sPath string, keepdir bool) error { return nil } +// TODO: test +func Zerofiles(sPath string) error { + f, err := os.Lstat(sPath) + switch { + case err != nil: + return err + case f.Mode()&os.ModeSymlink == os.ModeSymlink: + // islink + return nil + case f.Mode().IsRegular(): + return FilePutContents(sPath, "", false) + case f.Mode().IsDir(): + files, err := ioutil.ReadDir(sPath) + if err != nil { + return err + } + for _, file := range files { + if file.Mode()&os.ModeSymlink == os.ModeSymlink { + continue + } else if file.Mode().IsRegular() { + if err := FilePutContents(path.Join(sPath, file.Name()), "", false); err != nil { + return err + } + } else if file.Mode().IsDir() { + return Zerofiles(path.Join(sPath, file.Name())) + } + } + } + return nil +} + func FilePutContents(filename string, content string, modAppend bool) error { var mode = os.O_WRONLY | os.O_CREATE if modAppend { @@ -217,3 +250,87 @@ func (hf HostsFile) String() string { } return ret } + +//net utils +var PSEUDO_VIP = "169.254.169.231" +var MASKS = []string{"0", "128", "192", "224", "240", "248", "252", "254", "255"} + +func GetMainNic(nics []jsonutils.JSONObject) (jsonutils.JSONObject, error) { + var mainIp netutils.IPV4Addr + var mainNic jsonutils.JSONObject + for _, n := range nics { + if n.Contains("gateway") { + ip, _ := n.GetString("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 Netlen2Mask(netmasklen int64) string { + var mask = "" + var segCnt = 0 + for netmasklen > 0 { + var m string + if netmasklen > 8 { + m = MASKS[8] + netmasklen -= 8 + } else { + m = MASKS[netmasklen] + } + if mask != "" { + mask += "." + } + mask += m + segCnt += 1 + } + for i := 0; i < (4 - segCnt); i++ { + if mask != "" { + mask += "." + } + mask += "0" + } + return mask +} + +func addRoute(routes []string, net, gw string) { + for _, rt := range routes { + // if rt???? 有问题 + } +} + +func extendRoutes(routes []string, nicRoutes []jsonutils.JSONObject) error { + for i := 0; i < len(nicRoutes); i++ { + rt, ok := nicRoutes[i].(*jsonutils.JSONArray) + if !ok { + return fmt.Errorf("Nic routes format error") + } + // 写到这里了 + rts := rt.GetStringArray() + if len(rts) < 2 { + return fmt.Errorf("Nic routes count error") + } + addRoute(routes, rts[0], rts[1]) + } +} + +func AddNicRoutes(routes []string, nic jsonutils.JSONObject, mainIp string, nicCnt int) []string { + ip, _ := nic.GetString("ip") + if mainIp == ip { + return routes + } + if nic.Contains("routes") { + nicRoutes, _ := nic.GetArray("routes") + extendRoutes(routes, nicRoutes) + } +}