Files
2026-04-04 00:09:02 +08:00

455 lines
14 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"archive/zip"
"encoding/json"
"flag"
"fmt"
"log"
"os"
"strings"
"time"
)
func main() {
var out outputServerStruct
var err error
var errs []error
var showVer bool
var verbose bool
var isPlatform bool
var isLocation bool
version := "2603-01.8"
ticketName := flag.String("ticket", "not_number", "номер тикета isp")
flag.BoolVar(&showVer, "v", false, "версия")
flag.BoolVar(&showVer, "version", false, "версия")
flag.BoolVar(&verbose, "verbose", false, "подробно")
flag.BoolVar(&isPlatform, "platform", false, "будет запущен сбор данных по платформе")
flag.BoolVar(&isLocation, "location", false, "будет запущен сбор данных по локации")
hwName := flag.String("hw", "", "исследуемое оборудование пример -hw switch:13")
flag.Parse()
if showVer {
fmt.Println(version)
return
}
now := time.Now()
formatedNow := now.Format("2006-01-02_15-04")
outputDir := "isp_" + *ticketName + "_" + formatedNow
err = os.Mkdir(outputDir, 0644)
if err != nil {
log.Println(err)
outputDir = "."
}
logInfo, logWarn, logErr := createLogger(outputDir, verbose)
logInfo.Println("=====================СТАРТ СБОРА ДАННЫХ=====================")
// флаг номер тикета
logInfo.Println("Уточняем, что утилита запущена на сервере с платформой")
logInfo.Println("Получаем информацию о BIOS : bios_info")
out.BiosInfo, err = dmidecodeTSystem()
if err != nil {
logWarn.Println(err)
}
logInfo.Println("Получаем информацию об операционной системе: os_info")
out.OperatingSystem, errs = getOs()
// ставим OsRelease = NA значит вообще не получилось
if len(errs) > 0 {
for _, e := range errs {
logWarn.Println(e)
}
}
logInfo.Println("Получаем информацию об установленных пакетах: installed_packages")
if strings.Contains(out.OperatingSystem.OsRelease, "Ubuntu") || out.OperatingSystem.AstraVersion != "" {
out.InstalledPackages, err = getDebPackages()
if err != nil {
logWarn.Println(err)
}
} else {
out.InstalledPackages, err = getRpmPackages()
if err != nil {
logWarn.Println(err)
}
}
logInfo.Print("Получаем содержимое файла /root/.bash_history")
out.RootHistory, err = getRootHistory()
if err != nil {
logWarn.Println(err)
}
logInfo.Println("Получаем информацию о файловой системе сервера: fs_informations")
out.FsInformations, err = getFsInfo()
if err != nil {
logWarn.Println(err)
}
logInfo.Println("Получаем информацию о средней загрзке сервера: load_average")
out.LoadAverage, err = getLa()
if err != nil {
logWarn.Println(err)
}
logInfo.Println("Получаем информацию о процессоре: cpu")
out.Cpus, err = getCpuinfo()
if err != nil {
logWarn.Println(err)
}
logInfo.Println("Получаем информацию о памяти: ram")
out.Ram, err = getRam()
if err != nil {
logWarn.Println(err)
}
logInfo.Println("Получаем информацию об аптайме: uptime")
out.Uptime, err = getUptime()
if err != nil {
logWarn.Println(err)
}
logInfo.Println("Получаем информацию о службе времени: time_service")
out.TimeService, errs = getTimeService()
for _, e := range errs {
logWarn.Println(e)
}
logInfo.Println("Получаем информацию о записях в journalctl xe p4 since 1 day ago: journalctl_entries")
out.JournalctlEntries, err = getJournalctl()
if err != nil {
logWarn.Println(err)
}
logInfo.Println("Получаем информацию о фаерволах: firewalls")
out.Firewalls, err = getFirewalls()
if err != nil {
logWarn.Println(err)
}
logInfo.Println("Получаем информацию о правилах nftables nft list ruleset")
out.NftRuleset, errs = getNftRuleset(outputDir)
if err != nil {
logWarn.Println(err)
}
for _, err := range errs {
logWarn.Println(err)
}
logInfo.Println("Получаем информацию о сетевых настройках: network_config")
out.NetworkConfig, errs = getNetworkConf()
for _, e := range errs {
logWarn.Println(e)
}
logInfo.Println("Получаем информацию о доступности необходимых интернет-ресурсов: internet_required")
requiredResources := []string{"docker-registry.ispsystem.com", "download.docker.com", "download.ispsystem.com", "license.ispsystem.com", "metricreport.ispsystem.net"}
for _, ispUrl := range requiredResources {
ir, err := getInternetResource(ispUrl)
if err != nil {
logWarn.Println(err)
}
out.InternetRequired = append(out.InternetRequired, ir)
}
//TODO Тут проблемы, активные службы не попали в json
logInfo.Println("Получаем информацию о настройках безопасности")
if strings.Contains(out.OperatingSystem.OsRelease, "Ubuntu") {
out.SecSetUbuntu, err = getSecSettingsUbuntu()
if err != nil {
logWarn.Println(err)
}
} else if strings.Contains(out.OperatingSystem.OsRelease, "Alma") {
out.SecSetAlma, err = getSecSettingsAlma()
if err != nil {
logWarn.Println(err)
}
} else {
out.SecSetALSE, errs = getSecSettingsAlse()
for _, e := range errs {
logWarn.Println(e)
}
}
logInfo.Println("Получаем информацию docker ps -a")
out.DockerPsA, err = getDockerPsA()
if err != nil {
logWarn.Println(err)
}
logInfo.Println("Информация о ресурсах контейнеров docker stats -a --no-stream")
out.DockerStats, err = getDockerStats()
if err != nil {
logWarn.Println(err)
}
logInfo.Println("Получаем логи и статус supervisord")
out.DockerSupervisor, errs = getDockerSupervisordLog(out, outputDir)
for _, e := range errs {
logWarn.Println(e)
}
//
//
//
//
// Запаковываем в json
outJson, err := json.Marshal(out)
err = os.WriteFile(outputDir+"/server_information.json", outJson, 0644)
if err != nil {
logErr.Println(err)
}
//
//
//
//
//
// ПЛАТФОРМА
//
//
//
//
//
//
//
logInfo.Println("Начинаем сбор данных по ПЛАТФОРМЕ")
isPlatform, errs = isDciPlatform()
//
//
//
//
// НУЖНА ПРОВЕРКА
//
if len(errs) > 0 {
for _, e := range errs {
logWarn.Println(e)
}
logWarn.Println("В таком случае предположим, что сбор данных происходит на платформе")
isPlatform = true
}
//
//
//
//
//
//
//
if isPlatform {
var platformStruct outputPlatformStruct
runningSql, err := getRunningSqlServer()
// Если я не смогу определить какой sql то тут придётся упасть, а значит файлы нужно скопировать раньше
// И логи контейнеров получить тоже раньше
if err != nil {
logErr.Fatalln(err)
}
var ispDbname string
if runningSql.Type == "pgsql" {
ispDbname, err = checkIspDbname(runningSql)
if err != nil {
logErr.Fatalln(err)
}
}
logInfo.Println("Получаем информацию из таблицы dci_location")
platformStruct.DciLocations, errs = getDciLocationDB(ispDbname, runningSql)
for _, e := range errs {
logWarn.Println(e)
}
logInfo.Println("Получаем base64 docker-compose из таблицы dci_location")
platformStruct.DciLocationDockerComposes, errs = getDciLocationComposeDB(ispDbname, runningSql)
for _, e := range errs {
logWarn.Println(e)
}
//
logInfo.Println("Получаем информацию о задачах с ошибками за месяц")
platformStruct.TaskManagerTask, errs = getDciTaskMonthErrorsDB(ispDbname, runningSql)
for _, e := range errs {
logWarn.Println(e)
}
//
// Позволит прикинуть какие локации больше нагружены, и в целом нагрузку на платформу
logInfo.Println("Получаем информацию о количестве оборудования по локациям")
platformStruct.HwByLocations, errs = getDciLocationHWCountDB(ispDbname, runningSql, platformStruct)
for _, e := range errs {
logWarn.Println(e)
}
//
logInfo.Println("Получаем информацию об установленных плагинах")
platformStruct.InstalledPlugin, errs = getDciPluginsDB(ispDbname, runningSql)
for _, e := range errs {
logWarn.Println(e)
}
//
// Получаем просто количество пользователей, получать какую то ещё информацию о пользователях вредно
logInfo.Println("Получаем количество пользователей")
platformStruct.Users, err = getDciUsersCountDB(ispDbname, runningSql)
if err != nil {
logWarn.Println(err)
}
//
// Не забираем сами настройки ldap потому что они нам ничего особо не скажут, проверить мы их не можем, а сам факт передачи этой информации может смутить пользователя
logInfo.Println("Проверяем наличие настроек ldap")
platformStruct.Ldaps, errs = getDciLdapDB(ispDbname, runningSql)
for _, e := range errs {
logWarn.Println(e)
}
//
//
logInfo.Println("Получаем информацию о репозиториях операционных систем")
platformStruct.Repos, errs = getDciRepoDB(ispDbname, runningSql)
for _, e := range errs {
logWarn.Println(e)
}
//
logInfo.Println("Получаем шаблоны ОС из репозиториев не ispsystem")
platformStruct.OsTemplates, errs = getDciOsTemplatesDB(ispDbname, runningSql, platformStruct)
for _, e := range errs {
logWarn.Println(e)
}
//
logInfo.Println("Получаем инфорамцию о доверенных серверах в Real IP")
platformStruct.RealIP, err = getDciRealIpDB(ispDbname, runningSql)
if err != nil {
logWarn.Println(err)
}
//
//
logInfo.Println("Получаем информацию о заданиях резервного копирования платформы")
platformStruct.BackupTasks, errs = getDciBackupTask(ispDbname, runningSql)
for _, e := range errs {
logWarn.Println(e)
}
//
//получаем информацию о лицензии dci licensse check и dci license info пока что оптимальные варианты, но было бы лучше получить непосредственно код этих флагов и встроить его сюда.
logInfo.Println("Получаем информацию о лицензии")
platformStruct.License, errs = getLicenseInlfo()
for _, err := range errs {
logWarn.Println(err)
}
//
// Копируем файлы config.json и docker-compose.yaml, а также собираем имена всех файлов из /opt/ispsystem
var copiedFiles copiedFiles
logInfo.Println("Копируем config.json")
err = copyFiles("/opt/ispsystem/dci/config.json", outputDir+"/config.json")
if err != nil {
copiedFiles.Config = "error"
logWarn.Printf("Оибка при копировании файла config.json: %s", err)
} else {
copiedFiles.Config = "done"
}
logInfo.Println("Копируем install.log")
err = copyFiles("/opt/ispsystem/dci/install.log", outputDir+"/config.json")
if err != nil {
copiedFiles.InstallLog = "error"
logWarn.Printf("Оибка при копировании файла install.log: %s", err)
} else {
copiedFiles.InstallLog = "done"
}
logInfo.Println("Копируем docker-compose.yaml")
err = copyFiles("/opt/ispsystem/dci/docker-compose.yaml", outputDir+"/docker-compose.yaml")
if err != nil {
copiedFiles.PlatformDockerCompose = "error"
logWarn.Printf("Оибка при копировании файла docker-compose.yaml: %s", err)
} else {
copiedFiles.PlatformDockerCompose = "done"
}
logInfo.Println("Собираем названия файлов из директории /opt/ispsystem/")
ispFiles, errs := getIspFileNames("/opt/ispsystem/")
for _, er := range errs {
logWarn.Printf("Ошибка получения имени файла: %err", er)
}
copiedFiles.FileNames = ispFiles
platformStruct.CopiedFiles = copiedFiles
//
logInfo.Println("=====================КОНЕЦ СБОРА ДАННЫХ=====================")
outJsonPlatform, err := json.Marshal(platformStruct)
err = os.WriteFile(outputDir+"/dci_platform_information.json", outJsonPlatform, 0644)
if err != nil {
logErr.Println(err)
}
//
//
//
//
// HARDWARE
//
//
//
//
if *hwName != "" {
hw := strings.Split(*hwName, ":")
if len(hw) == 1 {
logErr.Printf("Оборудование %s указано неверно. Правильный формат оборудования \" -hw switch:13 \" где switch тип оборудования (switch, pdu, server, ups, san), а 13 его id", *hwName)
} else {
switch hw[0] {
case "server":
getHwServerInfo(runningSql, hw[1])
case "switch":
getHwSwitchInfo(runningSql, hw[1])
}
}
}
} else {
logWarn.Fatalln("Утилитиа запущена не на сервере платформы.")
}
//
//
//
//
//
// ЗАПАКОВКА РЕЗУЛЬТАТОВ В АРХИВ
//
//
//
//
//
outFiles, err := os.ReadDir(outputDir)
if err != nil {
fmt.Printf("Возникла ошибка %s при чтении %s из директории %s", err, outFiles, outputDir)
} else {
zipArchName := outputDir + ".zip"
fmt.Printf("Создаём архив %s\n", zipArchName)
newZipFile, err := os.Create(zipArchName)
if err != nil {
fmt.Printf("Ошибка %s создания архива %s", err, zipArchName)
defer newZipFile.Close()
} else {
zipWriter := zip.NewWriter(newZipFile)
for _, zFile := range outFiles {
err = addToArchive(zipWriter, outputDir+"/"+zFile.Name())
if err != nil {
fmt.Printf("Ошибка %s при добавлении файла %s в архив", err, zFile.Name())
}
}
err = zipWriter.Close()
}
defer newZipFile.Close()
}
}