first
This commit is contained in:
BIN
DCIManager6/dci6-support/dci6-support
Executable file
BIN
DCIManager6/dci6-support/dci6-support
Executable file
Binary file not shown.
37
DCIManager6/dci6-support/go.mod
Normal file
37
DCIManager6/dci6-support/go.mod
Normal file
@@ -0,0 +1,37 @@
|
||||
module dci6-support
|
||||
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.24.4
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/containerd/errdefs v1.0.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/go-connections v0.6.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-sql-driver/mysql v1.9.3 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/pgx/v5 v5.7.6 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/moby/api v1.52.0 // indirect
|
||||
github.com/moby/moby/client v0.2.1 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
|
||||
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||
golang.org/x/crypto v0.37.0 // indirect
|
||||
golang.org/x/sync v0.13.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
)
|
||||
66
DCIManager6/dci6-support/go.sum
Normal file
66
DCIManager6/dci6-support/go.sum
Normal file
@@ -0,0 +1,66 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
||||
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
|
||||
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
|
||||
github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/moby/api v1.52.0 h1:00BtlJY4MXkkt84WhUZPRqt5TvPbgig2FZvTbe3igYg=
|
||||
github.com/moby/moby/api v1.52.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc=
|
||||
github.com/moby/moby/client v0.2.1 h1:1Grh1552mvv6i+sYOdY+xKKVTvzJegcVMhuXocyDz/k=
|
||||
github.com/moby/moby/client v0.2.1/go.mod h1:O+/tw5d4a1Ha/ZA/tPxIZJapJRUS6LNZ1wiVRxYHyUE=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
|
||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
15
DCIManager6/dci6-support/hw_info.go
Normal file
15
DCIManager6/dci6-support/hw_info.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
func getHwServerInfo(runningSql runningSqlServer, server_id string) (hwServer, error) {
|
||||
var hwS hwServer
|
||||
var err error
|
||||
|
||||
return hwS, err
|
||||
}
|
||||
|
||||
func getHwSwitchInfo(runningSql runningSqlServer, server_id string) (hwServer, error) {
|
||||
var hwS hwServer
|
||||
var err error
|
||||
|
||||
return hwS, err
|
||||
}
|
||||
1
DCIManager6/dci6-support/hw_server_info.go
Normal file
1
DCIManager6/dci6-support/hw_server_info.go
Normal file
@@ -0,0 +1 @@
|
||||
package main
|
||||
62
DCIManager6/dci6-support/hw_struct.go
Normal file
62
DCIManager6/dci6-support/hw_struct.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package main
|
||||
|
||||
type hwServer struct {
|
||||
Id int `json:"id"`
|
||||
Status string `json:"status"`
|
||||
// StatusInfo string `json:"status"` везде NULL надо по возможности посмотреть на боевых платформах
|
||||
Warehouse int `json:"warehouse"`
|
||||
Uuid string `json:"uuid"`
|
||||
Barcode string `json:"barcode"`
|
||||
SerialNumber string `json:"serial_number"`
|
||||
Note string `json:"note"`
|
||||
CustomField string `json:"custom_field"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
WarehouseStatus string `json:"warehouse_status"`
|
||||
Name string `json:"name"`
|
||||
Rack int `json:"rack"`
|
||||
Unit float64 `json:"unit"`
|
||||
Mac string `json:"mac"`
|
||||
MainIpv4 int `json:"main_ipv4"` // по возможности получить из таблицы ip
|
||||
MainIpv6 int `json:"main_ipv6"` // по возможности получить из таблицы ip
|
||||
UserNote string `json:"user_note"`
|
||||
OsTemplate string `json:"os_template"`
|
||||
HardwareInfo string `json:"hardware_info"`
|
||||
PerformInfo string `json:"perform_info"`
|
||||
Settings string `json:"settings"`
|
||||
Model string `json:"model"`
|
||||
Configuration string `json:"configuration"`
|
||||
CustomConfiguration string `json:"custom_configuration"`
|
||||
IsCustomConfiguration int `json:"is_custom_configuration"`
|
||||
Platform int `json:"platform"` //получить платформу из таблицы
|
||||
// Owner
|
||||
}
|
||||
|
||||
type hwSwitch struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Hostname string `json:"hostname"`
|
||||
Note string `json:"note"`
|
||||
Rack int `json:"rack"`
|
||||
Location int `json:"location"`
|
||||
Status string `json:"status"`
|
||||
StatusInfo string `json:"status_info"`
|
||||
Warehouse string `json:"warehouse"`
|
||||
WarehouseStatus string `json:"warehouse_status"`
|
||||
WarehouseStatusInfo string `json:"warehouse_status_info"`
|
||||
Device string `json:"device"`
|
||||
AdditionalInfo string `json:"additional_info"`
|
||||
Unit float64 `json:"unit"`
|
||||
Size float64 `json:"size"`
|
||||
LastUpdate string `json:"last_update"`
|
||||
LastSuccessUpdate string `json:"last_success_update"`
|
||||
AggregationAllowed int `json:"aggregation_allowed"`
|
||||
Model string `json:"model"`
|
||||
WarehousePortCount int `json:"warehouse_port_count"`
|
||||
ExploitationStatus string `json:"exploitation_status"`
|
||||
CustomParams string `json:"custom_params"`
|
||||
CustomField string `json:"custom_field"`
|
||||
Weight float64 `json:"weight"`
|
||||
ConnectedPduId int `json:"connected_pdu_id"`
|
||||
ConnectedUpsId int `json:"connected_ups_id"`
|
||||
TaskmgrTask []taskManagerTask `json:"taskmgr_tasks"`
|
||||
}
|
||||
1
DCIManager6/dci6-support/hw_switch_info.go
Normal file
1
DCIManager6/dci6-support/hw_switch_info.go
Normal file
@@ -0,0 +1 @@
|
||||
package main
|
||||
79
DCIManager6/dci6-support/isPlatformOrLocation.go
Normal file
79
DCIManager6/dci6-support/isPlatformOrLocation.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/moby/moby/client"
|
||||
)
|
||||
|
||||
func isDciPlatform() (bool, []error) {
|
||||
var result bool
|
||||
var errors []error
|
||||
// наличие сервиса dci
|
||||
units, err := os.ReadDir("/run/systemd/units")
|
||||
dciService := false
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка доступа к директории systemd units: %s", err)
|
||||
errors = append(errors, err)
|
||||
err = nil
|
||||
dciService = false
|
||||
} else {
|
||||
for _, unit := range units {
|
||||
matched, _ := regexp.Match("dci.service", []byte(unit.Name()))
|
||||
if matched {
|
||||
dciService = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// наличие config.json
|
||||
configJson := false
|
||||
files, err := os.ReadDir("/opt/ispsystem/dci/")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при чтении директории opt ispsystem dci")
|
||||
errors = append(errors, err)
|
||||
err = nil
|
||||
configJson = false
|
||||
} else {
|
||||
for _, file := range files {
|
||||
matched, _ := regexp.Match("config.json", []byte(file.Name()))
|
||||
if matched {
|
||||
configJson = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// запущенный контейнер dci_back
|
||||
dciBack := false
|
||||
apiClient, err := client.New(client.FromEnv)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при создании docker клиента %s", err)
|
||||
errors = append(errors, err)
|
||||
err = nil
|
||||
} else {
|
||||
defer apiClient.Close()
|
||||
containers, err := apiClient.ContainerList(context.Background(), client.ContainerListOptions{All: true})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка получения списка контейнеров : %s", err)
|
||||
errors = append(errors, err)
|
||||
err = nil
|
||||
} else {
|
||||
for _, ctr := range containers.Items {
|
||||
if ctr.Names[0] == "/dci_back" {
|
||||
dciBack = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if dciService {
|
||||
result = true
|
||||
} else if configJson {
|
||||
result = true
|
||||
} else if dciBack {
|
||||
result = true
|
||||
} else {
|
||||
result = false
|
||||
}
|
||||
return result, errors
|
||||
}
|
||||
3
DCIManager6/dci6-support/location-info.go
Normal file
3
DCIManager6/dci6-support/location-info.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
// Просканировать с сервера порты на Локации
|
||||
454
DCIManager6/dci6-support/main.go
Normal file
454
DCIManager6/dci6-support/main.go
Normal file
@@ -0,0 +1,454 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
52
DCIManager6/dci6-support/misc.go
Normal file
52
DCIManager6/dci6-support/misc.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func createLogger(logDir string, verbose bool) (*log.Logger, *log.Logger, *log.Logger) {
|
||||
logFile, err := os.OpenFile(logDir+"/dci_support_info.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
log.Println("Failed to open log file:", err)
|
||||
logInfo := log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
logWarn := log.New(os.Stdout, "WARN: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
logErr := log.New(os.Stderr, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
return logInfo, logWarn, logErr
|
||||
} else {
|
||||
if verbose {
|
||||
mw := io.MultiWriter(os.Stdout, logFile)
|
||||
mwErr := io.MultiWriter(os.Stderr, logFile)
|
||||
log.SetOutput(mw)
|
||||
logInfo := log.New(mw, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
logWarn := log.New(mw, "WARN: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
logErr := log.New(mwErr, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
return logInfo, logWarn, logErr
|
||||
} else {
|
||||
log.SetOutput(logFile)
|
||||
logInfo := log.New(logFile, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
logWarn := log.New(logFile, "WARN: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
logErr := log.New(logFile, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
return logInfo, logWarn, logErr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addToArchive(zipWriter *zip.Writer, filename string) error {
|
||||
fileToZip, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fileToZip.Close()
|
||||
|
||||
w, err := zipWriter.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(w, fileToZip); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
2
DCIManager6/dci6-support/notes.md
Normal file
2
DCIManager6/dci6-support/notes.md
Normal file
@@ -0,0 +1,2 @@
|
||||
компиляция со статической линковкой
|
||||
CGO_ENABLED=0 go build -a -ldflags="-s -w" -o dci6-support
|
||||
43
DCIManager6/dci6-support/outputStruct.go
Normal file
43
DCIManager6/dci6-support/outputStruct.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
type outputPlatformStruct struct {
|
||||
// IspSettings []ispSetting `json:"isp_settings"`
|
||||
DciLocations []dciLocation `json:"dci_locations"`
|
||||
DciLocationDockerComposes []dciLocationDockerCompose `json:"dci_location_dockercomposes"`
|
||||
TaskManagerTask []taskManagerTask `json:"task_manager_task"`
|
||||
HwByLocations []hwByLocation `json:"hw_by_locations"`
|
||||
InstalledPlugin []installedPlugin `json:"installed_plugin"`
|
||||
Users users `json:"users"`
|
||||
Ldaps []ldap `json:"ldaps"`
|
||||
Repos []repo `json:"repos"`
|
||||
OsTemplates []osTemplate `json:"os_template"`
|
||||
RealIP realIP `json:"real_ip"`
|
||||
BackupTasks []backupTask `json:"backup_tasks"`
|
||||
CopiedFiles copiedFiles `json:"copied_files"`
|
||||
License license `json:"license"`
|
||||
// ShowProcesslist []processlist `json:"show_processlist"`
|
||||
}
|
||||
|
||||
type outputServerStruct struct {
|
||||
BiosInfo biosInfo `json:"bios_info"`
|
||||
OperatingSystem operatingSystem `json:"operating_system"`
|
||||
InstalledPackages []installedPackage `json:"installed_packages"`
|
||||
FsInformations []fsInfo `json:"fs_informations"`
|
||||
LoadAverage loadAverage `json:"load_average"`
|
||||
Cpus []cpu `json:"cpu"`
|
||||
Ram ram `json:"ram"`
|
||||
Uptime uptime `json:"uptime"`
|
||||
TimeService timeService `json:"time_service"`
|
||||
JournalctlEntries []journalctlEntry `json:"journalctl_entries"`
|
||||
Firewalls firewalls `json:"firewalls"`
|
||||
NetworkConfig networkConfig `json:"network_config"`
|
||||
InternetRequired []internetResource `json:"internet_required"`
|
||||
SecSetALSE secSetALSE `json:"security_settings_alse"`
|
||||
SecSetUbuntu secSetUbuntu `json:"security_settings_ubuntu"`
|
||||
SecSetAlma secSetAlma `json:"security_settings_alma"`
|
||||
DockerPsA []dockerPs `json:"docker_ps_a"`
|
||||
DockerStats []dockerStats `json:"docker_stats"`
|
||||
DockerSupervisor []dockerSupervisor `json:"docker_supervisor"`
|
||||
NftRuleset nftRuleset `json:"nft_rulest"`
|
||||
RootHistory []rootHistoryCommand `json:"root_history_command"`
|
||||
}
|
||||
63
DCIManager6/dci6-support/platform-conf.go
Normal file
63
DCIManager6/dci6-support/platform-conf.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
func copyFiles(src, dst string) error {
|
||||
isSrcExist, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isSrcExist.Mode().IsRegular() {
|
||||
return &os.PathError{
|
||||
Op: "copy",
|
||||
Path: src,
|
||||
Err: errors.New("не является обычным файлом"),
|
||||
}
|
||||
}
|
||||
|
||||
source, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer source.Close()
|
||||
|
||||
destination, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer destination.Close()
|
||||
_, err = io.Copy(destination, source)
|
||||
return err
|
||||
}
|
||||
|
||||
func getIspFileNames(dirName string) ([]string, []error) {
|
||||
var fileList []string
|
||||
var errs []error
|
||||
|
||||
ispList, err := os.ReadDir(dirName)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при получении содержимого директории %s : %s", dirName, err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
}
|
||||
for _, entry := range ispList {
|
||||
dirPath := dirName + "/" + entry.Name()
|
||||
if entry.IsDir() {
|
||||
interList, interErrs := getIspFileNames(dirPath)
|
||||
for _, ie := range interErrs {
|
||||
errs = append(errs, ie)
|
||||
}
|
||||
for _, il := range interList {
|
||||
fileList = append(fileList, il)
|
||||
}
|
||||
}
|
||||
fileList = append(fileList, dirPath)
|
||||
}
|
||||
|
||||
return fileList, errs
|
||||
}
|
||||
133
DCIManager6/dci6-support/platformStruct.go
Normal file
133
DCIManager6/dci6-support/platformStruct.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package main
|
||||
|
||||
// type ispSetting struct {
|
||||
// // select name, value from isp_settings;
|
||||
// Name string `json:"name"`
|
||||
// Value string `json:"value"`
|
||||
// }
|
||||
|
||||
type dciLocation struct {
|
||||
// select id,status,status_info,name,ssh_address,ssh_port,ssh_user,setup_info,params_dhcp,params_redis,params_nginx,params_netflow,settings,is_main,proxy_params,userspace,patch from dci_1.dci_location;
|
||||
Id int `json:"id"`
|
||||
Status string `json:"status"`
|
||||
StatusInfo string `json:"status_info"`
|
||||
Name string `json:"name"`
|
||||
SshAddress string `json:"ssh_address"`
|
||||
SshPort int `json:"ssh_port"`
|
||||
SshUser string `json:"ssh_user"`
|
||||
SetupInfo string `json:"setup_info"`
|
||||
ParamsDhcp string `json:"params_dhcp"`
|
||||
ParamsRedis string `json:"params_redis"`
|
||||
ParamsNginx string `json:"params_nginx"`
|
||||
ParamsNetflow string `json:"params_netflow"`
|
||||
Settings string `json:"settings"`
|
||||
IsMain int `json:"is_main"`
|
||||
ProxyParams string `json:"proxy_params"`
|
||||
Userspace int `json:"userspace"`
|
||||
Patch string `json:"patch"`
|
||||
}
|
||||
|
||||
type dciLocationDockerCompose struct {
|
||||
// select id,name,docker_compose from dci_1.dci_location;
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
DockerCompose string `json:"docker_compose"`
|
||||
}
|
||||
|
||||
type taskManagerTask struct {
|
||||
// select id,name,status,registration_time from auth.taskmgr_task where status != 'complete' and registration_time >= NOW() - INTERVAL 1 MONTH;
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
RegistrationTime string `json:"registration_time"`
|
||||
RequestInfo string `json:"request_info"`
|
||||
Output string `json:"output"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type hwByLocation struct {
|
||||
// SELECT
|
||||
// (SELECT COUNT(id) from dci_server WHERE location = 2) as server,
|
||||
// (SELECT COUNT(id) from dci_switch WHERE location = 2) as switch,
|
||||
// (SELECT count(id) from dci_pdu WHERE location = 2) as pdu,
|
||||
// (SELECT COUNT(id) from dci_ups WHERE location = 2) as ups,
|
||||
// (SELECT COUNT(id) from dci_server WHERE location = 2) +
|
||||
// (SELECT COUNT(id) from dci_switch WHERE location = 2) +
|
||||
// (SELECT count(id) from dci_pdu WHERE location = 2) +
|
||||
// (SELECT COUNT(id) from dci_ups WHERE location = 2) as total_location_2;
|
||||
Location int `json:"location"`
|
||||
Server int `json:"server"`
|
||||
Switch int `json:"switch"`
|
||||
Pdu int `json:"pdu"`
|
||||
Ups int `json:"ups"`
|
||||
}
|
||||
|
||||
type installedPlugin struct {
|
||||
// select name,status,version,current_version from ps_plugin;
|
||||
Name string `json:"name"`
|
||||
Status string `json:"string"`
|
||||
Version string `json:"version"`
|
||||
CurrentVersion string `json:"current_version"`
|
||||
}
|
||||
|
||||
type users struct {
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
type ldap struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
LastSync string `json:"last_sync"`
|
||||
}
|
||||
|
||||
type repo struct {
|
||||
// SELECT id,name,url FROM dci_repo
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
type osTemplate struct {
|
||||
// SELECT id,name,filename,macro,metainfo,directory_name,repository,size from dci_os_template where repo != 1 /* репозиторий ispsystem*/
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Filename string `json:"filename"`
|
||||
Macro string `json:"macro"`
|
||||
Metainfo string `json:"metainfo"`
|
||||
DirectoryName string `json:"directory_name"`
|
||||
Repository int `json:"repository"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
// type processlist struct {
|
||||
// // SELECT * FROM information_schema.processlist WHERE COMMAND != 'Sleep' AND TIME > 0 ORDER BY TIME DESC;
|
||||
// Id int `json:"id"`
|
||||
// User string `json:"user"`
|
||||
// Host string `json:"host"`
|
||||
// Db string `json:"db"`
|
||||
// Command string `json:"command"`
|
||||
// Time int `json:"time"`
|
||||
// State string `json:"state"`
|
||||
// Info string `json:"info"`
|
||||
// }
|
||||
|
||||
type realIP struct {
|
||||
// SELECT name, value FROM auth.isp_settings WHERE name = "trusted_servers"
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type backupTask struct {
|
||||
// SELECT id,enabled,cron_expression,limit_count,limit_size_mib FROM backup_task
|
||||
Id int `json:"id"`
|
||||
Enabled int `json:"enabled"`
|
||||
CronExpression string `json:"cron_expression"`
|
||||
LimitCount int `json:"limit_count"`
|
||||
LimitSizeMib int `json:"limit_size_mib"`
|
||||
}
|
||||
|
||||
type copiedFiles struct {
|
||||
FileNames []string `json:"file_names"`
|
||||
Config string `json:"config"`
|
||||
PlatformDockerCompose string `json:"platform_docker_compose"`
|
||||
InstallLog string `json:"install_log"`
|
||||
}
|
||||
28
DCIManager6/dci6-support/platform_2602-2.go
Normal file
28
DCIManager6/dci6-support/platform_2602-2.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func getLicenseInlfo() (license, []error) {
|
||||
var errors []error
|
||||
var lic license
|
||||
|
||||
cmd := exec.Command("dci", "license", "check")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения команды dci license check : %s", err)
|
||||
errors = append(errors, err)
|
||||
}
|
||||
lic.LicenseCheck = string(output)
|
||||
|
||||
cmd = exec.Command("dci", "license", "info")
|
||||
output, err = cmd.Output()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения команды dci license info : %s", err)
|
||||
errors = append(errors, err)
|
||||
}
|
||||
lic.LicenseInfo = string(output)
|
||||
return lic, errors
|
||||
}
|
||||
579
DCIManager6/dci6-support/platform_info_fromDB.go
Normal file
579
DCIManager6/dci6-support/platform_info_fromDB.go
Normal file
@@ -0,0 +1,579 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getDciLocationDB(ispDbName string, runningSql runningSqlServer) ([]dciLocation, []error) {
|
||||
dbName := "dci_1"
|
||||
if ispDbName == "isp" {
|
||||
dbName = ispDbName
|
||||
}
|
||||
query := "SELECT id, status, COALESCE(status_info, 'null') as status_info, name, ssh_address, ssh_port, ssh_user, COALESCE(setup_info, 'null') as setup_info, COALESCE(params_dhcp, 'null') as params_dhcp, COALESCE(params_redis, 'null') as params_redis, COALESCE(params_nginx, 'null') as params_nginx, COALESCE(params_netflow, 'null') as params_netflow, COALESCE(settings, 'null') as settings, CASE WHEN is_main THEN 1 ELSE 0 END as is_main, COALESCE(proxy_params, '') as proxy_params, COALESCE(userspace, 0) as userspace, COALESCE(patch, 'null') as patch FROM dci_location;"
|
||||
|
||||
var errs []error
|
||||
var dl []dciLocation
|
||||
|
||||
if runningSql.Type == "mysql" {
|
||||
rows, db, err := mysqlQuery(query, dbName, runningSql)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблице %s.dci_location : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return dl, errs
|
||||
}
|
||||
defer db.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var dciLoc dciLocation
|
||||
err = rows.Scan(&dciLoc.Id, &dciLoc.Status, &dciLoc.StatusInfo, &dciLoc.Name, &dciLoc.SshAddress, &dciLoc.SshPort, &dciLoc.SshUser, &dciLoc.SetupInfo, &dciLoc.ParamsDhcp, &dciLoc.ParamsRedis, &dciLoc.ParamsNginx, &dciLoc.ParamsNetflow, &dciLoc.Settings, &dciLoc.IsMain, &dciLoc.ProxyParams, &dciLoc.Userspace, &dciLoc.Patch)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка сканирования результатов запроса в структуру dciLocation : %s", err.Error())
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
dl = append(dl, dciLoc)
|
||||
}
|
||||
} else if runningSql.Type == "pgsql" {
|
||||
rows, pool, err := pgsqlQuery(query, dbName, runningSql)
|
||||
// dbName dci_1
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблице %s.dci_location : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return dl, errs
|
||||
}
|
||||
defer pool.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var dciLoc dciLocation
|
||||
err = rows.Scan(&dciLoc.Id, &dciLoc.Status, &dciLoc.StatusInfo, &dciLoc.Name, &dciLoc.SshAddress, &dciLoc.SshPort, &dciLoc.SshUser, &dciLoc.SetupInfo, &dciLoc.ParamsDhcp, &dciLoc.ParamsRedis, &dciLoc.ParamsNginx, &dciLoc.ParamsNetflow, &dciLoc.Settings, &dciLoc.IsMain, &dciLoc.ProxyParams, &dciLoc.Userspace, &dciLoc.Patch)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка сканирования результатов запроса в структуру dciLocation : %s", err.Error())
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
dl = append(dl, dciLoc)
|
||||
}
|
||||
}
|
||||
return dl, errs
|
||||
}
|
||||
|
||||
func getDciLocationComposeDB(ispDbName string, runningSql runningSqlServer) ([]dciLocationDockerCompose, []error) {
|
||||
dbName := "dci_1"
|
||||
if ispDbName == "isp" {
|
||||
dbName = ispDbName
|
||||
}
|
||||
var errs []error
|
||||
var dlc []dciLocationDockerCompose
|
||||
query := "SELECT id,name,docker_compose FROM dci_location;"
|
||||
|
||||
switch runningSql.Type {
|
||||
case "mysql":
|
||||
rows, db, err := mysqlQuery(query, dbName, runningSql)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблице %s.dci_location : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return dlc, errs
|
||||
}
|
||||
defer db.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var dciLocCompose dciLocationDockerCompose
|
||||
err = rows.Scan(&dciLocCompose.Id, &dciLocCompose.Name, &dciLocCompose.DockerCompose)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру dciLocationDockerCompose : %s", err.Error())
|
||||
}
|
||||
dlc = append(dlc, dciLocCompose)
|
||||
}
|
||||
case "pgsql":
|
||||
rows, pool, err := pgsqlQuery(query, dbName, runningSql)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблице %s.dci_location : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return dlc, errs
|
||||
}
|
||||
defer rows.Close()
|
||||
defer pool.Close()
|
||||
for rows.Next() {
|
||||
var dciLocCompose dciLocationDockerCompose
|
||||
err = rows.Scan(&dciLocCompose.Id, &dciLocCompose.Name, &dciLocCompose.DockerCompose)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру dciLocationDockerCompose : %s", err.Error())
|
||||
}
|
||||
dlc = append(dlc, dciLocCompose)
|
||||
}
|
||||
}
|
||||
return dlc, errs
|
||||
}
|
||||
|
||||
func getDciTaskMonthErrorsDB(ispDbName string, runningSql runningSqlServer) ([]taskManagerTask, []error) {
|
||||
var tm []taskManagerTask
|
||||
var errs []error
|
||||
dbName := "auth"
|
||||
if ispDbName == "isp" {
|
||||
dbName = ispDbName
|
||||
}
|
||||
|
||||
switch runningSql.Type {
|
||||
case "mysql":
|
||||
query := "SELECT id,name,registration_time,request_info,output,status FROM taskmgr_task WHERE status != 'complete' AND registration_time >= NOW() - INTERVAL 1 MONTH;"
|
||||
rows, db, err := mysqlQuery(query, dbName, runningSql)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблице %s.taskmgr_task : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return tm, errs
|
||||
}
|
||||
defer rows.Close()
|
||||
defer db.Close()
|
||||
for rows.Next() {
|
||||
var taskManagerFailed taskManagerTask
|
||||
err = rows.Scan(&taskManagerFailed.Id, &taskManagerFailed.Name, &taskManagerFailed.RegistrationTime, &taskManagerFailed.RequestInfo, &taskManagerFailed.Output, &taskManagerFailed.Status)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру taskManagerFailed : %s", err.Error())
|
||||
}
|
||||
tm = append(tm, taskManagerFailed)
|
||||
}
|
||||
case "pgsql":
|
||||
query := "SELECT id,name,registration_time,request_info,output,status FROM taskmgr_task WHERE status != 'complete' AND registration_time >= NOW() - INTERVAL '1 MONTH';"
|
||||
rows, pool, err := pgsqlQuery(query, dbName, runningSql)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблице %s.taskmgr_task : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return tm, errs
|
||||
}
|
||||
defer rows.Close()
|
||||
defer pool.Close()
|
||||
for rows.Next() {
|
||||
|
||||
var taskManagerFailed taskManagerTask
|
||||
err = rows.Scan(&taskManagerFailed.Id, &taskManagerFailed.Name, &taskManagerFailed.RegistrationTime, &taskManagerFailed.RequestInfo, &taskManagerFailed.Output, &taskManagerFailed.Status)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру taskManagerFailed : %s", err.Error())
|
||||
}
|
||||
log.Println(taskManagerFailed.Id)
|
||||
tm = append(tm, taskManagerFailed)
|
||||
}
|
||||
}
|
||||
|
||||
return tm, errs
|
||||
}
|
||||
|
||||
func getDciLocationHWCountDB(ispDbName string, runningSql runningSqlServer, platformStruct outputPlatformStruct) ([]hwByLocation, []error) {
|
||||
var hw []hwByLocation
|
||||
var errs []error
|
||||
dbName := "dci_1"
|
||||
if ispDbName == "isp" {
|
||||
dbName = ispDbName
|
||||
}
|
||||
|
||||
// dbName dci_1
|
||||
for _, loc := range platformStruct.DciLocations {
|
||||
locId := strconv.Itoa(loc.Id)
|
||||
query := "select (SELECT COUNT(id) FROM dci_server WHERE location = " + locId + ") AS server, (SELECT COUNT(id) FROM dci_switch WHERE location = " + locId + ") AS switch, (SELECT count(id) FROM dci_pdu WHERE location = " + locId + ") AS pdu, (SELECT COUNT(id) FROM dci_ups WHERE location = " + locId + ") AS ups;"
|
||||
switch runningSql.Type {
|
||||
case "mysql":
|
||||
rows, db, err := mysqlQuery(query, dbName, runningSql)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблицам с оборудованиям : %s", err.Error())
|
||||
errs = append(errs, err)
|
||||
return hw, errs
|
||||
}
|
||||
defer db.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var hwByLocation hwByLocation
|
||||
err = rows.Scan(&hwByLocation.Server, &hwByLocation.Switch, &hwByLocation.Pdu, &hwByLocation.Ups)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру hwByLocation: %s", err.Error())
|
||||
}
|
||||
hwByLocation.Location = loc.Id
|
||||
hw = append(hw, hwByLocation)
|
||||
}
|
||||
case "pgsql":
|
||||
rows, pool, err := pgsqlQuery(query, dbName, runningSql)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблицам с оборудованием : %s", err.Error())
|
||||
errs = append(errs, err)
|
||||
return hw, errs
|
||||
}
|
||||
defer pool.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var hwByLocation hwByLocation
|
||||
err = rows.Scan(&hwByLocation.Server, &hwByLocation.Switch, &hwByLocation.Pdu, &hwByLocation.Ups)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру hwByLocation: %s", err.Error())
|
||||
}
|
||||
hwByLocation.Location = loc.Id
|
||||
hw = append(hw, hwByLocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
return hw, errs
|
||||
}
|
||||
|
||||
func getDciPluginsDB(ispDbName string, runningSql runningSqlServer) ([]installedPlugin, []error) {
|
||||
var ip []installedPlugin
|
||||
var errs []error
|
||||
dbName := "auth"
|
||||
if ispDbName == "isp" {
|
||||
dbName = ispDbName
|
||||
}
|
||||
query := "SELECT COALESCE(name, 'null'), COALESCE(status, 'null'), COALESCE(version, 'null'), COALESCE(current_version, 'null') from ps_plugin;"
|
||||
switch runningSql.Type {
|
||||
case "mysql":
|
||||
rows, db, err := mysqlQuery(query, dbName, runningSql)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблице %s.ps_plugin : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return ip, errs
|
||||
}
|
||||
defer db.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var instPlug installedPlugin
|
||||
err = rows.Scan(&instPlug.Name, &instPlug.Status, &instPlug.Version, &instPlug.CurrentVersion)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру installedPlugin : %s", err.Error())
|
||||
errs = append(errs, err)
|
||||
}
|
||||
ip = append(ip, instPlug)
|
||||
}
|
||||
case "pgsql":
|
||||
rows, pool, err := pgsqlQuery(query, dbName, runningSql)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблице %s.ps_plugin : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return ip, errs
|
||||
}
|
||||
defer pool.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var instPlug installedPlugin
|
||||
err = rows.Scan(&instPlug.Name, &instPlug.Status, &instPlug.Version, &instPlug.CurrentVersion)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру installedPlugin : %s", err.Error())
|
||||
errs = append(errs, err)
|
||||
}
|
||||
ip = append(ip, instPlug)
|
||||
}
|
||||
}
|
||||
return ip, errs
|
||||
}
|
||||
|
||||
func getDciUsersCountDB(ispDbName string, runningSql runningSqlServer) (users, error) {
|
||||
var u users
|
||||
var err error
|
||||
dbName := "auth"
|
||||
if ispDbName == "isp" {
|
||||
dbName = ispDbName
|
||||
}
|
||||
|
||||
query := "SELECT COUNT(id) FROM auth_user;"
|
||||
switch runningSql.Type {
|
||||
case "mysql":
|
||||
rows, db, err := mysqlQuery(query, dbName, runningSql)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблице %s.auth_user : %s", dbName, err.Error())
|
||||
return u, err
|
||||
}
|
||||
defer db.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
err = rows.Scan(&u.Count)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру users")
|
||||
if rows != nil {
|
||||
rows.Close()
|
||||
}
|
||||
return u, err
|
||||
}
|
||||
}
|
||||
case "pgsql":
|
||||
rows, pool, err := pgsqlQuery(query, dbName, runningSql)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблице %s.auth_user : %s", dbName, err.Error())
|
||||
return u, err
|
||||
}
|
||||
defer pool.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
err = rows.Scan(&u.Count)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру users")
|
||||
if rows != nil {
|
||||
rows.Close()
|
||||
}
|
||||
return u, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return u, err
|
||||
}
|
||||
|
||||
func getDciLdapDB(ispDbName string, runningSql runningSqlServer) ([]ldap, []error) {
|
||||
var ldaps []ldap
|
||||
var errs []error
|
||||
dbName := "auth"
|
||||
if ispDbName == "isp" {
|
||||
dbName = ispDbName
|
||||
}
|
||||
query := "SELECT id,name,last_sync FROM auth_ldap;"
|
||||
switch runningSql.Type {
|
||||
case "mysql":
|
||||
rows, db, err := mysqlQuery(query, dbName, runningSql)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при выполнении запроса к %s.auth_ldap : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return ldaps, errs
|
||||
}
|
||||
defer db.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var ldap ldap
|
||||
err = rows.Scan(&ldap.Id, &ldap.Name, &ldap.LastSync)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при записи структуры ldap : %s", err.Error())
|
||||
errs = append(errs, err)
|
||||
}
|
||||
ldaps = append(ldaps, ldap)
|
||||
}
|
||||
case "pgsql":
|
||||
rows, pool, err := pgsqlQuery(query, dbName, runningSql)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при выполнении запроса к %s.auth_ldap : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return ldaps, errs
|
||||
}
|
||||
defer pool.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var ldap ldap
|
||||
err = rows.Scan(&ldap.Id, &ldap.Name, &ldap.LastSync)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при записи структуры ldap : %s", err.Error())
|
||||
errs = append(errs, err)
|
||||
}
|
||||
ldaps = append(ldaps, ldap)
|
||||
}
|
||||
}
|
||||
return ldaps, errs
|
||||
}
|
||||
|
||||
func getDciRepoDB(ispDbName string, runningSql runningSqlServer) ([]repo, []error) {
|
||||
var repos []repo
|
||||
var errs []error
|
||||
query := "SELECT id,name,url FROM dci_repo"
|
||||
dbName := "dci_1"
|
||||
if ispDbName == "isp" {
|
||||
dbName = ispDbName
|
||||
}
|
||||
|
||||
switch runningSql.Type {
|
||||
case "mysql":
|
||||
rows, db, err := mysqlQuery(query, dbName, runningSql)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к %s.dci_repo : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return repos, errs
|
||||
}
|
||||
defer db.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var repo repo
|
||||
err = rows.Scan(&repo.Id, &repo.Name, &repo.Url)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка запписи в структуру repo : %s", err.Error())
|
||||
errs = append(errs, err)
|
||||
}
|
||||
repos = append(repos, repo)
|
||||
}
|
||||
case "pgsql":
|
||||
rows, pool, err := pgsqlQuery(query, dbName, runningSql)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к %s.dci_repo : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return repos, errs
|
||||
}
|
||||
defer pool.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var repo repo
|
||||
err = rows.Scan(&repo.Id, &repo.Name, &repo.Url)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка запписи в структуру repo : %s", err.Error())
|
||||
errs = append(errs, err)
|
||||
}
|
||||
repos = append(repos, repo)
|
||||
}
|
||||
}
|
||||
return repos, errs
|
||||
}
|
||||
|
||||
func getDciOsTemplatesDB(ispDbName string, runningSql runningSqlServer, platformStruct outputPlatformStruct) ([]osTemplate, []error) {
|
||||
var ispRepSlice []string
|
||||
for _, r := range platformStruct.Repos {
|
||||
if strings.Contains(r.Url, "download.ispsystem.com") {
|
||||
ispRepSlice = append(ispRepSlice, strconv.Itoa(r.Id))
|
||||
}
|
||||
}
|
||||
ispRep := strings.Join(ispRepSlice, ",")
|
||||
var osTemplates []osTemplate
|
||||
var errs []error
|
||||
query := "SELECT id,name,filename,macro,metainfo,directory_name,repository,size from dci_os_template where repository not in (" + ispRep + ");"
|
||||
dbName := "dci_1"
|
||||
if ispDbName == "isp" {
|
||||
dbName = ispDbName
|
||||
}
|
||||
switch runningSql.Type {
|
||||
case "mysql":
|
||||
rows, db, err := mysqlQuery(query, dbName, runningSql)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при выполнении запроса к %s.dci_os_template : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return osTemplates, errs
|
||||
}
|
||||
defer db.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var ostempl osTemplate
|
||||
err = rows.Scan(&ostempl.Id, &ostempl.Name, &ostempl.Filename, &ostempl.Macro, &ostempl.Metainfo, &ostempl.DirectoryName, &ostempl.Repository, &ostempl.Size)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру osTemplate : %s", err.Error())
|
||||
errs = append(errs, err)
|
||||
}
|
||||
osTemplates = append(osTemplates, ostempl)
|
||||
}
|
||||
case "pgsql":
|
||||
rows, pool, err := pgsqlQuery(query, dbName, runningSql)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при выполнении запроса к %s.dci_os_template : %s", dbName, err.Error())
|
||||
errs = append(errs, err)
|
||||
return osTemplates, errs
|
||||
}
|
||||
defer pool.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var ostempl osTemplate
|
||||
err = rows.Scan(&ostempl.Id, &ostempl.Name, &ostempl.Filename, &ostempl.Macro, &ostempl.Metainfo, &ostempl.DirectoryName, &ostempl.Repository, &ostempl.Size)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру osTemplate : %s", err.Error())
|
||||
errs = append(errs, err)
|
||||
}
|
||||
osTemplates = append(osTemplates, ostempl)
|
||||
}
|
||||
}
|
||||
|
||||
return osTemplates, errs
|
||||
}
|
||||
|
||||
func getDciRealIpDB(ispDbName string, runningSql runningSqlServer) (realIP, error) {
|
||||
dbName := "dci_1"
|
||||
if ispDbName == "isp" {
|
||||
dbName = ispDbName
|
||||
}
|
||||
var ri realIP
|
||||
var err error
|
||||
query := "SELECT name, value FROM isp_settings WHERE name = 'trusted_servers';"
|
||||
|
||||
switch runningSql.Type {
|
||||
case "mysql":
|
||||
// TODO Тут важно проверить, что это хранится в таблице isp_settings в базе dci_1, а не auth Эта таблица есть в обеих базах и там разные настройки
|
||||
rows, db, err := mysqlQuery(query, dbName, runningSql)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка запроса к %s.isp_settings : %s", dbName, err.Error())
|
||||
return ri, err
|
||||
}
|
||||
defer db.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var ri realIP
|
||||
err = rows.Scan(&ri.Name, &ri.Value)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру realIP : %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
case "pgsql":
|
||||
// TODO Тут важно проверить, что это хранится в таблице isp_settings в базе dci_1, а не auth Эта таблица есть в обеих базах и там разные настройки
|
||||
rows, pool, err := pgsqlQuery(query, dbName, runningSql)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка запроса к %s.isp_settings : %s", dbName, err.Error())
|
||||
return ri, err
|
||||
}
|
||||
defer pool.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var ri realIP
|
||||
err = rows.Scan(&ri.Name, &ri.Value)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру realIP : %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ri, err
|
||||
}
|
||||
|
||||
func getDciBackupTask(ispDbName string, runningSql runningSqlServer) ([]backupTask, []error) {
|
||||
var bts []backupTask
|
||||
var errs []error
|
||||
dbName := "auth"
|
||||
if ispDbName == "isp" {
|
||||
dbName = ispDbName
|
||||
}
|
||||
query := "SELECT id,enabled,cron_expression,limit_count,limit_size_mib FROM backup_task;"
|
||||
|
||||
switch runningSql.Type {
|
||||
case "mysql":
|
||||
rows, db, err := mysqlQuery(query, dbName, runningSql)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка запроса к %s.backup_task : %s", dbName, err)
|
||||
errs = append(errs, err)
|
||||
return bts, errs
|
||||
}
|
||||
defer db.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var bt backupTask
|
||||
err = rows.Scan(&bt.Id, &bt.Enabled, &bt.CronExpression, &bt.LimitCount, &bt.LimitSizeMib)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру backupTask : %s", err.Error())
|
||||
}
|
||||
bts = append(bts, bt)
|
||||
}
|
||||
case "pgsql":
|
||||
rows, pool, err := pgsqlQuery(query, dbName, runningSql)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка запроса к %s.backup_task : %s", dbName, err)
|
||||
errs = append(errs, err)
|
||||
return bts, errs
|
||||
}
|
||||
defer pool.Close()
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var bt backupTask
|
||||
err = rows.Scan(&bt.Id, &bt.Enabled, &bt.CronExpression, &bt.LimitCount, &bt.LimitSizeMib)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка записи в структуру backupTask : %s", err.Error())
|
||||
}
|
||||
bts = append(bts, bt)
|
||||
}
|
||||
}
|
||||
return bts, errs
|
||||
}
|
||||
6
DCIManager6/dci6-support/platform_struct_2602-2.go
Normal file
6
DCIManager6/dci6-support/platform_struct_2602-2.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package main
|
||||
|
||||
type license struct {
|
||||
LicenseCheck string `json:"license_check"`
|
||||
LicenseInfo string `json:"license_info"`
|
||||
}
|
||||
165
DCIManager6/dci6-support/serverStruct.go
Normal file
165
DCIManager6/dci6-support/serverStruct.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package main
|
||||
|
||||
type biosInfo struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type operatingSystem struct {
|
||||
OsRelease string `json:"os_name"`
|
||||
AstraVersion string `json:"astra_version"`
|
||||
AstraLicense string `json:"astra_license"`
|
||||
}
|
||||
|
||||
type installedPackage struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type fsInfo struct {
|
||||
MountPointDevice string `json:"mount_point_devices"`
|
||||
MountPointOsPath string `json:"mount_point_os_path"`
|
||||
MountPointSize uint64 `json:"mount_point_size"`
|
||||
MountPointFree uint64 `json:"mount_point_free"`
|
||||
}
|
||||
|
||||
type loadAverage struct {
|
||||
OneMin string `json:"la_onemin"`
|
||||
FiveMin string `json:"la_fivemin"`
|
||||
FifteenMin string `json:"la_fifteenmin"`
|
||||
Processes string `json:"la_processes"`
|
||||
}
|
||||
|
||||
// type cpu struct {
|
||||
// Model []string `json:"model"`
|
||||
// }
|
||||
type cpu struct {
|
||||
VendorId string `json:"vendor_id"`
|
||||
CpuFamily string `json:"cpu_family"`
|
||||
Model string `json:"model"`
|
||||
ModelName string `json:"model_name"`
|
||||
Stepping string `json:"stepping"`
|
||||
Microcode string `json:"microcode"`
|
||||
CpuMhz string `json:"cpu_mhz"`
|
||||
CacheSize string `json:"cache_size"`
|
||||
PhysicalId string `json:"phusical_id"`
|
||||
CpuCores string `json:"cpu_cores"`
|
||||
Flags string `json:"flags"`
|
||||
Bugs string `json:"bugs"`
|
||||
Bogomips string `json:"bogomips"`
|
||||
TlbSize string `json:"tlb_size"`
|
||||
ClflushSize string `json:"clflush_size"`
|
||||
CacheAlignment string `json:"cache_alignment"`
|
||||
AddressSize string `json:"address_size"`
|
||||
PowerManagement string `json:"power_management"`
|
||||
}
|
||||
|
||||
type ram struct {
|
||||
MemTotal string `json:"mem_total"`
|
||||
MemFree string `json:"mem_free"`
|
||||
MemAvailable string `json:"mem_available"`
|
||||
}
|
||||
|
||||
type uptime struct {
|
||||
WorkSeconds string `json:"work_seconds"`
|
||||
}
|
||||
|
||||
type timeService struct {
|
||||
TimeService string `json:"time_service"`
|
||||
TimeSync string `json:"time_sync"`
|
||||
}
|
||||
|
||||
type journalctlEntry struct {
|
||||
Timestamp string `json:"__REALTIME_TIMESTAMP"`
|
||||
CommandLine string `json:"_CMDLINE"`
|
||||
CommandName string `json:"_COMM"`
|
||||
SyslogIdentifier string `json:"SYSLOG_IDENTIFIER"`
|
||||
Message string `json:"MESSAGE"`
|
||||
}
|
||||
|
||||
type firewalls struct {
|
||||
Ufw string `json:"ufw"`
|
||||
Nftables string `json:"nftables"`
|
||||
Iptables string `json:"iptables"`
|
||||
Firewalld string `json:"firewalld"`
|
||||
}
|
||||
|
||||
type netInterface struct {
|
||||
Device string `json:"device"`
|
||||
Flags string `json:"flags"`
|
||||
HwAddr string `json:"hardware_address"`
|
||||
IpAddr []string `json:"ip_addr"`
|
||||
Index string `json:"index"`
|
||||
MTU string `json:"mtu"`
|
||||
}
|
||||
|
||||
type networkConfig struct {
|
||||
NetInterfaces []netInterface `json:"net_interfaces"`
|
||||
NetworkManager string `json:"networkmanager"`
|
||||
NetworkManagerConn []string `json:"networkmanager_conn"`
|
||||
Networking string `json:"networking"`
|
||||
EtcHosts []string `json:"etc_hosts"`
|
||||
}
|
||||
|
||||
type internetResource struct {
|
||||
Name string `json:"name"`
|
||||
Http string `json:"http"`
|
||||
Https string `json:"https"`
|
||||
IpList string `json:"ip_list"`
|
||||
}
|
||||
|
||||
type secSetALSE struct {
|
||||
Apparmor string `json:"apparmor"`
|
||||
Selinux string `json:"selinux"`
|
||||
Parsec string `json:"parsec"`
|
||||
Mic string `json:"astra_mic"`
|
||||
Mac string `json:"astra_mac"`
|
||||
Digsig string `json:"digsig"`
|
||||
Sudo string `json:"sudo"`
|
||||
Nochmodx string `json:"nochmodx"`
|
||||
Interpret string `json:"interpret"`
|
||||
SudoersAstraAdmin string `json:"sudoers_astraadmin"`
|
||||
SudoersSudo string `json:"sudoers_sudo"`
|
||||
AstraAdmin string `json:"astra-admin"`
|
||||
}
|
||||
|
||||
type secSetUbuntu struct {
|
||||
Apparmor string `json:"apparmor"`
|
||||
}
|
||||
|
||||
type secSetAlma struct {
|
||||
Selinux string `json:"selinux"`
|
||||
}
|
||||
|
||||
type dockerPs struct {
|
||||
Id string `json:"id"`
|
||||
Image string `json:"image"`
|
||||
Names []string `json:"names"`
|
||||
Created int64 `json:"running_for"`
|
||||
State string `json:"state"`
|
||||
Status string `json:"status"`
|
||||
// Health string `json:"health"`
|
||||
}
|
||||
|
||||
type dockerStats struct {
|
||||
BlockIO string `json:"BlockIO"`
|
||||
CPUPerc string `json:"CPUPerc"`
|
||||
Container string `json:"Container"`
|
||||
ID string `json:"ID"`
|
||||
MemPerc string `json:"MemPerc"`
|
||||
MemUsage string `json:"MemUsage"`
|
||||
Name string `json:"Name"`
|
||||
NetIO string `json:"NetIO"`
|
||||
PIDs string `json:"PIDs"`
|
||||
}
|
||||
|
||||
type dockerSupervisor struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SupStatus string `json:"sup_status"`
|
||||
}
|
||||
|
||||
type rootHistoryCommand struct {
|
||||
Id int `json:"id"`
|
||||
ExecutionTime string `json:"excution_time"`
|
||||
Command string `json:"command"`
|
||||
}
|
||||
600
DCIManager6/dci6-support/server_info.go
Normal file
600
DCIManager6/dci6-support/server_info.go
Normal file
@@ -0,0 +1,600 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
// "bufio"
|
||||
// "fmt"
|
||||
// "io/ioutil"
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ОС серверов Платформа и Локации
|
||||
// (источник ОС)
|
||||
// - Серверная платформа
|
||||
// dmidecode -t system
|
||||
|
||||
func dmidecodeTSystem() (biosInfo, error) {
|
||||
var biosInfo biosInfo
|
||||
// нужно получить информацию из bios
|
||||
// cat /sys/firmware/dmi/entries/1-0/raw
|
||||
bi, err := os.ReadFile("/sys/firmware/dmi/entries/1-0/raw")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка получения dmi данных: %s", err)
|
||||
}
|
||||
biosInfo.Name = string(bi)
|
||||
return biosInfo, nil
|
||||
|
||||
}
|
||||
|
||||
// - Операционная система
|
||||
// cat /etc/os-release
|
||||
// cat /etc/astra_version
|
||||
// cat /etc/astra_license
|
||||
|
||||
func getOs() (operatingSystem, []error) {
|
||||
var opsys operatingSystem
|
||||
var errors []error
|
||||
|
||||
fOsInfo, err := os.ReadFile("/etc/os-release")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка чтения os-release: %s", err)
|
||||
errors = append(errors, err)
|
||||
} else {
|
||||
osInfoSpl := strings.Split(string(fOsInfo), "\n")
|
||||
for _, r := range osInfoSpl {
|
||||
capt, _ := regexp.MatchString("PRETTY_NAME*", r)
|
||||
if capt {
|
||||
opsys.OsRelease = strings.Split(r, "=")[1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
_, err = os.Stat("/etc/astra_version")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("ошибка чтения asrta_version")
|
||||
errors = append(errors, err)
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
return opsys, errors
|
||||
}
|
||||
|
||||
// - Пакеты
|
||||
// apt list --installed
|
||||
|
||||
func getDebPackages() ([]installedPackage, error) {
|
||||
// читаем /var/lib/dpkg/status
|
||||
var debPackages []installedPackage
|
||||
|
||||
b_dpkgStatus, err := os.ReadFile("/var/lib/dpkg/status")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка чтения файла /var/lib/dpkg/status: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dpkgStatus := strings.Split(string(b_dpkgStatus), "\n\n")
|
||||
for _, ds := range dpkgStatus {
|
||||
var debPackage installedPackage
|
||||
if len(ds) == 0 {
|
||||
continue
|
||||
}
|
||||
ds_s := strings.Split(ds, "\n")
|
||||
for _, d := range ds_s {
|
||||
if strings.Contains(d, "Package: ") {
|
||||
debPackage.Name = strings.Split(d, ": ")[1]
|
||||
}
|
||||
if strings.Contains(d, "Version: ") {
|
||||
debPackage.Version = strings.Split(d, ": ")[1]
|
||||
}
|
||||
}
|
||||
debPackages = append(debPackages, debPackage)
|
||||
}
|
||||
|
||||
return debPackages, err
|
||||
}
|
||||
|
||||
func getRpmPackages() ([]installedPackage, error) {
|
||||
var rpmPackages []installedPackage
|
||||
|
||||
cmd := exec.Command("rpm", "-qa", "--queryformat", "%{NAME};%{VERSION}\n")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выпонения команды rpm -qa: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
scanner := bufio.NewScanner(strings.NewReader(string(output)))
|
||||
for scanner.Scan() {
|
||||
var instpack installedPackage
|
||||
line := scanner.Text()
|
||||
parts := strings.Split(line, ";")
|
||||
instpack.Name = parts[0]
|
||||
instpack.Version = parts[1]
|
||||
rpmPackages = append(rpmPackages, instpack)
|
||||
}
|
||||
return rpmPackages, err
|
||||
}
|
||||
|
||||
// - Размер диска и объем свободного места на диске
|
||||
// lsblk
|
||||
// df
|
||||
// df -i
|
||||
|
||||
func getFsInfo() ([]fsInfo, error) {
|
||||
var fsInfoList []fsInfo
|
||||
fProcMounts, err := os.ReadFile("/proc/mounts")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка чтения файла /proc/mounts : %s", err)
|
||||
return fsInfoList, err
|
||||
}
|
||||
for _, mp := range strings.Split(string(fProcMounts), "\n") {
|
||||
var fi fsInfo
|
||||
var sysStatfs syscall.Statfs_t
|
||||
if len(mp) == 0 {
|
||||
continue
|
||||
}
|
||||
mp_s := strings.Split(mp, " ")
|
||||
fi.MountPointDevice = mp_s[0]
|
||||
fi.MountPointOsPath = mp_s[1]
|
||||
err = syscall.Statfs(fi.MountPointOsPath, &sysStatfs)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
} else {
|
||||
fi.MountPointSize = sysStatfs.Blocks * uint64(sysStatfs.Bsize)
|
||||
fi.MountPointFree = sysStatfs.Blocks * uint64(sysStatfs.Bfree)
|
||||
}
|
||||
fsInfoList = append(fsInfoList, fi)
|
||||
// fmt.Printf("Dev: %s Path: %s Size: %d Free: %d \n", fi.MountPointDevice, fi.MountPointOsPath, fi.MountPointSize, fi.MountPointFree)
|
||||
}
|
||||
return fsInfoList, err
|
||||
}
|
||||
|
||||
// - LA
|
||||
// top -bn1 | head -n 1
|
||||
// cat /proc/loadavg
|
||||
|
||||
func getLa() (loadAverage, error) {
|
||||
var la loadAverage
|
||||
laFile, err := os.ReadFile("/proc/loadavg")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("файл proc loadavg недоступен %s", err)
|
||||
return la, err
|
||||
}
|
||||
laFileSplit := strings.Split(string(laFile), " ")
|
||||
la.OneMin = laFileSplit[0]
|
||||
la.FiveMin = laFileSplit[1]
|
||||
la.FifteenMin = laFileSplit[2]
|
||||
la.Processes = laFileSplit[3]
|
||||
|
||||
return la, nil
|
||||
}
|
||||
|
||||
// - Процессор
|
||||
// cat /proc/cpuinfo
|
||||
// lscpu
|
||||
|
||||
// func getCpu() (cpu, error) {
|
||||
// var cpu cpu
|
||||
// cpuFile, err := os.ReadFile("/proc/cpuinfo")
|
||||
// if err != nil {
|
||||
// err = fmt.Errorf("Проблема с доступом к файлу proc cpuinfo %s", err)
|
||||
// return cpu, err
|
||||
// }
|
||||
// prevCpu := " "
|
||||
// for _, line := range strings.Split(string(cpuFile), "\n") {
|
||||
// matched, err := regexp.Match("model name", []byte(line))
|
||||
// if err != nil {
|
||||
// err = fmt.Errorf("Ошибка при оценке регулярного выражения %s", err)
|
||||
// return cpu, err
|
||||
// }
|
||||
// if matched {
|
||||
// cpuFound := strings.Split(line, ":")[1]
|
||||
// if cpuFound != prevCpu {
|
||||
// cpu.Model = append(cpu.Model, cpuFound)
|
||||
// prevCpu = cpuFound
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return cpu, nil
|
||||
// }
|
||||
func getCpuinfo() ([]cpu, error) {
|
||||
var cpus []cpu
|
||||
var err error
|
||||
rawCpuinfo, err := os.ReadFile("/proc/cpuinfo")
|
||||
|
||||
var c cpu
|
||||
var physId []string
|
||||
physId = append(physId, "a")
|
||||
for _, cpuLine := range strings.Split(string(rawCpuinfo), "\n") {
|
||||
if len(strings.TrimSpace(cpuLine)) == 0 {
|
||||
controlPoint := 0
|
||||
for _, arrayIndex := range physId {
|
||||
if c.PhysicalId == "" {
|
||||
controlPoint = 1
|
||||
}
|
||||
if arrayIndex == c.PhysicalId {
|
||||
controlPoint = 1
|
||||
}
|
||||
}
|
||||
if controlPoint == 0 {
|
||||
cpus = append(cpus, c)
|
||||
physId = append(physId, c.PhysicalId)
|
||||
c = cpu{}
|
||||
} else {
|
||||
c = cpu{}
|
||||
}
|
||||
} else {
|
||||
if strings.Contains(cpuLine, "vendor_id") {
|
||||
c.VendorId = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "cpu family") {
|
||||
c.CpuFamily = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "model") && !strings.Contains(cpuLine, "name") {
|
||||
c.Model = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "model name") {
|
||||
c.ModelName = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "stepping") {
|
||||
c.Stepping = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "microcode") {
|
||||
c.Microcode = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "cpu MHz") {
|
||||
c.CpuMhz = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "cache size") {
|
||||
c.CacheSize = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "physical id") {
|
||||
c.PhysicalId = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "cpu cores") {
|
||||
c.CpuCores = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "flags") {
|
||||
c.Flags = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "bugs") {
|
||||
c.Bugs = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "bogomips") {
|
||||
c.Bogomips = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "TLB size") {
|
||||
c.TlbSize = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "clflush size") {
|
||||
c.ClflushSize = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "cache_alignment") {
|
||||
c.CacheAlignment = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "address size") {
|
||||
c.AddressSize = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
if strings.Contains(cpuLine, "power management") {
|
||||
c.PowerManagement = strings.TrimSpace(strings.Split(cpuLine, ":")[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
return cpus, err
|
||||
}
|
||||
|
||||
// - Объём и тип ОЗУ, объём свободной памяти в моменте
|
||||
// vmstat -s
|
||||
// free
|
||||
// /proc/meminfo
|
||||
|
||||
func getRam() (ram, error) {
|
||||
var ram ram
|
||||
ramFile, err := os.ReadFile("/proc/meminfo")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Проблема с доступом к файлу proc meminfo %s", err)
|
||||
return ram, err
|
||||
}
|
||||
for _, line := range strings.Split(string(ramFile), "\n") {
|
||||
matched, _ := regexp.Match("MemTotal", []byte(line))
|
||||
if matched {
|
||||
ram.MemTotal = strings.Trim(strings.Split(line, ":")[1], " ")
|
||||
}
|
||||
matched, _ = regexp.Match("MemFree", []byte(line))
|
||||
if matched {
|
||||
ram.MemFree = strings.Trim(strings.Split(line, ":")[1], " ")
|
||||
}
|
||||
matched, _ = regexp.Match("Available", []byte(line))
|
||||
if matched {
|
||||
ram.MemAvailable = strings.Trim(strings.Split(line, ":")[1], " ")
|
||||
}
|
||||
}
|
||||
return ram, nil
|
||||
}
|
||||
|
||||
// - Uptime сервера
|
||||
// uptime
|
||||
|
||||
func getUptime() (uptime, error) {
|
||||
var uptime uptime
|
||||
uptimeFile, err := os.ReadFile("/proc/uptime")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка досутпа к файлу proc uptime: %s", err)
|
||||
return uptime, err
|
||||
}
|
||||
uptime.WorkSeconds = strings.Split(string(uptimeFile), " ")[0]
|
||||
return uptime, nil
|
||||
}
|
||||
|
||||
// - NTP (nrp ntpsec chrony)
|
||||
// Запущен ли сервис, выполнялась ли синхронизация
|
||||
// date -R на всех серверах инфраструктуры
|
||||
|
||||
func getTimeService() (timeService, []error) {
|
||||
var timeService timeService
|
||||
var errors []error
|
||||
cmd := exec.Command("timedatectl", "show", "--property=NTPSynchronized")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка получения данных timedatectl: %s", err)
|
||||
errors = append(errors, err)
|
||||
err = nil
|
||||
}
|
||||
timeService.TimeSync = strings.Trim(strings.Split(string(output), "=")[1], "\n")
|
||||
dir, err := os.ReadDir("/run/systemd/units")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при получении содержимого run systemd units : %s", err)
|
||||
errors = append(errors, err)
|
||||
err = nil
|
||||
} else {
|
||||
for _, entry := range dir {
|
||||
matchedChrony, _ := regexp.Match("chrony", []byte(entry.Name()))
|
||||
if matchedChrony {
|
||||
timeService.TimeService = strings.Split(entry.Name(), ":")[1]
|
||||
break
|
||||
}
|
||||
matchedNtp, _ := regexp.Match("ntp", []byte(entry.Name()))
|
||||
if matchedNtp {
|
||||
timeService.TimeService = strings.Split(entry.Name(), ":")[1]
|
||||
break
|
||||
}
|
||||
timeService.TimeService = "nothing"
|
||||
}
|
||||
}
|
||||
return timeService, errors
|
||||
}
|
||||
|
||||
// - Стандартный сбор ошибок
|
||||
// journalctl -xe -p4 -o json-pretty
|
||||
// dmesg -T --level=err,warn
|
||||
|
||||
// dmesg \| grep -i -E 'error\|failed\|critical\|bug\|panic' или dmesg --level=warn,err
|
||||
// journalctl \| grep -i -E 'error\|failed\|critical\|bug\|panic' или journalctl -xe -p 4 можно since "1 day ago" -o json-pretty
|
||||
// journalctl -xe -p 4 --since "1 day ago" -o json-pretty
|
||||
|
||||
func getJournalctl() ([]journalctlEntry, error) {
|
||||
var jList []journalctlEntry
|
||||
cmd := exec.Command("journalctl", "-xe", "-p 4", "--since", "1 day ago", "-o", "json-pretty")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения команды journalctl -xe -p 4 --since '5 minutes ago' -o json-pretty : %s", err)
|
||||
return jList, err
|
||||
}
|
||||
|
||||
outputSplited := strings.Split(string(output), "}\n{")
|
||||
for _, event := range outputSplited {
|
||||
var je journalctlEntry
|
||||
if len(event) == 0 {
|
||||
continue
|
||||
}
|
||||
event = strings.Trim(event, "{}")
|
||||
eventFull := "{" + event + "}"
|
||||
// err = json.Unmarshal([]byte(eventFull), &je)
|
||||
buf := bytes.NewBuffer([]byte(eventFull))
|
||||
err = json.NewDecoder(buf).Decode(&je)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка десериализации данных: %s в итерации %s", err, eventFull)
|
||||
return jList, err
|
||||
}
|
||||
jList = append(jList, je)
|
||||
}
|
||||
|
||||
return jList, nil
|
||||
}
|
||||
|
||||
// - Порты
|
||||
// nmap от Платформы к Локациям и наоборот
|
||||
// оставим пока, двигаем в самый низ, как реализовать пока не представляю. Нужны проверки портов с учетом фаерволов
|
||||
// возможно это будет выполнение в лоб команды docker exec -it dci_back dcissh -a "nmap"
|
||||
// пока вместо открытых портов проверим запущен ли фаервол
|
||||
|
||||
func getFirewalls() (firewalls, error) {
|
||||
var fwl firewalls
|
||||
units, err := os.ReadDir("/run/systemd/units")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при получении содержимого run systemd units : %s", err)
|
||||
return fwl, err
|
||||
} else {
|
||||
for _, unit := range units {
|
||||
ufw, _ := regexp.Match("ufw", []byte(unit.Name()))
|
||||
if ufw {
|
||||
fwl.Ufw = "running"
|
||||
}
|
||||
nftables, _ := regexp.Match("nftables", []byte(unit.Name()))
|
||||
if nftables {
|
||||
fwl.Nftables = "running"
|
||||
}
|
||||
iptables, _ := regexp.Match("iptables", []byte(unit.Name()))
|
||||
if iptables {
|
||||
fwl.Iptables = "running"
|
||||
}
|
||||
firewalld, _ := regexp.Match("firewalld", []byte(unit.Name()))
|
||||
if firewalld {
|
||||
fwl.Firewalld = "running"
|
||||
}
|
||||
}
|
||||
}
|
||||
return fwl, nil
|
||||
}
|
||||
|
||||
// - Настройки сети
|
||||
// NetworkManager
|
||||
// настройки интерфейсов
|
||||
// etc/hosts
|
||||
// etc/resolv.conf
|
||||
|
||||
func getNetworkConf() (networkConfig, []error) {
|
||||
var networkConfig networkConfig
|
||||
var errors []error
|
||||
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при получении сетевых интерфейсов: %s", err)
|
||||
errors = append(errors, err)
|
||||
err = nil
|
||||
} else {
|
||||
for _, interf := range interfaces {
|
||||
var netInterface netInterface
|
||||
netInterface.Device = interf.Name
|
||||
netInterface.Flags = interf.Flags.String()
|
||||
netInterface.HwAddr = interf.HardwareAddr.String()
|
||||
adrs, _ := interf.Addrs()
|
||||
for _, adr := range adrs {
|
||||
netInterface.IpAddr = append(netInterface.IpAddr, adr.String())
|
||||
}
|
||||
netInterface.Index = strconv.Itoa(interf.Index)
|
||||
netInterface.MTU = strconv.Itoa(interf.MTU)
|
||||
networkConfig.NetInterfaces = append(networkConfig.NetInterfaces, netInterface)
|
||||
// fmt.Printf("interf: %v\n", interf)
|
||||
}
|
||||
}
|
||||
|
||||
units, err := os.ReadDir("/run/systemd/units")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при получении содержимого run systemd units : %s", err)
|
||||
errors = append(errors, err)
|
||||
err = nil
|
||||
} else {
|
||||
for _, unit := range units {
|
||||
// Полчить статус NetworkManager
|
||||
matched, _ := regexp.Match("NetworkManager.services", []byte(unit.Name()))
|
||||
if matched {
|
||||
networkConfig.NetworkManager = "running"
|
||||
}
|
||||
// Полчить статус networking
|
||||
matchedNetworking, _ := regexp.Match("networking", []byte(unit.Name()))
|
||||
if matchedNetworking {
|
||||
networkConfig.Networking = "running"
|
||||
}
|
||||
}
|
||||
}
|
||||
nmConns, err := os.ReadDir("/run/NetworkManager/system-connections")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при получении содержимого run NetworkManager")
|
||||
errors = append(errors, err)
|
||||
err = nil
|
||||
} else {
|
||||
for _, nmConn := range nmConns {
|
||||
networkConfig.NetworkManagerConn = append(networkConfig.NetworkManagerConn, nmConn.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// Содержимое /etc/hosts
|
||||
linesByte, err := os.ReadFile("/etc/hosts")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при получении содержимого etc hosts : %s", err)
|
||||
errors = append(errors, err)
|
||||
err = nil
|
||||
} else {
|
||||
lines := strings.Split(string(linesByte), "\n")
|
||||
for _, line := range lines {
|
||||
if strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
} else {
|
||||
networkConfig.EtcHosts = append(networkConfig.EtcHosts, line)
|
||||
}
|
||||
}
|
||||
}
|
||||
return networkConfig, errors
|
||||
}
|
||||
|
||||
// Возможность доступа к основным ресурсам в internet
|
||||
// docker-registry.ispsystem.com, download.docker.com — для доступа к Docker;
|
||||
// download.ispsystem.com — для обновления и установки платформы;
|
||||
// license6.ispsystem.com — для проверки лицензий;
|
||||
// metricreport.ispsystem.net — для работы сервера метрик.
|
||||
|
||||
func getInternetResource(ispUrl string) (internetResource, error) {
|
||||
var ir internetResource
|
||||
var outErr error
|
||||
ipList, err := net.LookupIP(ispUrl)
|
||||
if err != nil {
|
||||
return ir, err
|
||||
}
|
||||
ir.Name = ispUrl
|
||||
var i []string
|
||||
for _, ip := range ipList {
|
||||
i = append(i, ip.String())
|
||||
}
|
||||
ir.IpList = strings.Join(i, ",")
|
||||
|
||||
httpUrl := "http://" + ispUrl
|
||||
httpsUrl := "https://" + ispUrl
|
||||
|
||||
resp, err := http.Get(httpUrl)
|
||||
if err != nil {
|
||||
outErr = fmt.Errorf("Ошибка HTTP %s :: %s. ", httpUrl, err)
|
||||
ir.Http = err.Error()
|
||||
} else {
|
||||
ir.Http = strconv.Itoa(resp.StatusCode)
|
||||
}
|
||||
|
||||
resp, err = http.Get(httpsUrl)
|
||||
if err != nil {
|
||||
outErr = fmt.Errorf("%s Ошибка HTTPS %s :: %s", outErr, httpUrl, err)
|
||||
ir.Https = err.Error()
|
||||
} else {
|
||||
ir.Https = strconv.Itoa(resp.StatusCode)
|
||||
}
|
||||
return ir, outErr
|
||||
}
|
||||
|
||||
// 2026-02.5 получить историю. просто прочитаем файл с историей bash у root
|
||||
|
||||
func getRootHistory() ([]rootHistoryCommand, error) {
|
||||
var rootHistoryCommands []rootHistoryCommand
|
||||
rawHistory, err := os.ReadFile("/root/.bash_history")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при открытии файла /root/.bash_history : %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
i := 0
|
||||
execTime := ""
|
||||
for _, line := range strings.Split(string(rawHistory), "\n") {
|
||||
var c rootHistoryCommand
|
||||
if strings.HasPrefix(line, "#") {
|
||||
execTime = strings.TrimLeft(line, "#")
|
||||
} else {
|
||||
c.Id = i
|
||||
i += 1
|
||||
c.ExecutionTime = execTime
|
||||
c.Command = line
|
||||
execTime = ""
|
||||
rootHistoryCommands = append(rootHistoryCommands, c)
|
||||
}
|
||||
|
||||
}
|
||||
return rootHistoryCommands, err
|
||||
}
|
||||
121
DCIManager6/dci6-support/server_info_docker.go
Normal file
121
DCIManager6/dci6-support/server_info_docker.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/moby/moby/client"
|
||||
)
|
||||
|
||||
func getDockerPsA() ([]dockerPs, error) {
|
||||
var dps []dockerPs
|
||||
var err error
|
||||
//
|
||||
apiClient, err := client.New(client.FromEnv)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при создании docker клиента %s", err)
|
||||
return dps, err
|
||||
}
|
||||
defer apiClient.Close()
|
||||
|
||||
containers, err := apiClient.ContainerList(context.Background(), client.ContainerListOptions{All: true})
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка получения списка контейнеров : %s", err)
|
||||
return dps, err
|
||||
}
|
||||
for _, ctr := range containers.Items {
|
||||
var dp dockerPs
|
||||
dp.Id = ctr.ID
|
||||
dp.Image = ctr.Image
|
||||
dp.Names = ctr.Names
|
||||
dp.Created = ctr.Created
|
||||
dp.State = string(ctr.State)
|
||||
dp.Status = ctr.Status
|
||||
// dp.Health = string(ctr.Health.Status)
|
||||
dps = append(dps, dp)
|
||||
}
|
||||
|
||||
return dps, err
|
||||
}
|
||||
|
||||
func getDockerStats() ([]dockerStats, error) {
|
||||
var ds []dockerStats
|
||||
var err error
|
||||
cmd := exec.Command("docker", "stats", "-a", "--no-stream", "--format", "{{ json . }}")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения docker stats -a --format \"{{ json . }}\"")
|
||||
return ds, err
|
||||
}
|
||||
for _, stat := range strings.Split(strings.TrimSpace(string(output)), "\n") {
|
||||
var docS dockerStats
|
||||
if stat == "" {
|
||||
continue
|
||||
}
|
||||
buf := bytes.NewBuffer([]byte(stat))
|
||||
err := json.NewDecoder(buf).Decode(&docS)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка десериализации переменной %v в строке %s", err, stat)
|
||||
return ds, err
|
||||
}
|
||||
ds = append(ds, docS)
|
||||
}
|
||||
|
||||
return ds, err
|
||||
}
|
||||
|
||||
func getDockerSupervisordLog(outputServerStruct outputServerStruct, outDir string) ([]dockerSupervisor, []error) {
|
||||
var dS []dockerSupervisor
|
||||
var errs []error
|
||||
|
||||
for _, d := range outputServerStruct.DockerStats {
|
||||
dSup := dockerSupervisor{
|
||||
Id: d.ID,
|
||||
Name: d.Name,
|
||||
}
|
||||
|
||||
// 1. Ищем supervisord.log
|
||||
cmd := exec.Command("docker", "exec", d.Name, "bash", "-c", "find / -name supervisord.log 2>/dev/null | head -1")
|
||||
output, err := cmd.Output()
|
||||
if err != nil || len(output) == 0 {
|
||||
errs = append(errs, fmt.Errorf("supervisord.log не найден в контейнере %s", d.Name))
|
||||
dS = append(dS, dSup)
|
||||
continue
|
||||
}
|
||||
|
||||
// Очищаем путь от пробелов и переносов
|
||||
logPath := strings.TrimSpace(string(output))
|
||||
|
||||
// 2. Читаем содержимое файла
|
||||
cmd = exec.Command("docker", "exec", d.Name, "bash", "-c", fmt.Sprintf("cat %s", logPath))
|
||||
logContent, err := cmd.Output()
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("ошибка чтения supervisord.log в %s: %s", d.Name, err.Error()))
|
||||
} else {
|
||||
// Сохраняем лог в файл
|
||||
supervisordLogFile := fmt.Sprintf("%s/%s_supervisord.log", outDir, d.Name)
|
||||
if err := os.WriteFile(supervisordLogFile, logContent, 0644); err != nil {
|
||||
errs = append(errs, fmt.Errorf("ошибка записи лога %s: %s", d.Name, err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Получаем supervisorctl status
|
||||
cmd = exec.Command("docker", "exec", d.Name, "bash", "-c", "supervisorctl status")
|
||||
status, err := cmd.Output()
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("ошибка supervisorctl status в %s: %s", d.Name, err.Error()))
|
||||
} else {
|
||||
dSup.SupStatus = string(status)
|
||||
}
|
||||
|
||||
dS = append(dS, dSup)
|
||||
}
|
||||
|
||||
return dS, errs
|
||||
}
|
||||
60
DCIManager6/dci6-support/server_info_firewalls.go
Normal file
60
DCIManager6/dci6-support/server_info_firewalls.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// для всех обычных фаерволов хватит двух команд
|
||||
// iptables --version если в ответе есть nf_tables (а это почти 100% случаев теперь), то просто команда
|
||||
// nft -j list ruleset
|
||||
// в ином случае можно добавить iptables -L
|
||||
// довольно сложный json, быстро у меня не получится его разоброать. Временно, я заберу просто вывод без json построчно
|
||||
// и так же, построчно отображу в читалке. Там даже в простом варианте из убунты, где их никто не настраивал, 590 строк.
|
||||
// значит пока что структура nfrRuleset
|
||||
// type nftRuleset struct {
|
||||
// Lines []string
|
||||
// }
|
||||
//
|
||||
|
||||
func getNftRuleset(dirName string) (nftRuleset, []error) {
|
||||
var rules nftRuleset
|
||||
var errs []error
|
||||
|
||||
cmd := exec.Command("nft", "list", "ruleset")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при выполнении команды fmt list ruleset : %v", err)
|
||||
errs = append(errs, err)
|
||||
return rules, errs
|
||||
}
|
||||
i := 0
|
||||
rulesFile, err := os.Create(dirName + "/nftListRuleset.txt")
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка создания файла nftListRuleset.txt : %v", err)
|
||||
errs = append(errs, err)
|
||||
for line := range strings.SplitSeq(string(output), "\n") {
|
||||
line = strconv.Itoa(i) + " " + strings.TrimSpace(line)
|
||||
rules.Lines = append(rules.Lines, line)
|
||||
i += 1
|
||||
}
|
||||
} else {
|
||||
for line := range strings.SplitSeq(string(output), "\n") {
|
||||
line = strings.TrimSpace(line) + "\n"
|
||||
_, err := rulesFile.WriteString(line)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при записи в файл nftListRuleset.txt")
|
||||
errs = append(errs, err)
|
||||
}
|
||||
line = strconv.Itoa(i) + " " + strings.TrimSpace(line)
|
||||
rules.Lines = append(rules.Lines, line)
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
defer rulesFile.Close()
|
||||
return rules, errs
|
||||
}
|
||||
8
DCIManager6/dci6-support/server_nft_struct.go
Normal file
8
DCIManager6/dci6-support/server_nft_struct.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package main
|
||||
|
||||
// я расчитываю в дальнейшем вернуться к этому. Json структура nftables непростая, поэтому я или разгадаю сам как её анмаршалить, или сопру из одной из двух библиотек на гитхабе. Или вообще их заиспользую.
|
||||
// пока что просто построчно выведу правила nft list ruleset
|
||||
|
||||
type nftRuleset struct {
|
||||
Lines []string `json:"lines"`
|
||||
}
|
||||
257
DCIManager6/dci6-support/server_sec_info.go
Normal file
257
DCIManager6/dci6-support/server_sec_info.go
Normal file
@@ -0,0 +1,257 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// - Безопасность
|
||||
//
|
||||
// ALSE
|
||||
//
|
||||
// parsec
|
||||
// astra-mic-control status
|
||||
// astra-mac-control status
|
||||
//
|
||||
// astra-digsig-control status
|
||||
// astra-sudo-control status
|
||||
// astra-nochmodx-lock status
|
||||
// astra-interpreters-lock status
|
||||
// etc/sudoers %astra-admin ALL=(ALL:ALL) NOPASSWD: ALL %sudo ALL=(ALL:ALL) NOPASSWD: ALL
|
||||
// группу astra-admin
|
||||
|
||||
// TODO команды astra-... status нужно проверить в файлах директории /parsecfs/
|
||||
|
||||
func getSecSettingsAlse() (secSetALSE, []error) {
|
||||
var secSet secSetALSE
|
||||
var errs []error
|
||||
//apparmor
|
||||
// parsec
|
||||
runSystemd, err := os.ReadDir("/run/systemd/units")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка чтения директории /run/systemd/units: %s", err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
}
|
||||
for _, run := range runSystemd {
|
||||
matchedPars, _ := regexp.Match("parsec", []byte(run.Name()))
|
||||
if matchedPars {
|
||||
secSet.Parsec = "active"
|
||||
}
|
||||
matchedApparm, _ := regexp.Match("apparmor", []byte(run.Name()))
|
||||
if matchedApparm {
|
||||
secSet.Apparmor = "active"
|
||||
}
|
||||
}
|
||||
// selinux
|
||||
if _, err := os.Stat("/etc/selinux/config"); errors.Is(err, os.ErrNotExist) {
|
||||
secSet.Selinux = "notexist"
|
||||
} else {
|
||||
seFile, err := os.ReadFile("/etc/selinux/config")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка. Файл selinux conf существует, но не может быть прочитан: %s", err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
}
|
||||
sestatus := 0
|
||||
for _, sf := range strings.Split(string(seFile), "\n") {
|
||||
matchedConfig, _ := regexp.Match(sf, []byte("byteSELINUX=disabled"))
|
||||
if matchedConfig {
|
||||
secSet.Selinux = "disabled"
|
||||
sestatus = 1
|
||||
}
|
||||
}
|
||||
if sestatus == 0 {
|
||||
secSet.Selinux = "enabled"
|
||||
}
|
||||
}
|
||||
// astra-mic-control status
|
||||
cmd := exec.Command("astra-mic-control", "is-enabled")
|
||||
mic, err := cmd.Output()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения astra-mic-control is-enabled : %s", err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
}
|
||||
secSet.Mic = string(mic)
|
||||
// astra-mac-control status
|
||||
cmd = exec.Command("astra-mac-control", "is-enabled")
|
||||
mac, err := cmd.Output()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения astra-mac-control is-enabled : %s", err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
}
|
||||
secSet.Mac = string(mac)
|
||||
// astra-digsig-control status
|
||||
if _, err := os.Stat("/etc/digsig/digsig_initramfs.conf"); errors.Is(err, os.ErrNotExist) {
|
||||
secSet.Digsig = "file notexist"
|
||||
} else {
|
||||
f, err := os.ReadFile("/etc/digsig/digsig_initramfs.conf")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка. Файл digsig_initramfs.conf существует, но не может быть прочитан: %s", err)
|
||||
errs = append(errs, err)
|
||||
}
|
||||
i := 0
|
||||
for _, sf := range strings.Split(string(f), "\n") {
|
||||
matchedConfig, _ := regexp.Match(sf, []byte("DIGSIG_ELF_MODE=0"))
|
||||
if matchedConfig {
|
||||
secSet.Digsig = "disabled"
|
||||
i = 1
|
||||
}
|
||||
}
|
||||
if i == 0 {
|
||||
secSet.Digsig = "enabled"
|
||||
}
|
||||
}
|
||||
|
||||
// astra-sudo-control status
|
||||
cmd = exec.Command("astra-sudo-control", "is-enabled")
|
||||
sudo, err := cmd.Output()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения astra-sudo-control is-enabled : %s", err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
}
|
||||
secSet.Sudo = string(sudo)
|
||||
// astra-nochmodx-lock status
|
||||
cmd = exec.Command("astra-nochmodx-control", "is-enabled")
|
||||
nochmodx, err := cmd.Output()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения astra-nochmodx-control is-enabled : %s", err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
}
|
||||
secSet.Nochmodx = string(nochmodx)
|
||||
// astra-interpreters-lock status
|
||||
cmd = exec.Command("astra-nochmodx-control", "is-enabled")
|
||||
interpret, err := cmd.Output()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения astra-interpreters-lock is-enabled : %s", err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
}
|
||||
secSet.Interpret = string(interpret)
|
||||
// etc/sudoers %astra-admin ALL=(ALL:ALL) NOPASSWD: ALL %sudo ALL=(ALL:ALL) NOPASSWD: ALL
|
||||
if _, err = os.Stat("/etc/sudoers"); errors.Is(err, os.ErrNotExist) {
|
||||
secSet.SudoersAstraAdmin = "file notexist"
|
||||
} else {
|
||||
f, err := os.ReadFile("/etc/sudoers")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка чтения файла etc sudoers: %s", err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
} else {
|
||||
i := 0
|
||||
for _, sf := range strings.Split(string(f), "\n") {
|
||||
matchedConfig, _ := regexp.Match(sf, []byte("%astra-admin ALL=(ALL:ALL) NOPASSWD: ALL"))
|
||||
if matchedConfig {
|
||||
secSet.SudoersAstraAdmin = "astra-admin nopass"
|
||||
i = 1
|
||||
}
|
||||
}
|
||||
if i == 0 {
|
||||
secSet.SudoersAstraAdmin = "astra-admin notnopass"
|
||||
}
|
||||
}
|
||||
}
|
||||
// etc/sudoers %sudo ALL=(ALL:ALL) NOPASSWD: ALL
|
||||
if _, err = os.Stat("/etc/sudoers"); errors.Is(err, os.ErrNotExist) {
|
||||
secSet.SudoersAstraAdmin = "file notexist"
|
||||
} else {
|
||||
f, err := os.ReadFile("/etc/sudoers")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка чтения файла etc sudoers: %s", err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
} else {
|
||||
i := 0
|
||||
for _, sf := range strings.Split(string(f), "\n") {
|
||||
matchedConfig, _ := regexp.Match(sf, []byte("%sudo ALL=(ALL:ALL) NOPASSWD: ALL"))
|
||||
if matchedConfig {
|
||||
secSet.SudoersSudo = "sudo nopass"
|
||||
i = 1
|
||||
}
|
||||
}
|
||||
if i == 0 {
|
||||
secSet.SudoersSudo = "astra-admin notnopass"
|
||||
}
|
||||
}
|
||||
}
|
||||
// группу astra-admin
|
||||
curUser, err := user.Current()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка получения данных о текущем пользователе: %s", err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
}
|
||||
curUserGroups, err := curUser.GroupIds()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка получения групп текущего пользователя: %s", err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
}
|
||||
for _, grpId := range curUserGroups {
|
||||
grp, err := user.LookupGroupId(grpId)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка получения информации о группе: %s", err)
|
||||
errs = append(errs, err)
|
||||
err = nil
|
||||
}
|
||||
if grp.Name == "astra-admin" {
|
||||
secSet.SudoersAstraAdmin = "astra-admin"
|
||||
}
|
||||
}
|
||||
return secSet, nil
|
||||
}
|
||||
|
||||
// Ubuntu apparmor
|
||||
|
||||
func getSecSettingsUbuntu() (secSetUbuntu, error) {
|
||||
var secSetUbuntu secSetUbuntu
|
||||
runSystemd, err := os.ReadDir("/run/systemd/units")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка чтения директории /run/systemd/units: %s", err)
|
||||
return secSetUbuntu, err
|
||||
}
|
||||
for _, run := range runSystemd {
|
||||
matched, _ := regexp.Match("apparmor", []byte(run.Name()))
|
||||
if matched {
|
||||
fmt.Println(run.Name())
|
||||
secSetUbuntu.Apparmor = "active"
|
||||
}
|
||||
}
|
||||
return secSetUbuntu, nil
|
||||
}
|
||||
|
||||
// Almalinux selinux
|
||||
|
||||
func getSecSettingsAlma() (secSetAlma, error) {
|
||||
var secSetAlma secSetAlma
|
||||
if _, err := os.Stat("/etc/selinux/config"); errors.Is(err, os.ErrNotExist) {
|
||||
secSetAlma.Selinux = "notexist"
|
||||
} else {
|
||||
seFile, err := os.ReadFile("/etc/selinux/config")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка. Файл selinux conf существует, но не может быть прочитан: %s", err)
|
||||
return secSetAlma, err
|
||||
}
|
||||
sestatus := 0
|
||||
for _, sf := range strings.Split(string(seFile), "\n") {
|
||||
matchedConfig, _ := regexp.Match("SELINUX=disabled", []byte(sf))
|
||||
if matchedConfig {
|
||||
secSetAlma.Selinux = "disabled"
|
||||
sestatus = 1
|
||||
}
|
||||
}
|
||||
if sestatus == 0 {
|
||||
secSetAlma.Selinux = "enabled"
|
||||
}
|
||||
}
|
||||
return secSetAlma, nil
|
||||
}
|
||||
172
DCIManager6/dci6-support/sqlInteract.go
Normal file
172
DCIManager6/dci6-support/sqlInteract.go
Normal file
@@ -0,0 +1,172 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"github.com/moby/moby/client"
|
||||
)
|
||||
|
||||
type runningSqlServer struct {
|
||||
Type string `json:"type"`
|
||||
IPaddr string `json:"ipaddr"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
func getRunningSqlServer() (runningSqlServer, error) {
|
||||
var runningSql runningSqlServer
|
||||
|
||||
// запущенный контейнер sql
|
||||
apiClient, err := client.New(client.FromEnv)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка при создании docker клиента %s", err)
|
||||
return runningSql, err
|
||||
}
|
||||
defer apiClient.Close()
|
||||
|
||||
// пробуем этот метод!
|
||||
ctx := context.Background()
|
||||
|
||||
containers, err := apiClient.ContainerList(ctx, client.ContainerListOptions{All: true})
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка получения списка контейнеров : %s", err)
|
||||
return runningSql, err
|
||||
}
|
||||
for _, ctr := range containers.Items {
|
||||
// println(ctr.Names[0])
|
||||
if ctr.Names[0] == "/mysql" {
|
||||
runningSql.Type = "mysql"
|
||||
for _, nets := range ctr.NetworkSettings.Networks {
|
||||
runningSql.IPaddr = nets.IPAddress.String()
|
||||
}
|
||||
|
||||
cont, err := apiClient.ContainerInspect(ctx, ctr.ID, client.ContainerInspectOptions{})
|
||||
if err != nil {
|
||||
return runningSql, err
|
||||
}
|
||||
|
||||
for _, e := range cont.Container.Config.Env {
|
||||
matched, _ := regexp.Match("PASSWORD", []byte(e))
|
||||
if matched {
|
||||
runningSql.Password = strings.Split(e, "=")[1]
|
||||
}
|
||||
}
|
||||
} else if ctr.Names[0] == "/pgsql" {
|
||||
runningSql.Type = "pgsql"
|
||||
for _, nets := range ctr.NetworkSettings.Networks {
|
||||
runningSql.IPaddr = nets.IPAddress.String()
|
||||
}
|
||||
|
||||
cont, err := apiClient.ContainerInspect(ctx, ctr.ID, client.ContainerInspectOptions{})
|
||||
if err != nil {
|
||||
return runningSql, err
|
||||
}
|
||||
for _, e := range cont.Container.Config.Env {
|
||||
matched, _ := regexp.Match("POSTGRES_PASSWORD", []byte(e))
|
||||
if matched {
|
||||
runningSql.Password = strings.Split(e, "=")[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return runningSql, nil
|
||||
}
|
||||
|
||||
func checkIspDbname(runningSql runningSqlServer) (string, error) {
|
||||
var dbname string
|
||||
var dbnames []string
|
||||
query := "SELECT datname FROM pg_database;"
|
||||
rows, pool, err := pgsqlQuery(query, "postgres", runningSql)
|
||||
defer pool.Close()
|
||||
defer rows.Close()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса к таблице postgres : %s", err.Error())
|
||||
return dbname, err
|
||||
} else {
|
||||
for rows.Next() {
|
||||
var db string
|
||||
err = rows.Scan(&db)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка сканирования результатов запроса списка баз данных : %s", err.Error())
|
||||
return dbname, err
|
||||
// continue
|
||||
}
|
||||
dbnames = append(dbnames, db)
|
||||
}
|
||||
}
|
||||
// if rows != nil {
|
||||
// rows.Close()
|
||||
// }
|
||||
for _, d := range dbnames {
|
||||
if d == "isp" {
|
||||
dbname = "isp"
|
||||
}
|
||||
}
|
||||
return dbname, nil
|
||||
}
|
||||
|
||||
// func pgsqlQuery(query, dbname string, runningSql runningSqlServer) (pgx.Rows, error) {
|
||||
// dsn := "postgres://root:" + runningSql.Password + "@" + runningSql.IPaddr + ":5432/" + dbname
|
||||
// connect, err := pgx.Connect(context.Background(), dsn)
|
||||
|
||||
// err = connect.Ping(context.Background())
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// result, err := connect.Query(context.Background(), query)
|
||||
// if err != nil {
|
||||
// err = fmt.Errorf("Ошибка выполнения запроса к БД: %s", err)
|
||||
// return result, err
|
||||
// }
|
||||
|
||||
// defer connect.Close(context.Background())
|
||||
// return result, nil
|
||||
// }
|
||||
func pgsqlQuery(query, dbname string, runningSql runningSqlServer) (pgx.Rows, *pgxpool.Pool, error) {
|
||||
dsn := "postgres://root:" + runningSql.Password + "@" + runningSql.IPaddr + ":5432/" + dbname
|
||||
pool, err := pgxpool.New(context.Background(), dsn)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
rows, err := pool.Query(context.Background(), query)
|
||||
if err != nil {
|
||||
pool.Close()
|
||||
return nil, nil, fmt.Errorf("Ошибка выполнения запроса к БД: %s", err)
|
||||
}
|
||||
|
||||
return rows, pool, nil
|
||||
}
|
||||
|
||||
func mysqlQuery(query, dbname string, runningSql runningSqlServer) (*sql.Rows, *sql.DB, error) {
|
||||
|
||||
dsn := "root:" + runningSql.Password + "@tcp(" + runningSql.IPaddr + ":3306)/" + dbname
|
||||
db, err := sql.Open("mysql", dsn)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := db.Ping(); err != nil {
|
||||
err = fmt.Errorf("Ошибка проверки подключения к БД mysql: %s", err)
|
||||
db.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
result, err := db.Query(query)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Ошибка выполнения запроса %s: %s", query, err)
|
||||
db.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return result, db, nil
|
||||
}
|
||||
2
DCIManager6/dci6-support/todo.md
Normal file
2
DCIManager6/dci6-support/todo.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## 2602-3
|
||||
TODO найти куда падают ошибки опроса комплектующих. в dci_server_component_error пусто
|
||||
Reference in New Issue
Block a user