package patch import ( "fmt" "strings" "github.com/beclab/Olares/cli/pkg/utils" "github.com/pkg/errors" "github.com/beclab/Olares/cli/pkg/common" "github.com/beclab/Olares/cli/pkg/core/connector" "github.com/beclab/Olares/cli/pkg/core/logger" "github.com/beclab/Olares/cli/pkg/core/util" ) type EnableSSHTask struct { common.KubeAction } func (t *EnableSSHTask) Execute(runtime connector.Runtime) error { stdout, _ := runtime.GetRunner().SudoCmd("systemctl is-active ssh", false, false) if stdout != "active" { if _, err := runtime.GetRunner().SudoCmd("systemctl enable --now ssh", false, false); err != nil { return err } } return nil } type PatchTask struct { common.KubeAction } func (t *PatchTask) Execute(runtime connector.Runtime) error { var cmd string var debianFrontend = "DEBIAN_FRONTEND=noninteractive" var pre_reqs = "apt-transport-https ca-certificates curl cifs-utils" if _, err := util.GetCommand(common.CommandGPG); err != nil { pre_reqs = pre_reqs + " gnupg " } if _, err := util.GetCommand(common.CommandSudo); err != nil { pre_reqs = pre_reqs + " sudo " } if _, err := util.GetCommand(common.CommandUpdatePciids); err != nil { pre_reqs = pre_reqs + " pciutils " } if _, err := util.GetCommand(common.CommandIptables); err != nil { pre_reqs = pre_reqs + " iptables " } if _, err := util.GetCommand(common.CommandIp6tables); err != nil { pre_reqs = pre_reqs + " iptables " } if _, err := util.GetCommand(common.CommandIpset); err != nil { pre_reqs = pre_reqs + " ipset " } if _, err := util.GetCommand(common.CommandNmcli); err != nil { pre_reqs = pre_reqs + " network-manager " } pre_reqs += " conntrack socat apache2-utils net-tools make gcc bison flex tree unzip " var systemInfo = runtime.GetSystemInfo() var platformFamily = systemInfo.GetOsPlatformFamily() var aptToolAvailable bool if _, err := util.GetCommand("add-apt-repository"); err == nil { aptToolAvailable = true } else { if _, err := runtime.GetRunner().SudoCmd("apt install -y software-properties-common", false, true); err == nil { aptToolAvailable = true } else { logger.Infof("software-properties-common not available, try to update apt sources ourself") } } var pkgManager = systemInfo.GetPkgManager() switch platformFamily { case common.Debian: sourceType := "deb" repoURL := "https://deb.debian.org/debian" suite := systemInfo.GetDebianVersionCode() components := []string{"contrib", "non-free"} if aptToolAvailable { cmd := fmt.Sprintf("add-apt-repository '%s %s %s %s' -y", sourceType, repoURL, suite, strings.Join(components, " ")) if _, err := runtime.GetRunner().SudoCmd(cmd, false, true); err != nil { return err } } else { err := utils.AddAptSource(sourceType, repoURL, suite, components) if err != nil { return err } } if systemInfo.IsDebianVersionEqual(connector.Debian13) { pre_reqs += " systemd-timesyncd " } else { pre_reqs += " ntpdate " } fallthrough case common.Ubuntu: if systemInfo.IsUbuntu() { if !systemInfo.IsPveOrPveLxc() && !systemInfo.IsRaspbian() { if _, err := runtime.GetRunner().SudoCmd("add-apt-repository universe -y", false, true); err != nil { logger.Errorf("add os repo error %v", err) return err } if _, err := runtime.GetRunner().SudoCmd("add-apt-repository multiverse -y", false, true); err != nil { logger.Errorf("add os repo error %v", err) return err } } pre_reqs += " ntpdate " } if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s update -qq", pkgManager), false, true); err != nil { logger.Errorf("update os error %v", err) return err } logger.Debug("apt update success") if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s install -y -qq %s", pkgManager, pre_reqs), false, true); err != nil { logger.Errorf("install deps %s error %v", pre_reqs, err) return err } if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s %s install -y %s", debianFrontend, pkgManager, cmd), false, true); err != nil { logger.Errorf("install deps %s error %v", cmd, err) return err } if _, err := runtime.GetRunner().SudoCmd("update-pciids", false, true); err != nil { return fmt.Errorf("failed to update-pciids: %v", err) } if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s %s install -y openssh-server", debianFrontend, pkgManager), false, true); err != nil { logger.Errorf("install deps %s error %v", cmd, err) return err } case common.CentOs, common.Fedora, common.RHEl: cmd = "conntrack socat httpd-tools ntpdate net-tools make gcc openssh-server" if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s install -y %s", pkgManager, cmd), false, true); err != nil { logger.Errorf("install deps %s error %v", cmd, err) return err } } return nil } type CorrectHostname struct { common.KubeAction } func (t *CorrectHostname) Execute(runtime connector.Runtime) error { hostName := runtime.GetSystemInfo().GetHostname() if !utils.ContainsUppercase(hostName) { return nil } hostname := strings.ToLower(hostName) if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("hostnamectl set-hostname %s", hostname), false, false); err != nil { return err } runtime.GetSystemInfo().SetHostname(hostname) return nil } type RaspbianCheckTask struct { common.KubeAction } func (t *RaspbianCheckTask) Execute(runtime connector.Runtime) error { // if util.IsExist(common.RaspbianCmdlineFile) || util.IsExist(common.RaspbianFirmwareFile) { systemInfo := runtime.GetSystemInfo() if systemInfo.IsRaspbian() { if _, err := util.GetCommand(common.CommandIptables); err != nil { _, err = runtime.GetRunner().SudoCmd("apt install -y iptables", false, false) if err != nil { logger.Errorf("%s install iptables error %v", common.Raspbian, err) return err } _, err = runtime.GetRunner().Cmd("systemctl disable --user gvfs-udisks2-volume-monitor", false, true) if err != nil { logger.Errorf("%s exec error %v", common.Raspbian, err) return err } _, err = runtime.GetRunner().Cmd("systemctl stop --user gvfs-udisks2-volume-monitor", false, true) if err != nil { logger.Errorf("%s exec error %v", common.Raspbian, err) return err } if !systemInfo.CgroupCpuEnabled() || !systemInfo.CgroupMemoryEnabled() { return fmt.Errorf("cpu or memory cgroups disabled, please edit /boot/cmdline.txt or /boot/firmware/cmdline.txt and reboot to enable it") } } } return nil } type DisableLocalDNSTask struct { common.KubeAction } func (t *DisableLocalDNSTask) Execute(runtime connector.Runtime) error { switch runtime.GetSystemInfo().GetOsPlatformFamily() { case common.Ubuntu, common.Debian: stdout, _ := runtime.GetRunner().SudoCmd("systemctl is-active systemd-resolved", false, false) if stdout == "active" { _, _ = runtime.GetRunner().SudoCmd("systemctl stop systemd-resolved.service", false, true) _, _ = runtime.GetRunner().SudoCmd("systemctl disable systemd-resolved.service", false, true) if utils.IsExist("/usr/bin/systemd-resolve") { _, _ = runtime.GetRunner().SudoCmd("mv /usr/bin/systemd-resolve /usr/bin/systemd-resolve.bak", false, true) } ok, err := utils.IsSymLink("/etc/resolv.conf") if err != nil { logger.Errorf("check /etc/resolv.conf error %v", err) return err } if ok { if _, err := runtime.GetRunner().SudoCmd("unlink /etc/resolv.conf && touch /etc/resolv.conf", false, true); err != nil { logger.Errorf("unlink /etc/resolv.conf error %v", err) return err } } if err = t.configResolvConf(runtime); err != nil { logger.Errorf("config /etc/resolv.conf error %v", err) return err } } else { if _, err := runtime.GetRunner().SudoCmd("cat /etc/resolv.conf > /etc/resolv.conf.bak", false, true); err != nil { logger.Errorf("backup /etc/resolv.conf error %v", err) return err } httpCode, _ := utils.GetHttpStatus("https://www.apple.com") if httpCode != 200 { if err := t.configResolvConf(runtime); err != nil { logger.Errorf("config /etc/resolv.conf error %v", err) return err } } } } sysInfo := runtime.GetSystemInfo() localIp := sysInfo.GetLocalIp() hostname := sysInfo.GetHostname() if stdout, _ := runtime.GetRunner().SudoCmd("hostname -i &>/dev/null", false, true); stdout == "" { if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("echo %s %s >> /etc/hosts", localIp, hostname), false, true); err != nil { return errors.Wrap(err, "failed to set hostname mapping") } } if runtime.GetSystemInfo().IsWsl() { _, _ = runtime.GetRunner().SudoCmd("chattr +i /etc/hosts /etc/resolv.conf", false, false) } return nil } func (t *DisableLocalDNSTask) configResolvConf(runtime connector.Runtime) error { var err error var cmd string var secondNameserverOp string overrideOp := ">" appendOp := ">>" var internalDNS string if util.IsOnAliyunECS() { internalDNS = "100.100.10.12" } else if util.IsOnAWSEC2() { internalDNS = "169.254.169.253" } else if util.IsOnTencentCVM() { internalDNS = "183.60.83.19" } if internalDNS != "" { secondNameserverOp = appendOp cmd = fmt.Sprintf("echo 'nameserver %s' > /etc/resolv.conf", internalDNS) if _, err = runtime.GetRunner().SudoCmd(cmd, false, true); err != nil { logger.Errorf("exec %s error %v", cmd, err) return err } } else { secondNameserverOp = overrideOp } primaryDNSServer, secondaryDNSServer := "1.1.1.1", "114.114.114.114" if strings.Contains(t.KubeConf.Arg.RegistryMirrors, common.OlaresRegistryMirrorHost) || strings.Contains(t.KubeConf.Arg.RegistryMirrors, common.OlaresRegistryMirrorHostLegacy) { primaryDNSServer, secondaryDNSServer = secondaryDNSServer, primaryDNSServer } cmd = fmt.Sprintf("echo 'nameserver %s' %s /etc/resolv.conf", primaryDNSServer, secondNameserverOp) if _, err = runtime.GetRunner().SudoCmd(cmd, false, true); err != nil { logger.Errorf("exec %s error %v", cmd, err) return err } cmd = fmt.Sprintf("echo 'nameserver %s' >> /etc/resolv.conf", secondaryDNSServer) if _, err = runtime.GetRunner().SudoCmd(cmd, false, true); err != nil { logger.Errorf("exec %s error %v", cmd, err) return err } return nil }