| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496 |
- // 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 fsdriver
- import (
- "debug/elf"
- "fmt"
- "os"
- "path"
- "path/filepath"
- "regexp"
- "strconv"
- "strings"
- "syscall"
- "gopkg.in/yaml.v2"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/utils"
- "yunion.io/x/onecloud/pkg/apis"
- api "yunion.io/x/onecloud/pkg/apis/compute"
- "yunion.io/x/onecloud/pkg/cloudcommon/consts"
- "yunion.io/x/onecloud/pkg/cloudcommon/types"
- 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"
- "yunion.io/x/onecloud/pkg/util/netutils2"
- "yunion.io/x/onecloud/pkg/util/procutils"
- "yunion.io/x/onecloud/pkg/util/pwquality"
- "yunion.io/x/onecloud/pkg/util/seclib2"
- "yunion.io/x/onecloud/pkg/util/sysutils"
- )
- const (
- ROOT_USER = "root"
- YUNIONROOT_USER = "cloudroot"
- TELEGRAF_BINARY_PATH = "/opt/yunion/bin/telegraf"
- SUPERVISE_BINARY_PATH = "/opt/yunion/bin/supervise"
- QGA_BINARY_PATH = "/opt/yunion/bin/qemu-ga"
- QGA_WIN_MSI_INSTALLER_PATH = "/opt/yunion/bin/qemu-ga-x86_64.msi"
- )
- var (
- NetDevPrefix = "eth"
- NetDevPrefixEN = "en"
- IBNetDevPrefix = "ib"
- )
- func GetNetDevPrefix(nics []*types.SServerNic) string {
- if NicsHasDifferentDriver(nics) {
- return NetDevPrefixEN
- } else {
- return NetDevPrefix
- }
- }
- func GetIBNetDevPrefix() string {
- return IBNetDevPrefix
- }
- func NicsHasDifferentDriver(nics []*types.SServerNic) bool {
- m := make(map[string]int)
- for i := 0; i < len(nics); i++ {
- if _, ok := m[nics[i].Driver]; !ok {
- m[nics[i].Driver] = 1
- }
- }
- if len(m) > 1 {
- return true
- }
- return false
- }
- type sLinuxRootFs struct {
- *sGuestRootFsDriver
- }
- func newLinuxRootFs(part IDiskPartition) *sLinuxRootFs {
- return &sLinuxRootFs{
- sGuestRootFsDriver: newGuestRootFsDriver(part),
- }
- }
- func (l *sLinuxRootFs) RootSignatures() []string {
- return []string{"/bin", "/etc", "/boot", "/lib", "/usr"}
- }
- func getHostname(hostname, domain string) string {
- if len(domain) > 0 {
- return fmt.Sprintf("%s.%s", hostname, domain)
- } else {
- return hostname
- }
- }
- func (l *sLinuxRootFs) DeployQgaService(rootFs IDiskPartition) error {
- qemuGuestAgentPath := "/usr/bin/qemu-ga"
- if rootFs.Exists(qemuGuestAgentPath, false) {
- // qemu-ga has been installed
- return nil
- }
- output, err := procutils.NewCommand("cp", "-f",
- QGA_BINARY_PATH, path.Join(rootFs.GetMountPath(), qemuGuestAgentPath)).Output()
- if err != nil {
- return errors.Wrapf(err, "cp qga binary failed %s", output)
- }
- if l.isSupportSystemd() {
- udevPath := "/etc/udev/rules.d/"
- if rootFs.Exists(udevPath, false) {
- rules := rootFs.ListDir(udevPath, false)
- for _, rule := range rules {
- if strings.Index(rule, "qemu-guest-agent.rules") > 0 {
- rootFs.Remove(path.Join(udevPath, rule), false)
- }
- }
- qgaRules := `SUBSYSTEM=="virtio-ports", ATTR{name}=="org.qemu.guest_agent.0", \
- TAG+="systemd" ENV{SYSTEMD_WANTS}="qemu-guest-agent.service"` + "\n"
- if err := rootFs.FilePutContents(path.Join(udevPath, "99-qemu-guest-agent.rules"), qgaRules, false, false); err != nil {
- return err
- }
- }
- if err := l.InstallQemuGuestAgentSystemd(); err != nil {
- return errors.Wrap(err, "qga InstallQemuGuestAgentSystemd")
- }
- } else {
- initCmd := qemuGuestAgentPath
- if err := l.installCrond(initCmd); err != nil {
- return errors.Wrap(err, "qga installCrond")
- }
- }
- return nil
- }
- func (l *sLinuxRootFs) DeployQgaBlackList(rootFs IDiskPartition) error {
- var modeRwxOwner = syscall.S_IRUSR | syscall.S_IWUSR | syscall.S_IXUSR
- var qgaConfDir = "/etc/sysconfig"
- var etcSysconfigQemuga = path.Join(qgaConfDir, "qemu-ga")
- if err := rootFs.Mkdir(qgaConfDir, modeRwxOwner, false); err != nil {
- return errors.Wrap(err, "mkdir qga conf dir")
- }
- blackListContent := `# This is a systemd environment file, not a shell script.
- # It provides settings for \"/lib/systemd/system/qemu-guest-agent.service\".
- # Comma-separated blacklist of RPCs to disable, or empty list to enable all.
- #
- # You can get the list of RPC commands using \"qemu-ga --blacklist='?'\".
- # There should be no spaces between commas and commands in the blacklist.
- # BLACKLIST_RPC=guest-file-open,guest-file-close,guest-file-read,guest-file-write,guest-file-seek,guest-file-flush,guest-exec,guest-exec-status
- # Fsfreeze hook script specification.
- #
- # FSFREEZE_HOOK_PATHNAME=/dev/null : disables the feature.
- #
- # FSFREEZE_HOOK_PATHNAME=/path/to/executable : enables the feature with the
- # specified binary or shell script.
- #
- # FSFREEZE_HOOK_PATHNAME= : enables the feature with the
- # default value (invoke \"qemu-ga --help\" to interrogate).
- FSFREEZE_HOOK_PATHNAME=/etc/qemu-ga/fsfreeze-hook"
- `
- if err := rootFs.FilePutContents(etcSysconfigQemuga, blackListContent, false, false); err != nil {
- return errors.Wrap(err, "etcSysconfigQemuga error")
- }
- return nil
- }
- func (l *sLinuxRootFs) DeployHosts(rootFs IDiskPartition, hostname, domain string, ips []string) error {
- var etcHosts = "/etc/hosts"
- var oldHostFile string
- if rootFs.Exists(etcHosts, false) {
- oldhf, err := rootFs.FileGetContents(etcHosts, false)
- if err != nil {
- return err
- }
- oldHostFile = string(oldhf)
- }
- return rootFs.FilePutContents(etcHosts, fileutils2.FormatHostsFile(oldHostFile, ips, hostname, getHostname(hostname, domain)), false, false)
- }
- func (l *sLinuxRootFs) GetLoginAccount(rootFs IDiskPartition, sUser string, defaultRootUser bool, windowsDefaultAdminUser bool) (string, error) {
- if len(sUser) > 0 {
- if _, err := rootFs.CheckOrAddUser(sUser, "", false); err != nil && !strings.Contains(err.Error(), "already exists") {
- return "", fmt.Errorf("UserAdd %s: %v", sUser, err)
- }
- if err := l.EnableUserSudo(rootFs, sUser); err != nil {
- return "", fmt.Errorf("EnableUserSudo: %s", err)
- }
- return sUser, nil
- }
- var selUsr string
- if defaultRootUser && rootFs.Exists("/root", false) && l.GetIRootFsDriver().AllowAdminLogin() {
- selUsr = ROOT_USER
- } else {
- usrs := rootFs.ListDir("/home", false)
- for _, usr := range usrs {
- if usr == YUNIONROOT_USER {
- continue
- }
- if len(selUsr) == 0 || len(selUsr) > len(usr) {
- selUsr = usr
- }
- }
- if len(selUsr) == 0 && rootFs.Exists("/root", false) {
- selUsr = ROOT_USER
- }
- }
- return selUsr, nil
- }
- func (l *sLinuxRootFs) checkInputPasswd(rootFs IDiskPartition, config *pwquality.Config, account, gid, publicKey, password string) string {
- if config == nil {
- return password
- }
- err := config.Validate(password, account)
- if err != nil && errors.Cause(err) == pwquality.ErrPasswordTooWeak {
- log.Infof("password %s too weak, try regenerate password", password)
- npassword := config.GeneratePassword(seclib2.RandomPassword2)
- if len(npassword) > 0 {
- log.Infof("regenerate password %s", npassword)
- password = npassword
- }
- }
- return password
- }
- func (l *sLinuxRootFs) ChangeUserPasswd(rootFs IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error) {
- var secret string
- var err error
- err = rootFs.Passwd(account, password, false)
- if err == nil {
- if len(publicKey) > 0 {
- secret, err = seclib2.EncryptBase64(publicKey, password)
- } else {
- secret, err = utils.EncryptAESBase64(gid, password)
- }
- if err != nil {
- return "", errors.Wrap(err, "Encryption")
- }
- // put /.autorelabel if selinux enabled
- err = rootFs.FilePutContents("/.autorelabel", "", false, false)
- if err != nil {
- return "", errors.Wrap(err, "fail to put .autorelabel")
- }
- } else {
- return "", fmt.Errorf("ChangeUserPasswd error: %v", err)
- }
- return secret, err
- }
- func (l *sLinuxRootFs) DeployPublicKey(rootFs IDiskPartition, selUsr string, pubkeys *deployapi.SSHKeys) error {
- var usrDir string
- if selUsr == "root" {
- usrDir = "/root"
- } else {
- usrDir = path.Join("/home", selUsr)
- }
- return DeployAuthorizedKeys(rootFs, usrDir, pubkeys, false, false)
- }
- func (l *sLinuxRootFs) DeployYunionroot(rootFs IDiskPartition, pubkeys *deployapi.SSHKeys, isInit, enableCloudInit bool) error {
- if !consts.AllowVmSELinux() {
- l.DisableSelinux(rootFs)
- }
- if !enableCloudInit && isInit {
- l.DisableCloudinit(rootFs)
- }
- var yunionroot = YUNIONROOT_USER
- var rootdir string // := path.Join(cloudrootDirectory, yunionroot)
- var err error
- if rootdir, err = rootFs.CheckOrAddUser(yunionroot, cloudrootDirectory, true); err != nil {
- return errors.Wrap(err, "unable to CheckOrAddUser")
- }
- log.Infof("DeployYunionroot %s home %s", yunionroot, rootdir)
- err = DeployAuthorizedKeys(rootFs, rootdir, pubkeys, true, true)
- if err != nil {
- log.Infof("DeployAuthorizedKeys error: %s", err.Error())
- return fmt.Errorf("DeployAuthorizedKeys: %v", err)
- }
- if err := l.EnableUserSudo(rootFs, yunionroot); err != nil {
- return fmt.Errorf("EnableUserSudo: %v", err)
- }
- return nil
- }
- func (l *sLinuxRootFs) EnableUserSudo(rootFs IDiskPartition, user string) error {
- var sudoDir = "/etc/sudoers.d"
- var content = fmt.Sprintf("%s ALL=(ALL) NOPASSWD:ALL\n", user)
- if rootFs.Exists(sudoDir, false) {
- filepath := path.Join(sudoDir, fmt.Sprintf("90-%s-users", user))
- err := rootFs.FilePutContents(filepath, content, false, false)
- if err != nil {
- return fmt.Errorf("Write contents to %s: %v", filepath, err)
- }
- return rootFs.Chmod(filepath, syscall.S_IRUSR|syscall.S_IRGRP, false)
- }
- return nil
- }
- func (l *sLinuxRootFs) DisableSelinux(rootFs IDiskPartition) {
- selinuxConfig := "/etc/selinux/config"
- content := `# This file controls the state of SELinux on the system.
- # SELINUX= can take one of these three values:
- # enforcing - SELinux security policy is enforced.
- # permissive - SELinux prints warnings instead of enforcing.
- # disabled - No SELinux policy is loaded.
- SELINUX=disabled
- # SELINUXTYPE= can take one of three two values:
- # targeted - Targeted processes are protected,
- # minimum - Modification of targeted policy. Only selected processes are protected.
- # mls - Multi Level Security protection.
- SELINUXTYPE=targeted
- `
- if rootFs.Exists(selinuxConfig, false) {
- if err := rootFs.FilePutContents(selinuxConfig, content, false, false); err != nil {
- log.Errorf("DisableSelinux error: %v", err)
- }
- }
- }
- func (l *sLinuxRootFs) DisableCloudinit(rootFs IDiskPartition) {
- cloudDir := "/etc/cloud"
- cloudDisableFile := "/etc/cloud/cloud-init.disabled"
- if rootFs.Exists(cloudDir, false) {
- if err := rootFs.FilePutContents(cloudDisableFile, "", false, false); err != nil {
- log.Errorf("DisableCloudinit error: %v", err)
- }
- }
- }
- func (l *sLinuxRootFs) DeployFstabScripts(rootFs IDiskPartition, disks []*deployapi.Disk) error {
- fstabcont, err := rootFs.FileGetContents("/etc/fstab", false)
- if err != nil {
- return err
- }
- var dataDiskIdx = 0
- var rec string
- var modeRwxOwner = syscall.S_IRUSR | syscall.S_IWUSR | syscall.S_IXUSR
- var fstab = fstabutils.FSTabFile(string(fstabcont))
- if fstab != nil {
- fstab = fstab.RemoveDevices(len(disks))
- } else {
- _fstab := make(fstabutils.FsTab, 0)
- fstab = &_fstab
- }
- for i := 1; i < len(disks); i++ {
- diskId := disks[i].DiskId
- if len(diskId) == 0 {
- diskId = "None"
- }
- dev := fmt.Sprintf("UUID=%s", diskId)
- if !fstab.IsExists(dev) {
- 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].Mountpoint
- if len(mtPath) == 0 {
- mtPath = "/data"
- if dataDiskIdx > 0 {
- mtPath += fmt.Sprintf("%d", dataDiskIdx)
- }
- dataDiskIdx += 1
- }
- rec = fmt.Sprintf("%s %s %s defaults 2 2", dev, mtPath, fs)
- if !l.rootFs.Exists(mtPath, false) {
- if err := l.rootFs.Mkdir(mtPath, modeRwxOwner, false); err != nil {
- return err
- }
- }
- }
- fstab.AddFsrec(rec)
- }
- }
- }
- cf := fstab.ToConf()
- return rootFs.FilePutContents("/etc/fstab", cf, false, false)
- }
- func (l *sLinuxRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*types.SServerNic) error {
- netDevPrefix := GetNetDevPrefix(nics)
- log.Infof("netdev prefix: %s", netDevPrefix)
- udevPath := "/etc/udev/rules.d/"
- if rootFs.Exists(udevPath, false) {
- rules := rootFs.ListDir(udevPath, false)
- for _, rule := range rules {
- if strings.Index(rule, "persistent-net.rules") > 0 {
- rootFs.Remove(path.Join(udevPath, rule), false)
- } else if strings.Index(rule, "persistent-cd.rules") > 0 {
- if err := rootFs.FilePutContents(path.Join(udevPath, rule), "", false, false); err != nil {
- return err
- }
- }
- }
- var nicRules string
- for _, nic := range nics {
- nicRules += `KERNEL=="*", SUBSYSTEM=="net", ACTION=="add", `
- nicRules += `DRIVERS=="?*", `
- if nic.NicType == api.NIC_TYPE_INFINIBAND {
- nicRules += fmt.Sprintf(`ATTR{address}=="?*%s", ATTR{type}=="32", `, strings.ToLower(nic.Mac))
- nicRules += fmt.Sprintf("NAME=\"%s%d\"\n", GetIBNetDevPrefix(), nic.Index)
- } else {
- nicRules += fmt.Sprintf(`ATTR{address}=="%s", ATTR{type}=="1", `, strings.ToLower(nic.Mac))
- nicRules += fmt.Sprintf("NAME=\"%s%d\"\n", netDevPrefix, nic.Index)
- }
- }
- if err := rootFs.FilePutContents(path.Join(udevPath, "70-persistent-net.rules"), nicRules, false, false); err != nil {
- return err
- }
- var usbRules string
- usbRules = `SUBSYSTEM=="usb", ATTRS{idVendor}=="1d6b", ATTRS{idProduct}=="0001", `
- usbRules += "RUN+=" + `"/bin/sh -c \'echo enabled > /sys$env{DEVPATH}/../power/wakeup\'"` + "\n"
- if err := rootFs.FilePutContents(path.Join(udevPath,
- "90-usb-tablet-remote-wakeup.rules"), usbRules, false, false); err != nil {
- return err
- }
- }
- // deploy docker mtu
- {
- minMtu := int16(-1)
- for _, nic := range nics {
- if nic.Mtu > 0 && (minMtu > nic.Mtu || minMtu < 0) {
- minMtu = nic.Mtu
- }
- }
- const dockerDaemonConfPath = "/etc/docker/daemon.json"
- var daemonConfJson jsonutils.JSONObject
- if rootFs.Exists(dockerDaemonConfPath, false) {
- content, _ := rootFs.FileGetContents(dockerDaemonConfPath, false)
- if len(content) > 0 {
- daemonConfJson, _ = jsonutils.Parse(content)
- }
- } else {
- const modeRwxOwner = syscall.S_IRUSR | syscall.S_IWUSR | syscall.S_IXUSR
- if err := rootFs.Mkdir("/etc/docker", modeRwxOwner, false); err != nil {
- return errors.Wrap(err, "mkdir /etc/docker fail")
- }
- }
- if daemonConfJson == nil {
- daemonConfJson = jsonutils.NewDict()
- }
- daemonConfJson.(*jsonutils.JSONDict).Set("mtu", jsonutils.NewInt(int64(minMtu)))
- if err := rootFs.FilePutContents(dockerDaemonConfPath, daemonConfJson.PrettyString(), false, false); err != nil {
- return errors.Wrapf(err, "write %s fail", dockerDaemonConfPath)
- }
- }
- // deploy ssh host key
- {
- err := rootFs.GenerateSshHostKeys()
- if err != nil {
- // ignore error
- log.Errorf("rootFs.GenerateSshHostKeys fail %s", err)
- }
- }
- {
- // deploy /etc/gai.conf if both IPv4 and IPv6 are enabled
- v4Enabled := false
- v6Enabled := false
- for _, nic := range nics {
- if nic.Ip != "" {
- v4Enabled = true
- }
- if nic.Ip6 != "" {
- v6Enabled = true
- }
- if v4Enabled && v6Enabled {
- // prefer IPv4 over IPv6 by default of /etc/gai.conf not present
- if !rootFs.Exists("/etc/gai.conf", false) {
- rootFs.FilePutContents("/etc/gai.conf", "precedence ::ffff:0:0/96 100\n", false, false)
- }
- break
- }
- }
- }
- return nil
- }
- func (l *sLinuxRootFs) DeployStandbyNetworkingScripts(rootFs IDiskPartition, nics, nicsStandby []*types.SServerNic) error {
- var netDevPrefix = GetNetDevPrefix(nicsStandby)
- var udevPath = "/etc/udev/rules.d/"
- var nicRules string
- for _, nic := range nicsStandby {
- if len(nic.NicType) == 0 || nic.NicType != api.NIC_TYPE_IPMI {
- nicRules += `KERNEL=="*", SUBSYSTEM=="net", ACTION=="add", `
- nicRules += `DRIVERS=="?*", `
- mac := nic.Mac
- nicRules += fmt.Sprintf(`ATTR{address}=="%s", ATTR{type}=="1", `, strings.ToLower(mac))
- idx := nic.Index
- nicRules += fmt.Sprintf(`NAME="%s%d"\n`, netDevPrefix, idx)
- }
- }
- if err := rootFs.FilePutContents(path.Join(udevPath, "70-persistent-net.rules"), nicRules, true, false); err != nil {
- return err
- }
- return nil
- }
- func (l *sLinuxRootFs) DeployUdevSubsystemScripts(rootFs IDiskPartition) error {
- udevPath := "/etc/udev/rules.d/"
- if rootFs.Exists(udevPath, false) {
- cpuMemHotplugRules := `SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}="1"
- SUBSYSTEM=="memory", ACTION=="add", TEST=="state", ATTR{state}=="offline", ATTR{state}="online"` + "\n"
- if err := rootFs.FilePutContents(path.Join(udevPath, "80-hotplug-cpu-mem.rules"), cpuMemHotplugRules, false, false); err != nil {
- return err
- }
- }
- return nil
- }
- func (l *sLinuxRootFs) GetOs() string {
- return "Linux"
- }
- func (l *sLinuxRootFs) GetArch(rootFs IDiskPartition) string {
- // search lib64 first
- for _, dir := range []string{"/usr/lib64", "/lib64", "/usr/lib", "/lib"} {
- if !rootFs.Exists(dir, false) {
- continue
- }
- files := rootFs.ListDir(dir, false)
- for i := 0; i < len(files); i++ {
- if strings.HasPrefix(files[i], "ld-") {
- p := rootFs.GetLocalPath(path.Join(dir, files[i]), false)
- fileInfo, err := os.Stat(p)
- if err != nil {
- log.Errorf("stat file %s: %s", p, err)
- continue
- }
- if fileInfo.IsDir() {
- continue
- }
- if fileInfo.Mode()&os.ModeSymlink != 0 {
- continue
- }
- rp, err := filepath.EvalSymlinks(p)
- if err != nil {
- log.Errorf("readlink of %s: %s", p, err)
- continue
- }
- elfHeader, err := elf.Open(rp)
- if err != nil {
- log.Errorf("failed read file elf %s: %s", rp, err)
- continue
- }
- defer elfHeader.Close()
- // https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header
- switch elfHeader.Machine {
- case elf.EM_X86_64:
- return apis.OS_ARCH_X86_64
- case elf.EM_386:
- return apis.OS_ARCH_X86_32
- case elf.EM_AARCH64:
- return apis.OS_ARCH_AARCH64
- case elf.EM_ARM:
- return apis.OS_ARCH_AARCH32
- case elf.EM_RISCV:
- if elfHeader.Class == elf.ELFCLASS32 {
- return apis.OS_ARCH_RISCV32
- }
- return apis.OS_ARCH_RISCV64
- }
- }
- }
- }
- return apis.OS_ARCH_X86_64
- }
- func (l *sLinuxRootFs) PrepareFsForTemplate(rootFs IDiskPartition) error {
- // clean /etc/fstab
- if rootFs.Exists("/etc/fstab", false) {
- fstabcont, _ := rootFs.FileGetContents("/etc/fstab", false)
- fstab := fstabutils.FSTabFile(string(fstabcont))
- var cf string
- if fstab != nil {
- fstab = fstab.RemoveDevices(1)
- cf = fstab.ToConf()
- }
- if err := rootFs.FilePutContents("/etc/fstab", cf, false, false); err != nil {
- return err
- }
- }
- // rm /etc/ssh/*_key.*
- if rootFs.Exists("/etc/ssh", false) {
- for _, f := range l.rootFs.ListDir("/etc/ssh", false) {
- if strings.HasSuffix(f, "_key") || strings.HasSuffix(f, "_key.pub") {
- rootFs.Remove("/etc/ssh/"+f, false)
- }
- }
- }
- // clean cloud-init
- if rootFs.Exists("/var/lib/cloud", false) {
- if err := rootFs.Cleandir("/var/lib/cloud", false, false); err != nil {
- return err
- }
- }
- cloudDisableFile := "/etc/cloud/cloud-init.disabled"
- if rootFs.Exists(cloudDisableFile, false) {
- rootFs.Remove(cloudDisableFile, false)
- }
- // clean /tmp /var/log /var/cache /var/spool /var/run
- for _, dir := range []string{"/tmp", "/var/tmp"} {
- if rootFs.Exists(dir, false) {
- if err := 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 rootFs.Exists(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",
- "/etc/openvswitch",
- } {
- if rootFs.Exists(dir, false) {
- if err := rootFs.Cleandir(dir, true, true); err != nil {
- return err
- }
- }
- }
- return nil
- }
- func (l *sLinuxRootFs) getSerialPorts(rootFs IDiskPartition) []string {
- if !rootFs.SupportSerialPorts() {
- return nil
- }
- // XXX HACK, only sshpart.SSHPartition support this
- var confpath = "/proc/tty/driver/serial"
- content, err := rootFs.FileGetContentsByPath(confpath)
- if err != nil {
- log.Errorf("Get %s error: %v", confpath, err)
- return nil
- }
- ttys := sysutils.GetSerialPorts(strings.Split(string(content), "\n"))
- log.Infof("Get serial ports content:\n%s, find serial ttys: %#v", string(content), ttys)
- return ttys
- }
- func (l *sLinuxRootFs) enableSerialConsoleInitCentos(rootFs IDiskPartition) error {
- // http://www.jonno.org/drupal/node/10
- var err error
- for _, tty := range l.getSerialPorts(rootFs) {
- content := fmt.Sprintf(
- `stop on runlevel [016]
- start on runlevel [345]
- instance %s
- respawn
- pre-start exec /sbin/securetty %s
- exec /sbin/agetty /dev/%s 115200 vt100`, tty, tty, tty)
- err = rootFs.FilePutContents(fmt.Sprintf("/etc/init/%s.conf", tty), content, false, false)
- }
- return err
- }
- func (l *sLinuxRootFs) enableSerialConsoleRootLogin(rootFs IDiskPartition, tty string) error {
- secureTTYFile := "/etc/securetty"
- content, err := rootFs.FileGetContents(secureTTYFile, false)
- if err != nil {
- return errors.Wrapf(err, "get contents of %s", secureTTYFile)
- }
- secureTTYs := sysutils.GetSecureTTYs(strings.Split(string(content), "\n"))
- if utils.IsInStringArray(tty, secureTTYs) {
- return nil
- }
- return rootFs.FilePutContents(secureTTYFile, fmt.Sprintf("\n%s", tty), true, false)
- }
- func (l *sLinuxRootFs) enableSerialConsoleInit(rootFs IDiskPartition) error {
- // https://help.ubuntu.com/community/SerialConsoleHowto
- var err error
- for _, tty := range l.getSerialPorts(rootFs) {
- if err := l.enableSerialConsoleRootLogin(rootFs, tty); err != nil {
- log.Errorf("Enable %s root login: %v", tty, err)
- }
- content := fmt.Sprintf(
- `start on stopped rc or RUNLEVEL=[12345]
- stop on runlevel [!12345]
- respawn
- exec /sbin/getty -L 115200 %s vt102`, tty)
- err = rootFs.FilePutContents(fmt.Sprintf("/etc/init/%s.conf", tty), content, false, false)
- }
- return err
- }
- func (l *sLinuxRootFs) disableSerialConsoleInit(rootFs IDiskPartition) {
- for _, tty := range l.getSerialPorts(rootFs) {
- path := fmt.Sprintf("/etc/init/%s.conf", tty)
- if rootFs.Exists(path, false) {
- rootFs.Remove(path, false)
- }
- }
- }
- func (l *sLinuxRootFs) enableSerialConsoleSystemd(rootFs IDiskPartition) error {
- for _, tty := range l.getSerialPorts(rootFs) {
- if err := l.enableSerialConsoleRootLogin(rootFs, tty); err != nil {
- log.Errorf("Enable %s root login: %v", tty, err)
- }
- sPath := fmt.Sprintf("/etc/systemd/system/getty.target.wants/getty@%s.service", tty)
- if err := rootFs.Symlink("/usr/lib/systemd/system/getty@.service", sPath, false); err != nil {
- return errors.Wrapf(err, "Symbol link tty %s", tty)
- }
- }
- return nil
- }
- func (l *sLinuxRootFs) disableSerialConsoleSystemd(rootFs IDiskPartition) {
- for _, tty := range l.getSerialPorts(rootFs) {
- sPath := fmt.Sprintf("/etc/systemd/system/getty.target.wants/getty@%s.service", tty)
- if rootFs.Exists(sPath, false) {
- rootFs.Remove(sPath, false)
- }
- }
- }
- func (l *sLinuxRootFs) dirWalk(part IDiskPartition, sPath string, wF func(path string, isDir bool) bool) bool {
- stat := part.Stat(sPath, false)
- if !stat.IsDir() {
- if wF(sPath, false) {
- return true
- }
- return false
- }
- if wF(sPath, true) {
- return true
- }
- for _, subPath := range part.ListDir(sPath, false) {
- if l.dirWalk(part, path.Join(sPath, subPath), wF) {
- return true
- }
- }
- return false
- }
- func (l *sLinuxRootFs) DetectIsUEFISupport(part IDiskPartition) bool {
- // ref: https://wiki.archlinux.org/title/EFI_system_partition#Check_for_an_existing_partition
- // To confirm this is the ESP, mount it and check whether it contains a directory named EFI,
- // if it does this is definitely the ESP.
- hasEFIFirmware := false
- for _, efiDir := range []string{"/EFI", "/efi"} {
- if !part.Exists(efiDir, false) {
- continue
- }
- l.dirWalk(part, efiDir, func(path string, isDir bool) bool {
- if isDir {
- return false
- }
- // check file is UEFI firmware
- if strings.HasSuffix(path, ".efi") {
- log.Infof("EFI firmware %s found", path)
- hasEFIFirmware = true
- return true
- }
- // continue walk
- return false
- })
- }
- return hasEFIFirmware
- }
- func (l *sLinuxRootFs) IsCloudinitInstall() bool {
- return l.GetPartition().Exists("/usr/bin/cloud-init", false)
- }
- func (d *sLinuxRootFs) DeployTelegraf(config string) (bool, error) {
- var (
- part = d.GetPartition()
- modeRwxOwner = syscall.S_IRUSR | syscall.S_IWUSR | syscall.S_IXUSR
- cloudMonitorPath = "/opt/.cloud-monitor"
- telegrafPath = path.Join(cloudMonitorPath, "run")
- )
- err := part.Mkdir(cloudMonitorPath, modeRwxOwner, false)
- if err != nil {
- return false, errors.Wrap(err, "mkdir cloud-monitor")
- }
- err = part.Mkdir(telegrafPath, modeRwxOwner, false)
- if err != nil {
- return false, errors.Wrap(err, "mkdir telegraf")
- }
- // telegraf files
- err = part.FilePutContents(path.Join(cloudMonitorPath, "telegraf.conf"), config, false, false)
- if err != nil {
- return false, errors.Wrap(err, "write telegraf config")
- }
- output, err := procutils.NewCommand("cp", "-f", TELEGRAF_BINARY_PATH, path.Join(part.GetMountPath(), cloudMonitorPath)).Output()
- if err != nil {
- return false, errors.Wrapf(err, "cp telegraf failed %s", output)
- }
- // supervise
- output, err = procutils.NewCommand("cp", "-f", SUPERVISE_BINARY_PATH, path.Join(part.GetMountPath(), cloudMonitorPath)).Output()
- if err != nil {
- return false, errors.Wrapf(err, "cp supervise failed %s", output)
- }
- err = part.FilePutContents(
- path.Join(telegrafPath, "run"),
- fmt.Sprintf("#!/bin/sh\n%s/telegraf -config %s/telegraf.conf", cloudMonitorPath, cloudMonitorPath),
- false, false,
- )
- if err != nil {
- return false, errors.Wrap(err, "write supervise run script")
- }
- err = part.Chmod(path.Join(telegrafPath, "run"), 0755, false)
- if err != nil {
- return false, errors.Wrap(err, "chmod supervise run script")
- }
- initCmd := fmt.Sprintf("%s/supervise %s", cloudMonitorPath, telegrafPath)
- if d.isSupportSystemd() {
- initCmd = path.Join(telegrafPath, "run")
- }
- err = d.installInitScript("telegraf", initCmd, false)
- if err != nil {
- return false, errors.Wrap(err, "installInitScript")
- }
- /* // add crontab: start telegraf on guest boot
- cronJob := fmt.Sprintf("@reboot %s/supervise %s", cloudMonitorPath, telegrafPath)
- if procutils.NewCommand("chroot", part.GetMountPath(), "crontab", "-l", "|", "grep", cronJob).Run() == nil {
- // if cronjob exist, return success
- return true, nil
- }
- output, err = procutils.NewCommand("chroot", part.GetMountPath(), "sh", "-c",
- fmt.Sprintf("(crontab -l 2>/dev/null; echo '%s') |crontab -", cronJob),
- ).Output()
- if err != nil {
- return false, errors.Wrapf(err, "add crontab %s", output)
- }*/
- return true, nil
- }
- func (d *sLinuxRootFs) ConfigSshd(loginAccount, loginPassword string, sshPort int) error {
- if d.rootFs.Exists("/etc/ssh/sshd_config.d", false) {
- content := "### sshd config for cloud config\n"
- if loginAccount == "root" {
- content += "PermitRootLogin yes\n"
- }
- if len(loginPassword) > 0 {
- content += "PasswordAuthentication yes\n"
- }
- if sshPort > 0 && sshPort != 22 {
- content += fmt.Sprintf("Port %d\n", sshPort)
- }
- return d.rootFs.FilePutContents("/etc/ssh/sshd_config.d/00-cloud-config.conf", content, false, false)
- } else {
- content, err := d.rootFs.FileGetContents("/etc/ssh/sshd_config", false)
- if err != nil {
- return errors.Wrap(err, "read sshd config")
- }
- lines := genSshdConfig(strings.Split(string(content), "\n"), loginAccount, loginPassword, sshPort)
- return d.rootFs.FilePutContents("/etc/ssh/sshd_config", strings.Join(lines, "\n"), false, false)
- }
- }
- type sDebianLikeRootFs struct {
- *sLinuxRootFs
- }
- func newDebianLikeRootFs(part IDiskPartition) *sDebianLikeRootFs {
- return &sDebianLikeRootFs{
- sLinuxRootFs: newLinuxRootFs(part),
- }
- }
- func (d *sDebianLikeRootFs) PrepareFsForTemplate(rootFs IDiskPartition) error {
- if err := d.sLinuxRootFs.PrepareFsForTemplate(rootFs); err != nil {
- return err
- }
- // clean /etc/network/interface
- if rootFs.Exists("/etc/network/interface", false) {
- fn := "/etc/network/interfaces"
- var cmds strings.Builder
- cmds.WriteString("auto lo\n")
- cmds.WriteString("iface lo inet loopback\n\n")
- if err := rootFs.FilePutContents(fn, cmds.String(), false, false); err != nil {
- return errors.Wrap(err, "file put content /etc/network/interface")
- }
- }
- // clean /etc/netplan/*
- netplanDir := "/etc/netplan/"
- if rootFs.Exists(netplanDir, false) {
- for _, f := range rootFs.ListDir(netplanDir, false) {
- rootFs.Remove(filepath.Join(netplanDir, f), false)
- }
- }
- return nil
- }
- 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 &deployapi.ReleaseInfo{
- Distro: driver.DistroName(),
- Version: versionStr,
- Arch: d.GetArch(rootFs),
- }
- }
- func (d *sDebianLikeRootFs) RootSignatures() []string {
- sig := d.sLinuxRootFs.RootSignatures()
- return append([]string{"/etc/issue"}, sig...)
- }
- func (d *sDebianLikeRootFs) DeployHostname(rootFs IDiskPartition, hn, domain string) error {
- return rootFs.FilePutContents("/etc/hostname", hn, false, false)
- }
- func getNicTeamingConfigCmds(slaves []*types.SServerNic) string {
- var cmds strings.Builder
- cmds.WriteString(" bond-mode 4\n")
- cmds.WriteString(" bond-miimon 100\n")
- cmds.WriteString(" bond-lacp-rate 1\n")
- cmds.WriteString(" bond-xmit_hash_policy 1\n")
- cmds.WriteString(" bond-slaves")
- for i := range slaves {
- cmds.WriteString(" ")
- cmds.WriteString(slaves[i].Name)
- }
- cmds.WriteString("\n")
- return cmds.String()
- }
- func (d *sDebianLikeRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*types.SServerNic) error {
- if err := d.sLinuxRootFs.DeployNetworkingScripts(rootFs, nics); err != nil {
- return err
- }
- if !rootFs.Exists("/etc/network", false) {
- if err := rootFs.Mkdir("/etc/network",
- syscall.S_IRUSR|syscall.S_IWUSR|syscall.S_IXUSR, false); err != nil {
- return errors.Wrap(err, "mkdir /etc/network")
- }
- }
- fn := "/etc/network/interfaces"
- var cmds strings.Builder
- cmds.WriteString("auto lo\n")
- cmds.WriteString("iface lo inet loopback\n\n")
- // ToServerNics(nics)
- allNics, bondNics := convertNicConfigs(nics)
- nicCnt := len(allNics) - len(bondNics)
- mainNic := getMainNic(allNics)
- var mainIp string
- if mainNic != nil {
- mainIp = mainNic.Ip
- }
- mainNic6 := getMainNic6(allNics)
- var mainIp6 string
- if mainNic6 != nil {
- mainIp6 = mainNic6.Ip6
- }
- netplanDir := "/etc/netplan"
- if rootFs.Exists(netplanDir, false) {
- for _, f := range rootFs.ListDir(netplanDir, false) {
- rootFs.Remove(filepath.Join(netplanDir, f), false)
- }
- netplanConfig := NewNetplanConfig(allNics, bondNics, mainIp, mainIp6)
- log.Debugf("netplanConfig:\n %s", netplanConfig.YAMLString())
- if err := rootFs.FilePutContents(path.Join(netplanDir, "config.yaml"), netplanConfig.YAMLString(), false, false); err != nil {
- return errors.Wrap(err, "Put netplan config")
- }
- }
- var systemdResolveConfig strings.Builder
- dnss := []string{}
- domains := []string{}
- for i := range allNics {
- nicDesc := allNics[i]
- cmds.WriteString(fmt.Sprintf("auto %s\n", nicDesc.Name))
- if nicDesc.TeamingMaster != nil {
- cmds.WriteString(fmt.Sprintf("iface %s inet manual\n", nicDesc.Name))
- cmds.WriteString(fmt.Sprintf(" bond-master %s\n", nicDesc.TeamingMaster.Name))
- cmds.WriteString("\n")
- } else if nicDesc.Virtual {
- cmds.WriteString(fmt.Sprintf("iface %s inet static\n", nicDesc.Name))
- cmds.WriteString(fmt.Sprintf(" address %s\n", netutils2.PSEUDO_VIP))
- cmds.WriteString(" netmask 255.255.255.255\n")
- cmds.WriteString("\n")
- } else if nicDesc.Manual {
- ifname := nicDesc.Name
- if len(nicDesc.Ip) > 0 {
- cmds.WriteString(fmt.Sprintf("iface %s inet static\n", nicDesc.Name))
- if nicDesc.VlanInterface {
- cmds.WriteString("\n")
- ifname = fmt.Sprintf("%s.%d", nicDesc.Name, nicDesc.Vlan)
- cmds.WriteString(fmt.Sprintf("auto %s\n", ifname))
- cmds.WriteString(fmt.Sprintf("iface %s inet static\n", ifname))
- }
- netmask := netutils2.Netlen2Mask(int(nicDesc.Masklen))
- cmds.WriteString(fmt.Sprintf(" address %s\n", nicDesc.Ip))
- cmds.WriteString(fmt.Sprintf(" netmask %s\n", netmask))
- cmds.WriteString(fmt.Sprintf(" hwaddress ether %s\n", nicDesc.Mac))
- if len(nicDesc.Gateway) > 0 && nicDesc.Ip == mainIp {
- cmds.WriteString(fmt.Sprintf(" gateway %s\n", nicDesc.Gateway))
- }
- if nicDesc.Mtu > 0 {
- cmds.WriteString(fmt.Sprintf(" mtu %d\n", nicDesc.Mtu))
- }
- }
- routes4 := make([]netutils2.SRouteInfo, 0)
- routes6 := make([]netutils2.SRouteInfo, 0)
- routes4, routes6 = netutils2.AddNicRoutes(routes4, routes6, nicDesc, mainIp, mainIp6, nicCnt)
- for _, r := range routes4 {
- cmds.WriteString(fmt.Sprintf(" up ip route add %s/%d via %s || true\n", r.Prefix, r.PrefixLen, r.Gateway))
- cmds.WriteString(fmt.Sprintf(" down ip route del %s/%d via %s || true\n", r.Prefix, r.PrefixLen, r.Gateway))
- }
- for _, r := range routes6 {
- cmds.WriteString(fmt.Sprintf(" up ip -6 route add %s/%d via %s || true\n", r.Prefix, r.PrefixLen, r.Gateway))
- cmds.WriteString(fmt.Sprintf(" down ip -6 route del %s/%d via %s || true\n", r.Prefix, r.PrefixLen, r.Gateway))
- }
- dnslist, _ := netutils2.GetNicDns(nicDesc)
- if len(dnslist) > 0 {
- cmds.WriteString(fmt.Sprintf(" dns-nameservers %s\n", strings.Join(dnslist, " ")))
- dnss = append(dnss, dnslist...)
- if len(nicDesc.Domain) > 0 {
- cmds.WriteString(fmt.Sprintf(" dns-search %s\n", nicDesc.Domain))
- domains = append(domains, nicDesc.Domain)
- }
- if nicDesc.Mtu > 0 {
- cmds.WriteString(fmt.Sprintf(" mtu %d\n", nicDesc.Mtu))
- }
- if len(nicDesc.TeamingSlaves) > 0 {
- cmds.WriteString(getNicTeamingConfigCmds(nicDesc.TeamingSlaves))
- }
- cmds.WriteString("\n")
- }
- if len(nicDesc.Ip6) > 0 {
- cmds.WriteString(fmt.Sprintf("iface %s inet6 static\n", ifname))
- cmds.WriteString(fmt.Sprintf(" address %s\n", nicDesc.Ip6))
- cmds.WriteString(fmt.Sprintf(" netmask %d\n", nicDesc.Masklen6))
- if len(nicDesc.Gateway6) > 0 && nicDesc.Ip == mainIp {
- cmds.WriteString(fmt.Sprintf(" gateway %s\n", nicDesc.Gateway6))
- }
- _, dnslist := netutils2.GetNicDns(nicDesc)
- if len(dnslist) > 0 {
- cmds.WriteString(fmt.Sprintf(" dns-nameservers %s\n", strings.Join(dnslist, " ")))
- dnss = append(dnss, dnslist...)
- if len(nicDesc.Domain) > 0 {
- cmds.WriteString(fmt.Sprintf(" dns-search %s\n", nicDesc.Domain))
- domains = append(domains, nicDesc.Domain)
- }
- }
- cmds.WriteString("\n")
- }
- } else {
- if len(nicDesc.Ip) > 0 {
- cmds.WriteString(fmt.Sprintf("iface %s inet dhcp\n", nicDesc.Name))
- }
- if len(nicDesc.Ip6) > 0 {
- cmds.WriteString(fmt.Sprintf("iface %s inet6 dhcp\n", nicDesc.Name))
- }
- if len(nicDesc.Ip) > 0 || len(nicDesc.Ip6) > 0 {
- if len(nicDesc.TeamingSlaves) > 0 {
- cmds.WriteString(getNicTeamingConfigCmds(nicDesc.TeamingSlaves))
- }
- cmds.WriteString("\n")
- }
- }
- }
- if len(dnss) != 0 {
- systemdResolveConfig.WriteString("[Resolve]\n")
- systemdResolveConfig.WriteString(fmt.Sprintf("DNS=%s\n", strings.Join(dnss, " ")))
- if len(domains) != 0 {
- systemdResolveConfig.WriteString(fmt.Sprintf("Domains=%s\n", strings.Join(domains, " ")))
- }
- systemdResolveFn := "/etc/systemd/resolved.conf"
- content := systemdResolveConfig.String()
- if err := rootFs.FilePutContents(systemdResolveFn, content, false, false); err != nil {
- log.Warningf("Put %s to %s error: %v", content, systemdResolveFn, err)
- }
- }
- log.Debugf("%s", cmds.String())
- return rootFs.FilePutContents(fn, cmds.String(), false, false)
- }
- func (r *sDebianLikeRootFs) ChangeUserPasswd(rootFs IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error) {
- if isRandomPassword {
- var pwqualityConf *pwquality.Config
- if rootFs.Exists("/etc/security/pwquality.conf", false) {
- pwConfig, err := rootFs.FileGetContents("/etc/security/pwquality.conf", false)
- if err == nil {
- pwqualityConf = pwquality.ParseConfig(pwConfig)
- }
- }
- if rootFs.Exists("/etc/pam.d/common-password", false) {
- pamConfig, err := rootFs.FileGetContents("/etc/pam.d/common-password", false)
- if err == nil {
- pwqualityConf = pwquality.ParsePAMConfig(pamConfig, pwqualityConf)
- }
- }
- password = r.checkInputPasswd(rootFs, pwqualityConf, account, gid, publicKey, password)
- }
- return r.sLinuxRootFs.ChangeUserPasswd(rootFs, account, gid, publicKey, password, isRandomPassword)
- }
- type SDebianRootFs struct {
- *sDebianLikeRootFs
- }
- func NewDebianRootFs(part IDiskPartition) IRootFsDriver {
- driver := new(SDebianRootFs)
- driver.sDebianLikeRootFs = newDebianLikeRootFs(part)
- return driver
- }
- func (d *SDebianRootFs) String() string {
- return "DebianRootFs"
- }
- func (d *SDebianRootFs) GetName() string {
- return "Debian"
- }
- func (d *SDebianRootFs) DistroName() string {
- return d.GetName()
- }
- func (d *SDebianRootFs) VersionFilePath() string {
- return "/etc/debian_version"
- }
- func (d *SDebianRootFs) rootSignatures(driver IDebianRootFsDriver) []string {
- sig := d.sDebianLikeRootFs.RootSignatures()
- return append([]string{driver.VersionFilePath()}, sig...)
- }
- func (d *SDebianRootFs) RootSignatures() []string {
- return d.rootSignatures(d)
- }
- func (d *SDebianRootFs) RootExcludeSignatures() []string {
- return []string{"/etc/lsb-release"}
- }
- func (d *SDebianRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- return d.sDebianLikeRootFs.GetReleaseInfo(rootFs, d)
- }
- type SCirrosRootFs struct {
- *SDebianRootFs
- }
- func NewCirrosRootFs(part IDiskPartition) IRootFsDriver {
- driver := new(SCirrosRootFs)
- driver.SDebianRootFs = NewDebianRootFs(part).(*SDebianRootFs)
- return driver
- }
- func (d *SCirrosRootFs) GetName() string {
- return "Cirros"
- }
- func (d *SCirrosRootFs) String() string {
- return "CirrosRootFs"
- }
- func (d *SCirrosRootFs) DistroName() string {
- return d.GetName()
- }
- func (d *SCirrosRootFs) VersionFilePath() string {
- return "/etc/br-version"
- }
- func (d *SCirrosRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- return d.SDebianRootFs.sDebianLikeRootFs.GetReleaseInfo(rootFs, d)
- }
- func (d *SCirrosRootFs) RootSignatures() []string {
- return d.rootSignatures(d)
- }
- type SCirrosNewRootFs struct {
- *SDebianRootFs
- }
- func NewCirrosNewRootFs(part IDiskPartition) IRootFsDriver {
- driver := new(SCirrosNewRootFs)
- driver.SDebianRootFs = NewDebianRootFs(part).(*SDebianRootFs)
- return driver
- }
- func (d *SCirrosNewRootFs) GetName() string {
- return "Cirros"
- }
- func (d *SCirrosNewRootFs) String() string {
- return "CirrosNewRootFs"
- }
- func (d *SCirrosNewRootFs) DistroName() string {
- return d.GetName()
- }
- func (d *SCirrosNewRootFs) VersionFilePath() string {
- return "/etc/cirros/version"
- }
- func (d *SCirrosNewRootFs) RootSignatures() []string {
- return d.rootSignatures(d)
- }
- func (d *SCirrosNewRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- return d.SDebianRootFs.sDebianLikeRootFs.GetReleaseInfo(rootFs, d)
- }
- type SUbuntuRootFs struct {
- *sDebianLikeRootFs
- }
- func NewUbuntuRootFs(part IDiskPartition) IRootFsDriver {
- driver := new(SUbuntuRootFs)
- driver.sDebianLikeRootFs = newDebianLikeRootFs(part)
- return driver
- }
- func (d *SUbuntuRootFs) RootSignatures() []string {
- sig := d.sDebianLikeRootFs.RootSignatures()
- return append([]string{"/etc/lsb-release"}, sig...)
- }
- func (d *SUbuntuRootFs) GetName() string {
- return "Ubuntu"
- }
- func (d *SUbuntuRootFs) String() string {
- return "UbuntuRootFs"
- }
- func (d *SUbuntuRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- distroKey := "DISTRIB_RELEASE="
- distroId := "DISTRIB_ID="
- rel, err := rootFs.FileGetContents("/etc/lsb-release", false)
- if err != nil {
- log.Errorf("Get ubuntu release info error: %v", err)
- return nil
- }
- var version, distro string
- lines := strings.Split(string(rel), "\n")
- for _, l := range lines {
- if strings.HasPrefix(l, distroKey) {
- version = strings.TrimSpace(l[len(distroKey):])
- } else if strings.HasPrefix(l, distroId) {
- distro = strings.TrimSpace(l[len(distroId):])
- }
- }
- if distro == "" {
- distro = d.GetName()
- }
- return deployapi.NewReleaseInfo(distro, version, d.GetArch(rootFs))
- }
- func (d *SUbuntuRootFs) EnableSerialConsole(rootFs IDiskPartition, sysInfo *jsonutils.JSONDict) error {
- relInfo := d.GetReleaseInfo(rootFs)
- ver := strings.Split(relInfo.Version, ".")
- verInt, _ := strconv.Atoi(ver[0])
- if verInt < 16 {
- return d.enableSerialConsoleInit(rootFs)
- }
- return d.enableSerialConsoleSystemd(rootFs)
- }
- func (d *SUbuntuRootFs) DisableSerialConcole(rootFs IDiskPartition) error {
- relInfo := d.GetReleaseInfo(rootFs)
- ver := strings.Split(relInfo.Version, ".")
- verInt, _ := strconv.Atoi(ver[0])
- if verInt < 16 {
- d.disableSerialConsoleInit(rootFs)
- return nil
- }
- d.disableSerialConsoleSystemd(rootFs)
- return nil
- }
- type SUKylinRootfs struct {
- *SUbuntuRootFs
- }
- func NewUKylinRootfs(part IDiskPartition) IRootFsDriver {
- return &SUKylinRootfs{SUbuntuRootFs: NewUbuntuRootFs(part).(*SUbuntuRootFs)}
- }
- func (d *SUKylinRootfs) GetName() string {
- return "UbuntuKylin"
- }
- func (d *SUKylinRootfs) String() string {
- return "UKylinuRootFs"
- }
- func (d *SUKylinRootfs) RootSignatures() []string {
- sig := d.sDebianLikeRootFs.RootSignatures()
- return append([]string{"/etc/lsb-release", "/etc/kylin-build"}, sig...)
- }
- func (d *SUKylinRootfs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- info := d.SUbuntuRootFs.GetReleaseInfo(rootFs)
- info.Distro = d.GetName()
- return info
- }
- func (d *SUKylinRootfs) AllowAdminLogin() bool {
- return false
- }
- type sRedhatLikeRootFs struct {
- *sLinuxRootFs
- }
- func newRedhatLikeRootFs(part IDiskPartition) *sRedhatLikeRootFs {
- return &sRedhatLikeRootFs{
- sLinuxRootFs: newLinuxRootFs(part),
- }
- }
- func (r *sRedhatLikeRootFs) PrepareFsForTemplate(rootFs IDiskPartition) error {
- if err := r.sLinuxRootFs.PrepareFsForTemplate(rootFs); err != nil {
- return err
- }
- return r.CleanNetworkScripts(rootFs)
- }
- func (r *sRedhatLikeRootFs) cleanNetworkManagerConfigurations(rootFs IDiskPartition) error {
- networkPath := "/etc/NetworkManager/system-connections"
- if !rootFs.Exists(networkPath, false) {
- return nil
- }
- files := rootFs.ListDir(networkPath, false)
- for _, f := range files {
- rootFs.Remove(filepath.Join(networkPath, f), false)
- }
- return nil
- }
- func (r *sRedhatLikeRootFs) CleanNetworkScripts(rootFs IDiskPartition) error {
- networkPath := "/etc/sysconfig/network-scripts"
- if !rootFs.Exists(networkPath, false) {
- return r.cleanNetworkManagerConfigurations(rootFs)
- }
- files := rootFs.ListDir(networkPath, false)
- for i := 0; i < len(files); i++ {
- if strings.HasPrefix(files[i], "ifcfg-") && files[i] != "ifcfg-lo" {
- rootFs.Remove(path.Join(networkPath, files[i]), false)
- continue
- }
- if strings.HasPrefix(files[i], "route-") {
- rootFs.Remove(path.Join(networkPath, files[i]), false)
- }
- }
- return nil
- }
- func (r *sRedhatLikeRootFs) RootSignatures() []string {
- sig := r.sLinuxRootFs.RootSignatures()
- return append([]string{"/etc/redhat-release"}, sig...)
- }
- func (r *sRedhatLikeRootFs) DeployHostname(rootFs IDiskPartition, hn, domain string) error {
- var sPath = "/etc/sysconfig/network"
- if r.rootFs.Exists(sPath, false) {
- centosHn := ""
- centosHn += "NETWORKING=yes\n"
- centosHn += fmt.Sprintf("HOSTNAME=%s\n", getHostname(hn, domain))
- if err := rootFs.FilePutContents(sPath, centosHn, false, false); err != nil {
- return errors.Wrapf(err, "DeployHostname %s", sPath)
- }
- }
- if err := rootFs.FilePutContents("/etc/hostname", hn, false, false); err != nil {
- return errors.Wrapf(err, "DeployHostname %s", "/etc/hostname")
- }
- return nil
- }
- func (r *sRedhatLikeRootFs) Centos5DeployNetworkingScripts(rootFs IDiskPartition, nics []*types.SServerNic) error {
- var netDevPrefix = GetNetDevPrefix(nics)
- var udevPath = "/etc/udev/rules.d/"
- if rootFs.Exists(udevPath, false) {
- var nicRules = ""
- for _, nic := range nics {
- nicRules += `KERNEL=="*", `
- nicRules += fmt.Sprintf(`SYSFS{address}=="%s", `, strings.ToLower(nic.Mac))
- nicRules += fmt.Sprintf("NAME=\"%s%d\"\n", netDevPrefix, nic.Index)
- }
- return rootFs.FilePutContents(path.Join(udevPath, "60-net.rules"),
- nicRules, false, false)
- }
- return nil
- }
- func (r *sRedhatLikeRootFs) ChangeUserPasswd(rootFs IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error) {
- if isRandomPassword {
- var pwqualityConf *pwquality.Config
- if rootFs.Exists("/etc/security/pwquality.conf", false) {
- pwConfig, err := rootFs.FileGetContents("/etc/security/pwquality.conf", false)
- if err == nil {
- pwqualityConf = pwquality.ParseConfig(pwConfig)
- }
- }
- if rootFs.Exists("/etc/pam.d/system-auth", false) {
- pamConfig, err := rootFs.FileGetContents("/etc/pam.d/system-auth", false)
- if err == nil {
- pwqualityConf = pwquality.ParsePAMConfig(pamConfig, pwqualityConf)
- }
- }
- password = r.checkInputPasswd(rootFs, pwqualityConf, account, gid, publicKey, password)
- }
- return r.sLinuxRootFs.ChangeUserPasswd(rootFs, account, gid, publicKey, password, isRandomPassword)
- }
- func getMainNic(nics []*types.SServerNic) *types.SServerNic {
- for i := range nics {
- if nics[i].IsDefault {
- return nics[i]
- }
- }
- for i := range nics {
- if len(nics[i].Ip) > 0 && len(nics[i].Gateway) > 0 {
- return nics[i]
- }
- }
- return nil
- }
- func getMainNic6(nics []*types.SServerNic) *types.SServerNic {
- for i := range nics {
- if nics[i].IsDefault {
- return nics[i]
- }
- }
- for i := range nics {
- if len(nics[i].Ip6) > 0 && len(nics[i].Gateway6) > 0 {
- return nics[i]
- }
- }
- return nil
- }
- func (r *sRedhatLikeRootFs) enableBondingModule(rootFs IDiskPartition, bondNics []*types.SServerNic) error {
- var content strings.Builder
- for i := range bondNics {
- content.WriteString("alias ")
- content.WriteString(bondNics[i].Name)
- content.WriteString(" bonding\n options ")
- content.WriteString(bondNics[i].Name)
- content.WriteString(" miimon=100 mode=4 lacp_rate=1 xmit_hash_policy=1\n")
- }
- return rootFs.FilePutContents("/etc/modprobe.d/bonding.conf", content.String(), false, false)
- }
- // check if NetworkManager is enabled
- func (r *sRedhatLikeRootFs) isNetworkManagerEnabled(rootFs IDiskPartition) bool {
- return rootFs.Exists("/etc/systemd/system/multi-user.target.wants/NetworkManager.service", false)
- }
- func (r *sRedhatLikeRootFs) deployNetworkManagerConfigurations(rootFs IDiskPartition, nics []*types.SServerNic, relInfo *deployapi.ReleaseInfo) error {
- const scriptPath = "/etc/NetworkManager/system-connections"
- if !rootFs.Exists(scriptPath, false) {
- return errors.Wrap(errors.ErrNotSupported, "unsupported system, neither network-scripts nor NetworkManager")
- }
- // remove all connections profiles
- files := rootFs.ListDir(scriptPath, false)
- for _, f := range files {
- log.Infof("remove %s in %s", f, scriptPath)
- rootFs.Remove(filepath.Join(scriptPath, f), false)
- }
- allNics, bondNics := convertNicConfigs(nics)
- if len(bondNics) > 0 {
- err := r.enableBondingModule(rootFs, bondNics)
- if err != nil {
- return errors.Wrap(err, "enableBondingModule")
- }
- }
- nicCnt := len(allNics) - len(bondNics)
- mainNic := getMainNic(allNics)
- var mainIp string
- if mainNic != nil {
- mainIp = mainNic.Ip
- }
- mainNic6 := getMainNic6(allNics)
- var mainIp6 string
- if mainNic6 != nil {
- mainIp6 = mainNic6.Ip6
- }
- for i := range allNics {
- nicDesc := allNics[i]
- profile := nicDescToNetworkManager(nicDesc, mainIp, mainIp6, nicCnt)
- var fn = fmt.Sprintf("%s/%s.nmconnection", scriptPath, nicDesc.Name)
- if err := rootFs.FilePutContents(fn, profile, false, false); err != nil {
- return err
- }
- }
- return nil
- }
- func (r *sRedhatLikeRootFs) deployNetworkingScripts(rootFs IDiskPartition, nics []*types.SServerNic, relInfo *deployapi.ReleaseInfo) error {
- ver := strings.Split(relInfo.Version, ".")
- iv, err := strconv.ParseInt(ver[0], 10, 0)
- if err == nil && iv < 6 {
- err = r.Centos5DeployNetworkingScripts(rootFs, nics)
- } else {
- err = r.sLinuxRootFs.DeployNetworkingScripts(rootFs, nics)
- }
- if err != nil {
- return errors.Wrap(err, "DeployNetworkingScripts")
- }
- const scriptPath = "/etc/sysconfig/network-scripts"
- if !rootFs.Exists(scriptPath, false) {
- // NetworkManager is enabled, but no network-scripts directory, deploy NetworkManager configurations
- return r.deployNetworkManagerConfigurations(rootFs, nics, relInfo)
- }
- // remove all ifcfg-*
- files := rootFs.ListDir(scriptPath, false)
- for _, f := range files {
- if strings.HasPrefix(f, "ifcfg-") && f != "ifcfg-lo" {
- log.Infof("remove %s in %s", f, scriptPath)
- rootFs.Remove(filepath.Join(scriptPath, f), false)
- }
- }
- // ToServerNics(nics)
- allNics, bondNics := convertNicConfigs(nics)
- if len(bondNics) > 0 {
- err = r.enableBondingModule(rootFs, bondNics)
- if err != nil {
- return errors.Wrap(err, "enableBondingModule")
- }
- }
- nicCnt := len(allNics) - len(bondNics)
- mainNic := getMainNic(allNics)
- var mainIp string
- if mainNic != nil {
- mainIp = mainNic.Ip
- }
- mainNic6 := getMainNic6(allNics)
- var mainIp6 string
- if mainNic6 != nil {
- mainIp6 = mainNic6.Ip6
- }
- for i := range allNics {
- nicDesc := allNics[i]
- var cmds strings.Builder
- cmds.WriteString("DEVICE=")
- cmds.WriteString(nicDesc.Name)
- cmds.WriteString("\n")
- cmds.WriteString("NAME=")
- cmds.WriteString(nicDesc.Name)
- cmds.WriteString("\n")
- cmds.WriteString("ONBOOT=yes\n")
- if r.isNetworkManagerEnabled(rootFs) {
- cmds.WriteString("NM_CONTROLLED=yes\n")
- } else {
- cmds.WriteString("NM_CONTROLLED=no\n")
- }
- cmds.WriteString("USERCTL=no\n")
- if nicDesc.Mtu > 0 {
- cmds.WriteString(fmt.Sprintf("MTU=%d\n", nicDesc.Mtu))
- }
- if len(nicDesc.Mac) > 0 && nicDesc.NicType != api.NIC_TYPE_INFINIBAND {
- if len(nicDesc.TeamingSlaves) == 0 {
- // only real physical nic can set HWADDR
- cmds.WriteString("HWADDR=")
- cmds.WriteString(nicDesc.Mac)
- cmds.WriteString("\n")
- }
- cmds.WriteString("MACADDR=")
- cmds.WriteString(nicDesc.Mac)
- cmds.WriteString("\n")
- }
- if len(nicDesc.TeamingSlaves) > 0 {
- // bonding master
- cmds.WriteString(`BONDING_OPTS="mode=4 miimon=100"`)
- cmds.WriteString("\n")
- }
- if nicDesc.TeamingMaster != nil {
- cmds.WriteString("BOOTPROTO=none\n")
- cmds.WriteString("MASTER=")
- cmds.WriteString(nicDesc.TeamingMaster.Name)
- cmds.WriteString("\n")
- cmds.WriteString("SLAVE=yes\n")
- } else if nicDesc.Virtual {
- cmds.WriteString("BOOTPROTO=none\n")
- cmds.WriteString("NETMASK=255.255.255.255\n")
- cmds.WriteString("IPADDR=")
- cmds.WriteString(netutils2.PSEUDO_VIP)
- cmds.WriteString("\n")
- } else if nicDesc.Manual {
- cmds.WriteString("BOOTPROTO=none\n")
- if nicDesc.VlanInterface {
- if err := r.deployVlanNetworkingScripts(rootFs, scriptPath, mainIp, mainIp6, nicCnt, nicDesc); err != nil {
- return errors.Wrap(err, "deployVlanNetworkingScripts")
- }
- } else {
- if len(nicDesc.Ip) > 0 {
- netmask := netutils2.Netlen2Mask(int(nicDesc.Masklen))
- cmds.WriteString("NETMASK=")
- cmds.WriteString(netmask)
- cmds.WriteString("\n")
- cmds.WriteString("IPADDR=")
- cmds.WriteString(nicDesc.Ip)
- cmds.WriteString("\n")
- if len(nicDesc.Gateway) > 0 && nicDesc.Ip == mainIp {
- cmds.WriteString("GATEWAY=")
- cmds.WriteString(nicDesc.Gateway)
- cmds.WriteString("\n")
- }
- }
- routes4 := make([]netutils2.SRouteInfo, 0)
- routes6 := make([]netutils2.SRouteInfo, 0)
- routes4, routes6 = netutils2.AddNicRoutes(routes4, routes6, nicDesc, mainIp, mainIp6, nicCnt)
- var rtbl strings.Builder
- for _, r := range routes4 {
- rtbl.WriteString(fmt.Sprintf("%s/%d", r.Prefix, r.PrefixLen))
- rtbl.WriteString(" via ")
- rtbl.WriteString(r.Gateway.String())
- rtbl.WriteString(" dev ")
- rtbl.WriteString(nicDesc.Name)
- rtbl.WriteString("\n")
- }
- for _, r := range routes6 {
- rtbl.WriteString(fmt.Sprintf("%s/%d", r.Prefix, r.PrefixLen))
- rtbl.WriteString(" via ")
- rtbl.WriteString(r.Gateway.String())
- rtbl.WriteString(" dev ")
- rtbl.WriteString(nicDesc.Name)
- rtbl.WriteString("\n")
- }
- rtblStr := rtbl.String()
- if len(rtblStr) > 0 {
- var fn = fmt.Sprintf("%s/route-%s", scriptPath, nicDesc.Name)
- if err := rootFs.FilePutContents(fn, rtblStr, false, false); err != nil {
- return err
- }
- }
- dns4list, dns6list := netutils2.GetNicDns(nicDesc)
- if len(dns4list)+len(dns6list) > 0 {
- cmds.WriteString("PEERDNS=yes\n")
- dnsIdx := 1
- for i := 0; i < len(dns4list); i++ {
- cmds.WriteString(fmt.Sprintf("DNS%d=%s\n", dnsIdx, dns4list[i]))
- dnsIdx += 1
- }
- for i := 0; i < len(dns6list); i++ {
- cmds.WriteString(fmt.Sprintf("DNS%d=%s\n", dnsIdx, dns6list[i]))
- dnsIdx += 1
- }
- if len(nicDesc.Domain) > 0 {
- cmds.WriteString(fmt.Sprintf("DOMAIN=%s\n", nicDesc.Domain))
- }
- }
- if len(nicDesc.Ip6) > 0 {
- cmds.WriteString("IPV6INIT=yes\n")
- cmds.WriteString("DHCPV6C=no\n")
- cmds.WriteString("IPV6_AUTOCONF=no\n")
- cmds.WriteString(fmt.Sprintf("IPV6ADDR=%s/%d\n", nicDesc.Ip6, nicDesc.Masklen6))
- if len(nicDesc.Gateway6) > 0 && nicDesc.Ip6 == mainIp6 {
- cmds.WriteString(fmt.Sprintf("IPV6_DEFAULTGW=%s\n", nicDesc.Gateway6))
- }
- }
- }
- } else {
- if len(nicDesc.Ip) > 0 {
- cmds.WriteString("BOOTPROTO=dhcp\n")
- }
- if len(nicDesc.Ip6) > 0 {
- cmds.WriteString("IPV6INIT=yes\n")
- cmds.WriteString("DHCPV6C=yes\n")
- cmds.WriteString("IPV6_AUTOCONF=yes\n")
- }
- }
- var fn = fmt.Sprintf("%s/ifcfg-%s", scriptPath, nicDesc.Name)
- log.Debugf("%s: %s", fn, cmds.String())
- if err := rootFs.FilePutContents(fn, cmds.String(), false, false); err != nil {
- return err
- }
- }
- return nil
- }
- func (r *sRedhatLikeRootFs) deployVlanNetworkingScripts(rootFs IDiskPartition, scriptPath, mainIp, mainIp6 string, nicCnt int, nicDesc *types.SServerNic) error {
- if nicDesc.Vlan <= 1 {
- return nil
- }
- var cmds strings.Builder
- cmds.WriteString("BOOTPROTO=none\n")
- cmds.WriteString(fmt.Sprintf("DEVICE=%s.%d\n", nicDesc.Name, nicDesc.Vlan))
- cmds.WriteString(fmt.Sprintf("NAME=%s.%d\n", nicDesc.Name, nicDesc.Vlan))
- cmds.WriteString("ONBOOT=yes\n")
- if r.isNetworkManagerEnabled(rootFs) {
- cmds.WriteString("NM_CONTROLLED=yes\n")
- } else {
- cmds.WriteString("NM_CONTROLLED=no\n")
- }
- cmds.WriteString("USERCTL=no\n")
- if nicDesc.Mtu > 0 {
- cmds.WriteString(fmt.Sprintf("MTU=%d\n", nicDesc.Mtu))
- }
- if len(nicDesc.Ip) > 0 {
- netmask := netutils2.Netlen2Mask(int(nicDesc.Masklen))
- cmds.WriteString("NETMASK=")
- cmds.WriteString(netmask)
- cmds.WriteString("\n")
- cmds.WriteString("IPADDR=")
- cmds.WriteString(nicDesc.Ip)
- cmds.WriteString("\n")
- if len(nicDesc.Gateway) > 0 && nicDesc.Ip == mainIp {
- cmds.WriteString("GATEWAY=")
- cmds.WriteString(nicDesc.Gateway)
- cmds.WriteString("\n")
- }
- }
- if len(nicDesc.Ip6) > 0 {
- cmds.WriteString("IPV6INIT=yes\n")
- cmds.WriteString("DHCPV6C=no\n")
- cmds.WriteString("IPV6_AUTOCONF=no\n")
- cmds.WriteString(fmt.Sprintf("IPV6ADDR=%s/%d\n", nicDesc.Ip6, nicDesc.Masklen6))
- if len(nicDesc.Gateway6) > 0 && nicDesc.Ip6 == mainIp6 {
- cmds.WriteString(fmt.Sprintf("IPV6_DEFAULTGW=%s\n", nicDesc.Gateway6))
- }
- }
- routes4 := make([]netutils2.SRouteInfo, 0)
- routes6 := make([]netutils2.SRouteInfo, 0)
- routes4, routes6 = netutils2.AddNicRoutes(routes4, routes6, nicDesc, mainIp, mainIp6, nicCnt)
- var rtbl strings.Builder
- for _, r := range routes4 {
- rtbl.WriteString(fmt.Sprintf("%s/%d", r.Prefix, r.PrefixLen))
- rtbl.WriteString(" via ")
- rtbl.WriteString(r.Gateway.String())
- rtbl.WriteString(" dev ")
- rtbl.WriteString(fmt.Sprintf("%s.%d", nicDesc.Name, nicDesc.Vlan))
- rtbl.WriteString("\n")
- }
- for _, r := range routes6 {
- rtbl.WriteString(fmt.Sprintf("%s/%d", r.Prefix, r.PrefixLen))
- rtbl.WriteString(" via ")
- rtbl.WriteString(r.Gateway.String())
- rtbl.WriteString(" dev ")
- rtbl.WriteString(fmt.Sprintf("%s.%d", nicDesc.Name, nicDesc.Vlan))
- rtbl.WriteString("\n")
- }
- rtblStr := rtbl.String()
- if len(rtblStr) > 0 {
- var fn = fmt.Sprintf("%s/route-%s", scriptPath, nicDesc.Name)
- if err := rootFs.FilePutContents(fn, rtblStr, false, false); err != nil {
- return err
- }
- }
- dns4list, dns6list := netutils2.GetNicDns(nicDesc)
- if len(dns4list)+len(dns6list) > 0 {
- cmds.WriteString("PEERDNS=yes\n")
- dnsIdx := 1
- for i := 0; i < len(dns4list); i++ {
- cmds.WriteString(fmt.Sprintf("DNS%d=%s\n", dnsIdx, dns4list[i]))
- dnsIdx += 1
- }
- for i := 0; i < len(dns6list); i++ {
- cmds.WriteString(fmt.Sprintf("DNS%d=%s\n", dnsIdx, dns6list[i]))
- dnsIdx += 1
- }
- if len(nicDesc.Domain) > 0 {
- cmds.WriteString(fmt.Sprintf("DOMAIN=%s\n", nicDesc.Domain))
- }
- }
- cmds.WriteString("VLAN=yes\n")
- var fn = fmt.Sprintf("%s/ifcfg-%s.%d", scriptPath, nicDesc.Name, nicDesc.Vlan)
- log.Debugf("%s: %s", fn, cmds.String())
- if err := rootFs.FilePutContents(fn, cmds.String(), false, false); err != nil {
- return err
- }
- return nil
- }
- func (r *sRedhatLikeRootFs) DeployStandbyNetworkingScripts(rootFs IDiskPartition, nics, nicsStandby []*types.SServerNic) error {
- if err := r.sLinuxRootFs.DeployStandbyNetworkingScripts(rootFs, nics, nicsStandby); err != nil {
- return err
- }
- var netDevPrefix = GetNetDevPrefix(nics)
- for _, nic := range nicsStandby {
- var cmds string
- if len(nic.NicType) == 0 || nic.NicType != "ipmi" {
- cmds += fmt.Sprintf("DEVICE=%s%d\n", netDevPrefix, nic.Index)
- cmds += fmt.Sprintf("NAME=%s%d\n", netDevPrefix, 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-%s%d", netDevPrefix, nic.Index)
- if err := rootFs.FilePutContents(fn, cmds, false, false); err != nil {
- return err
- }
- }
- }
- return nil
- }
- func (r *sRedhatLikeRootFs) getReleaseMajorVersion(drv IRootFsDriver, rootFs IDiskPartition) (int, error) {
- relInfo := drv.GetReleaseInfo(rootFs)
- if len(relInfo.Version) == 0 {
- return 0, fmt.Errorf("release info version is empty")
- }
- log.Infof("Get release info: %#v", relInfo)
- ver, err := strconv.Atoi(string(relInfo.Version[0]))
- if err != nil {
- return 0, fmt.Errorf("Release version %s not start with digit", relInfo.Version)
- }
- return ver, nil
- }
- func (r *sRedhatLikeRootFs) enableSerialConsole(drv IRootFsDriver, rootFs IDiskPartition, sysInfo *jsonutils.JSONDict) error {
- ver, err := r.getReleaseMajorVersion(drv, rootFs)
- if err != nil {
- return errors.Wrap(err, "Get release major version")
- }
- if ver <= 6 {
- return r.enableSerialConsoleInitCentos(rootFs)
- }
- return r.enableSerialConsoleSystemd(rootFs)
- }
- func (r *sRedhatLikeRootFs) disableSerialConcole(drv IRootFsDriver, rootFs IDiskPartition) error {
- ver, err := r.getReleaseMajorVersion(drv, rootFs)
- if err != nil {
- return errors.Wrap(err, "Get release major version")
- }
- if ver <= 6 {
- r.disableSerialConsoleInit(rootFs)
- return nil
- }
- r.disableSerialConsoleSystemd(rootFs)
- return nil
- }
- type SCentosRootFs struct {
- *sRedhatLikeRootFs
- }
- func NewCentosRootFs(part IDiskPartition) IRootFsDriver {
- return &SCentosRootFs{sRedhatLikeRootFs: newRedhatLikeRootFs(part)}
- }
- func (c *SCentosRootFs) String() string {
- return "CentosRootFs"
- }
- func (c *SCentosRootFs) GetName() string {
- return "CentOS"
- }
- func (c *SCentosRootFs) RootSignatures() []string {
- sig := c.sRedhatLikeRootFs.RootSignatures()
- return append([]string{"/etc/centos-release"}, sig...)
- }
- func (c *SCentosRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- rel, _ := rootFs.FileGetContents("/etc/centos-release", false)
- var version string
- if len(rel) > 0 {
- re := regexp.MustCompile(`^\d+\.\d+`)
- dat := strings.Split(string(rel), " ")
- for _, v := range dat {
- if re.Match([]byte(v)) {
- version = v
- break
- }
- }
- }
- return deployapi.NewReleaseInfo(c.GetName(), version, c.GetArch(rootFs))
- }
- func (c *SCentosRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*types.SServerNic) error {
- relInfo := c.GetReleaseInfo(rootFs)
- if err := c.sRedhatLikeRootFs.deployNetworkingScripts(rootFs, nics, relInfo); err != nil {
- return errors.Wrap(err, "sRedhatLikeRootFs.deployNetworkingScripts")
- }
- var udevPath = "/etc/udev/rules.d/"
- var files = []string{"60-net.rules", "75-persistent-net-generator.rules"}
- for _, f := range files {
- sPath := path.Join(udevPath, f)
- if !rootFs.Exists(sPath, false) {
- if err := rootFs.FilePutContents(sPath, "", false, false); err != nil {
- return errors.Wrapf(err, "save %s", sPath)
- }
- }
- }
- return nil
- }
- func (c *SCentosRootFs) EnableSerialConsole(rootFs IDiskPartition, sysInfo *jsonutils.JSONDict) error {
- return c.enableSerialConsole(c, rootFs, sysInfo)
- }
- func (c *SCentosRootFs) DisableSerialConsole(rootFs IDiskPartition) error {
- return c.disableSerialConcole(c, rootFs)
- }
- type SFedoraRootFs struct {
- *sRedhatLikeRootFs
- }
- func NewFedoraRootFs(part IDiskPartition) IRootFsDriver {
- return &SFedoraRootFs{sRedhatLikeRootFs: newRedhatLikeRootFs(part)}
- }
- func (c *SFedoraRootFs) String() string {
- return "FedoraRootFs"
- }
- func (c *SFedoraRootFs) GetName() string {
- return "Fedora"
- }
- func (c *SFedoraRootFs) RootSignatures() []string {
- sig := c.sRedhatLikeRootFs.RootSignatures()
- return append([]string{"/etc/fedora-release"}, sig...)
- }
- func (c *SFedoraRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- rel, _ := rootFs.FileGetContents("/etc/fedora-release", false)
- var version string
- if len(rel) > 0 {
- re := regexp.MustCompile(`^\d+`)
- dat := strings.Split(string(rel), " ")
- for _, v := range dat {
- if re.Match([]byte(v)) {
- version = v
- break
- }
- }
- }
- return deployapi.NewReleaseInfo(c.GetName(), version, c.GetArch(rootFs))
- }
- func (c *SFedoraRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*types.SServerNic) error {
- relInfo := c.GetReleaseInfo(rootFs)
- if err := c.sRedhatLikeRootFs.deployNetworkingScripts(rootFs, nics, relInfo); err != nil {
- return err
- }
- return nil
- }
- func (c *SFedoraRootFs) EnableSerialConsole(rootFs IDiskPartition, sysInfo *jsonutils.JSONDict) error {
- return c.enableSerialConsole(c, rootFs, sysInfo)
- }
- func (c *SFedoraRootFs) DisableSerialConsole(rootFs IDiskPartition) error {
- return c.disableSerialConcole(c, rootFs)
- }
- type SRhelRootFs struct {
- *sRedhatLikeRootFs
- }
- func NewRhelRootFs(part IDiskPartition) IRootFsDriver {
- return &SRhelRootFs{sRedhatLikeRootFs: newRedhatLikeRootFs(part)}
- }
- func (d *SRhelRootFs) GetName() string {
- return "RHEL"
- }
- func (d *SRhelRootFs) String() string {
- return "RhelRootFs"
- }
- func (d *SRhelRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- rel, _ := rootFs.FileGetContents("/etc/redhat-release", false)
- var version string
- if len(rel) > 0 {
- dat := strings.Split(string(rel), " ")
- if len(dat) > 6 {
- version = dat[6]
- }
- }
- return deployapi.NewReleaseInfo(d.GetName(), version, d.GetArch(rootFs))
- }
- func (d *SRhelRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*types.SServerNic) error {
- relInfo := d.GetReleaseInfo(rootFs)
- if err := d.sRedhatLikeRootFs.deployNetworkingScripts(rootFs, nics, relInfo); err != nil {
- return err
- }
- return nil
- }
- func (c *SRhelRootFs) EnableSerialConsole(rootFs IDiskPartition, sysInfo *jsonutils.JSONDict) error {
- return c.enableSerialConsole(c, rootFs, sysInfo)
- }
- func (c *SRhelRootFs) DisableSerialConsole(rootFs IDiskPartition) error {
- return c.disableSerialConcole(c, rootFs)
- }
- type SOpenEulerRootFs struct {
- *SCentosRootFs
- }
- func NewOpenEulerRootFs(part IDiskPartition) IRootFsDriver {
- return &SOpenEulerRootFs{
- SCentosRootFs: NewCentosRootFs(part).(*SCentosRootFs),
- }
- }
- func (c *SOpenEulerRootFs) String() string {
- return "OpenEulerRootFs"
- }
- func (c *SOpenEulerRootFs) GetName() string {
- return "OpenEuler"
- }
- func (c *SOpenEulerRootFs) RootSignatures() []string {
- sig := c.sLinuxRootFs.RootSignatures()
- return append([]string{"/etc/sysconfig/network", "/etc/openEuler-release"}, sig...)
- }
- func (c *SOpenEulerRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- rel, _ := rootFs.FileGetContents("/etc/openEuler-release", false)
- var version string
- if len(rel) > 0 {
- re := regexp.MustCompile(`^\d+\.\d+`)
- dat := strings.Split(string(rel), " ")
- for _, v := range dat {
- if re.Match([]byte(v)) {
- version = v
- break
- }
- }
- }
- version = strings.TrimSpace(version)
- return deployapi.NewReleaseInfo(c.GetName(), version, c.GetArch(rootFs))
- }
- func (c *SOpenEulerRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*types.SServerNic) error {
- relInfo := c.GetReleaseInfo(rootFs)
- if err := c.sRedhatLikeRootFs.deployNetworkingScripts(rootFs, nics, relInfo); err != nil {
- return err
- }
- return nil
- }
- type SGentooRootFs struct {
- *sLinuxRootFs
- }
- func NewGentooRootFs(part IDiskPartition) IRootFsDriver {
- return &SGentooRootFs{sLinuxRootFs: newLinuxRootFs(part)}
- }
- func (d *SGentooRootFs) GetName() string {
- return "Gentoo"
- }
- func (d *SGentooRootFs) String() string {
- return "GentooRootFs"
- }
- func (d *SGentooRootFs) RootSignatures() []string {
- sig := d.sLinuxRootFs.RootSignatures()
- if sig != nil {
- return append(sig, "/etc/gentoo-release")
- } else {
- return []string{"/etc/gentoo-release"}
- }
- }
- func (d *SGentooRootFs) DeployHostname(rootFs IDiskPartition, hn, domain string) error {
- spath := "/etc/conf.d/hostname"
- content := fmt.Sprintf(`hostname="%s"\n`, hn)
- return rootFs.FilePutContents(spath, content, false, false)
- }
- func (l *SGentooRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*types.SServerNic) error {
- if err := l.sLinuxRootFs.DeployNetworkingScripts(rootFs, nics); err != nil {
- return err
- }
- var (
- fn = "/etc/conf.d/net"
- cmds = ""
- )
- var netDevPrefix = GetNetDevPrefix(nics)
- // Ref https://wiki.gentoo.org/wiki/Netifrc
- for _, nic := range nics {
- nicIndex := nic.Index
- if nic.Virtual {
- cmds += fmt.Sprintf(`config_%s%d="`, netDevPrefix, nicIndex)
- cmds += fmt.Sprintf("%s netmask 255.255.255.255", netutils2.PSEUDO_VIP)
- cmds += `"\n`
- } else {
- cmds += fmt.Sprintf(`config_%s%d="dhcp"\n`, netDevPrefix, nicIndex)
- }
- if nic.Mtu > 0 {
- cmds += fmt.Sprintf(`mtu_%s%d="%d"\n`, netDevPrefix, nicIndex, nic.Mtu)
- }
- }
- if err := rootFs.FilePutContents(fn, cmds, false, false); err != nil {
- return err
- }
- for _, nic := range nics {
- nicIndex := nic.Index
- netname := fmt.Sprintf("net.%s%d", netDevPrefix, nicIndex)
- procutils.NewCommand("ln", "-s", "net.lo",
- fmt.Sprintf("%s/etc/init.d/%s", rootFs.GetMountPath(), netname)).Run()
- procutils.NewCommand("chroot",
- rootFs.GetMountPath(), "rc-update", "add", netname, "default").Run()
- }
- return nil
- }
- func (d *SGentooRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- return &deployapi.ReleaseInfo{
- Distro: "Gentoo",
- Arch: d.GetArch(rootFs),
- }
- }
- type SArchLinuxRootFs struct {
- *sLinuxRootFs
- }
- func NewArchLinuxRootFs(part IDiskPartition) IRootFsDriver {
- return &SArchLinuxRootFs{sLinuxRootFs: newLinuxRootFs(part)}
- }
- func (d *SArchLinuxRootFs) GetName() string {
- return "ArchLinux"
- }
- func (d *SArchLinuxRootFs) String() string {
- return "ArchLinuxRootFs"
- }
- func (d *SArchLinuxRootFs) RootSignatures() []string {
- sig := d.sLinuxRootFs.RootSignatures()
- if sig != nil {
- return append(sig, "/etc/arch-release")
- } else {
- return []string{"/etc/arch-release"}
- }
- }
- func (d *SArchLinuxRootFs) DeployHostname(rootFs IDiskPartition, hn, domain string) error {
- return rootFs.FilePutContents("/etc/hostname", hn, false, false)
- }
- func (d *SArchLinuxRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- return &deployapi.ReleaseInfo{
- Distro: "ArchLinux",
- Arch: d.GetArch(rootFs),
- }
- }
- type SOpenWrtRootFs struct {
- *sLinuxRootFs
- }
- func NewOpenWrtRootFs(part IDiskPartition) IRootFsDriver {
- return &SOpenWrtRootFs{sLinuxRootFs: newLinuxRootFs(part)}
- }
- func (d *SOpenWrtRootFs) GetName() string {
- return "OpenWrt"
- }
- func (d *SOpenWrtRootFs) String() string {
- return "OpenWrtRootFs"
- }
- func (d *SOpenWrtRootFs) RootSignatures() []string {
- return []string{"/bin", "/etc/", "/lib", "/sbin", "/overlay", "/etc/openwrt_release", "/etc/openwrt_version"}
- }
- func (d *SOpenWrtRootFs) featureBoardConfig(rootFs IDiskPartition) bool {
- if rootFs.Exists("/etc/board.d", false) {
- return true
- }
- return false
- }
- func (d *SOpenWrtRootFs) putBoardConfig(rootFs IDiskPartition, f, c string) error {
- if err := rootFs.FilePutContents(f, c, false, false); err != nil {
- return err
- }
- if err := rootFs.Chmod(f, 0755, false); err != nil {
- return err
- }
- return nil
- }
- func (d *SOpenWrtRootFs) DeployPublicKey(rootFs IDiskPartition, selUsr string, pubkeys *deployapi.SSHKeys) error {
- if selUsr == "root" && rootFs.Exists("/etc/dropbear", false) {
- var (
- authFile = "/etc/dropbear/authorized_keys"
- uid = 0
- gid = 0
- replace = false
- )
- return deployAuthorizedKeys(rootFs, authFile, uid, gid, pubkeys, replace, false)
- }
- return d.sLinuxRootFs.DeployPublicKey(rootFs, selUsr, pubkeys)
- }
- func (d *SOpenWrtRootFs) DeployHostname(rootFs IDiskPartition, hn, domain string) error {
- if d.featureBoardConfig(rootFs) {
- f := "/etc/board.d/00-00-onecloud-hostname"
- c := fmt.Sprintf(`. /lib/functions/uci-defaults.sh
- board_config_update
- ucidef_set_hostname '%s'
- board_config_flush
- exit 0
- `, hn)
- return d.putBoardConfig(rootFs, f, c)
- }
- spath := "/etc/config/system"
- if !rootFs.Exists(spath, false) {
- return nil
- }
- bcont, err := rootFs.FileGetContents(spath, false)
- if err != nil {
- return err
- }
- cont := string(bcont)
- re := regexp.MustCompile("option hostname [^\n]+")
- cont = re.ReplaceAllString(cont, fmt.Sprintf("option hostname %s", hn))
- return rootFs.FilePutContents(spath, cont, false, false)
- }
- func (d *SOpenWrtRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*types.SServerNic) error {
- if d.featureBoardConfig(rootFs) {
- macs := ""
- for _, nic := range nics {
- macs = "," + nic.Mac
- }
- f := "/etc/board.d/00-01-onecloud-network"
- c := fmt.Sprintf(`. /lib/functions/uci-defaults.sh
- [ -d /sys/class/net ] || exit 0
- board_config_update
- macs='%s'
- i=0
- oc_set_ifname() {
- local net="$1"; shift
- local ifname="$1"; shift
- if type ucidef_set_interface &>/dev/null; then
- ucidef_set_interface "$net" ifname "$ifname" protocol dhcp
- elif type ucidef_set_interface_raw &>/dev/null; then
- ucidef_set_interface_raw "$net" "$ifname" "dhcp"
- else
- echo "no ucidef function to do network ifname config" >&2
- exit 0
- fi
- }
- for ifname in $(ls /sys/class/net/); do
- p="/sys/class/net/$ifname"
- mac="$(cat "$p/address")"
- if [ "${macs#*,$mac}" != "$macs" ]; then
- oc_set_ifname "lan$i" "$ifname"
- i="$(($i + 1))"
- fi
- done
- board_config_flush
- exit 0
- `, macs)
- return d.putBoardConfig(rootFs, f, c)
- }
- return nil
- }
- func (d *SOpenWrtRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- ver, _ := rootFs.FileGetContents("/etc/openwrt_version", false)
- return &deployapi.ReleaseInfo{
- Distro: "OpenWrt",
- Version: string(ver),
- Arch: d.GetArch(rootFs),
- }
- }
- type SCoreOsRootFs struct {
- *sGuestRootFsDriver
- config *coreosutils.SCloudConfig
- }
- func NewCoreOsRootFs(part IDiskPartition) IRootFsDriver {
- return &SCoreOsRootFs{sGuestRootFsDriver: newGuestRootFsDriver(part)}
- }
- func (d *SCoreOsRootFs) GetName() string {
- return "CoreOs"
- }
- func (d *SCoreOsRootFs) String() string {
- return "CoreOsRootFs"
- }
- func (d *SCoreOsRootFs) GetOs() string {
- return "Linux"
- }
- func (d *SCoreOsRootFs) GetReleaseInfo(rootFs IDiskPartition) *deployapi.ReleaseInfo {
- return &deployapi.ReleaseInfo{
- Distro: "CoreOS",
- Version: "stable",
- }
- }
- func (d *SCoreOsRootFs) RootSignatures() []string {
- return []string{"cloud-config.yml"}
- }
- func (d *SCoreOsRootFs) PrepareFsForTemplate(rootFs IDiskPartition) error {
- return nil
- }
- func (d *SCoreOsRootFs) GetConfig() *coreosutils.SCloudConfig {
- if d.config == nil {
- d.config = coreosutils.NewCloudConfig()
- d.config.YunionInit()
- d.config.SetTimezone("Asia/Shanghai")
- }
- return d.config
- }
- func (d *SCoreOsRootFs) DeployHostname(rootFs IDiskPartition, hn, domain string) error {
- d.GetConfig().SetHostname(hn)
- return nil
- }
- func (d *SCoreOsRootFs) DeployPublicKey(rootFs IDiskPartition, selUsr string, pubkeys *deployapi.SSHKeys) error {
- return nil
- }
- func (d *SCoreOsRootFs) DeployHosts(rootFs IDiskPartition, hostname, domain string, ips []string) error {
- d.GetConfig().SetEtcHosts("localhost")
- return nil
- }
- func (d *SCoreOsRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*types.SServerNic) error {
- var netDevPrefix = GetNetDevPrefix(nics)
- for _, nic := range nics {
- name := fmt.Sprintf("%s%d", netDevPrefix, nic.Index)
- cont := "[Match]\n"
- cont += "Name=" + name + "\n"
- cont += "\n[Network]\n"
- cont += "DHCP=yes\n"
- if nic.Mtu > 0 {
- cont += "\n[Link]\n"
- cont += fmt.Sprintf("MTUBytes=%d\n", nic.Mtu)
- }
- runtime := true
- d.GetConfig().AddUnits("00-dhcp-"+name+".network", nil, nil, &runtime, cont, "", nil)
- }
- return nil
- }
- func (d *SCoreOsRootFs) DeployFstabScripts(rootFs IDiskPartition, disks []*deployapi.Disk) error {
- dataDiskIdx := 0
- for i := 1; i < len(disks); i++ {
- 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].Mountpoint
- if len(mtPath) == 0 {
- mtPath = "/data"
- if dataDiskIdx > 0 {
- mtPath += fmt.Sprintf("%d", dataDiskIdx)
- }
- dataDiskIdx += 1
- }
- d.GetConfig().AddPartition(dev, mtPath, fs)
- }
- }
- }
- return nil
- }
- func (d *SCoreOsRootFs) ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string, isRandomPassword bool) (string, error) {
- keys := []string{}
- if len(publicKey) > 0 {
- keys = append(keys, publicKey)
- }
- d.GetConfig().AddUser("core", password, keys, false)
- if len(publicKey) > 0 {
- return seclib2.EncryptBase64(publicKey, password)
- } else {
- return utils.EncryptAESBase64(gid, password)
- }
- }
- func (d *SCoreOsRootFs) GetLoginAccount(rootFs IDiskPartition, user string, defaultRootUser bool, windowsDefaultAdminUser bool) (string, error) {
- return "core", nil
- }
- func (d *SCoreOsRootFs) DeployFiles(deploys []*deployapi.DeployContent) error {
- for _, deploy := range deploys {
- d.GetConfig().AddWriteFile(deploy.Path, deploy.Content, "", "", false)
- }
- return nil
- }
- func (d *SCoreOsRootFs) CommitChanges(IDiskPartition) error {
- ocont, err := d.rootFs.FileGetContents("/cloud-config.yml", false)
- if err != nil {
- return err
- }
- ocfg := coreosutils.NewCloudConfig()
- err = yaml.Unmarshal(ocont, ocfg)
- if err != nil {
- log.Errorln(err)
- }
- conf := d.GetConfig()
- if len(ocfg.Users) > 0 {
- for _, u := range ocfg.Users {
- if conf.HasUser(u.Name) {
- conf.AddUser(u.Name, u.Passwd, u.SshAuthorizedKeys, true)
- }
- }
- }
- if len(ocfg.WriteFiles) > 0 {
- for _, f := range ocfg.WriteFiles {
- if !conf.HasWriteFile(f.Path) {
- conf.AddWriteFile(f.Path, f.Content, f.Permissions, f.Owner, f.Encoding == "base64")
- }
- }
- }
- return d.rootFs.FilePutContents("/cloud-config.yml", conf.String(), false, false)
- }
- func (d *SCoreOsRootFs) ConfigSshd(loginAccount, loginPassword string, sshPort int) error {
- return nil
- }
|