Initial commit
This commit is contained in:
commit
12e8ef51c1
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/inventory
|
||||
/cmd/inventory/inventory
|
202
LICENSE
Normal file
202
LICENSE
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
12
README.md
Normal file
12
README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Inventory Application
|
||||
|
||||
Environmental objects inventory application
|
||||
|
||||
## run
|
||||
|
||||
### boottstrap
|
||||
```inventory bootstrap```
|
||||
|
||||
### agent
|
||||
```inventory agent run```
|
||||
|
12
cmd/inventory/agent.go
Normal file
12
cmd/inventory/agent.go
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/inventory-app/cmd/inventory/agent"
|
||||
)
|
||||
|
||||
// runCmd represents the run command
|
||||
func init() {
|
||||
rootCmd.AddCommand(agent.RootCmd)
|
||||
}
|
36
cmd/inventory/agent/agent.go
Normal file
36
cmd/inventory/agent/agent.go
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/utils/pid"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var pidfile = pid.File("/var/run/exmt.pid")
|
||||
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "agent",
|
||||
Short: "Extended Management Agent",
|
||||
}
|
||||
|
||||
// agentCmd represents the agent command
|
||||
var agentRunCmd = &cobra.Command{
|
||||
Use: "run",
|
||||
Short: "Run Extended Management Agent",
|
||||
Long: ``,
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
if err := pidfile.Write(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer pidfile.Remove()
|
||||
|
||||
return agent.Run()
|
||||
},
|
||||
}
|
||||
|
||||
// runCmd represents the run command
|
||||
func init() {
|
||||
RootCmd.AddCommand(agentRunCmd)
|
||||
}
|
12
cmd/inventory/bootstrap.go
Normal file
12
cmd/inventory/bootstrap.go
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/inventory-app/cmd/inventory/bootstrap"
|
||||
)
|
||||
|
||||
// runCmd represents the run command
|
||||
func init() {
|
||||
rootCmd.AddCommand(bootstrap.RootCmd)
|
||||
}
|
17
cmd/inventory/bootstrap/bootstrap.go
Normal file
17
cmd/inventory/bootstrap/bootstrap.go
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/bootstrap"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "bootstrap",
|
||||
Short: "Extended Management Agent Boostrap",
|
||||
Long: ``,
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
return bootstrap.Run()
|
||||
},
|
||||
}
|
7
cmd/inventory/main.go
Normal file
7
cmd/inventory/main.go
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package main
|
||||
|
||||
func main() {
|
||||
execute()
|
||||
}
|
13
cmd/inventory/main_test.go
Normal file
13
cmd/inventory/main_test.go
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go.uber.org/goleak"
|
||||
)
|
||||
|
||||
func TestMain(t *testing.T) {
|
||||
defer goleak.VerifyNone(t)
|
||||
}
|
90
cmd/inventory/root.go
Normal file
90
cmd/inventory/root.go
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
version = "v0.1.0"
|
||||
release = "dev"
|
||||
versionTemplate = `{{printf "%s Agent" .Short}}
|
||||
{{printf "Version: %s" .Version}}
|
||||
Release: ` + release + `
|
||||
`
|
||||
)
|
||||
|
||||
var configFile string
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "exmt",
|
||||
Short: "Extended Management",
|
||||
Long: `Coming soon...`,
|
||||
Version: version,
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// cobra.OnInitialize(initConfig)
|
||||
rootCmd.SetVersionTemplate(versionTemplate)
|
||||
rootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "", "config file (default is ~/.exmt.yaml)")
|
||||
rootCmd.AddCommand(autoShellCmd, testCmd)
|
||||
}
|
||||
|
||||
/*
|
||||
// initConfig reads in config file and ENV variables if set.
|
||||
|
||||
func initConfig() {
|
||||
if configFile == "" {
|
||||
if home, err := homedir.Dir(); err == nil {
|
||||
configFile = path.Join(home, ".exmt.yaml")
|
||||
}
|
||||
}
|
||||
profile.SetConfigFile(configFile)
|
||||
dir, err := filepath.Abs(filepath.Dir(configFile))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
os.MkdirAll(dir, 0600)
|
||||
profile.ReadInConfig()
|
||||
}
|
||||
*/
|
||||
var autoShellCmd = &cobra.Command{
|
||||
Use: "autoshell",
|
||||
Short: "Generate bash completion script",
|
||||
Long: "Generate bash completion script",
|
||||
Hidden: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := cmd.Root().GenBashCompletionFile("/etc/bash_completion.d/exmt.sh")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var testCmd = &cobra.Command{
|
||||
Use: "test",
|
||||
Hidden: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
utils.Init()
|
||||
err = json.NewEncoder(os.Stdout).Encode(utils.Sys)
|
||||
return
|
||||
},
|
||||
}
|
58
go.mod
Normal file
58
go.mod
Normal file
@ -0,0 +1,58 @@
|
||||
module git.fg-tech.ru/listware/inventory-app
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
git.fg-tech.ru/listware/cmdb v0.1.0
|
||||
git.fg-tech.ru/listware/go-core v0.1.0
|
||||
git.fg-tech.ru/listware/proto v0.1.1
|
||||
git.fg-tech.ru/listware/proxy v0.1.0
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/vishvananda/netlink v1.1.0
|
||||
github.com/yumaojun03/dmidecode v0.1.4
|
||||
github.com/zcalusic/sysinfo v0.9.5
|
||||
go.uber.org/goleak v1.2.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Shopify/sarama v1.38.1 // indirect
|
||||
github.com/apache/flink-statefun/statefun-sdk-go/v3 v3.2.0 // indirect
|
||||
github.com/arangodb/go-driver v1.4.1 // indirect
|
||||
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e // indirect
|
||||
github.com/eapache/go-resiliency v1.3.0 // indirect
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230111030713-bf00bc1b83b6 // indirect
|
||||
github.com/eapache/queue v1.1.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
|
||||
github.com/jcmturner/gofork v1.7.6 // indirect
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.3 // indirect
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
|
||||
github.com/klauspost/compress v1.15.14 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.17 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||
github.com/tklauser/numcpus v0.6.0 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
|
||||
golang.org/x/net v0.5.0 // indirect
|
||||
golang.org/x/sys v0.4.0 // indirect
|
||||
golang.org/x/text v0.6.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect
|
||||
google.golang.org/grpc v1.52.1 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
)
|
152
go.sum
Normal file
152
go.sum
Normal file
@ -0,0 +1,152 @@
|
||||
git.fg-tech.ru/listware/cmdb v0.1.0 h1:K4A8XI8X5nh975+m+LVea/kIa2hSQSXCnH3qVjDjOwk=
|
||||
git.fg-tech.ru/listware/cmdb v0.1.0/go.mod h1:kke3p3xl6lPlqwSfmA+grlKhGX6zKXctjcbE1Pcs9Ik=
|
||||
git.fg-tech.ru/listware/go-core v0.1.0 h1:ftwr4VjmFSHfCqPQFTi2rcpELVznYBUPmwRbKMm/OGQ=
|
||||
git.fg-tech.ru/listware/go-core v0.1.0/go.mod h1:jKjqdeZUtlNoSFSSHSmiw0fAy4FWeYhLqqRvLU5K4t4=
|
||||
git.fg-tech.ru/listware/proto v0.1.1 h1:CSqteAtgysiJe7+KtLOEXSIvxypmlJCKwQtla1d2v+A=
|
||||
git.fg-tech.ru/listware/proto v0.1.1/go.mod h1:t5lyMTuX/if05HI/na9tJAlHCHHMdhdPLBTkhvscedQ=
|
||||
git.fg-tech.ru/listware/proxy v0.1.0 h1:rQyaa894Pt0G1psNA/Li3znKZ2ol+4nX0yfi3EGPxwY=
|
||||
git.fg-tech.ru/listware/proxy v0.1.0/go.mod h1:bD0eR5gv4Dy4DV9Pp2dmHEIwrY476dQ+53/MB5xsnWw=
|
||||
github.com/Shopify/sarama v1.38.1 h1:lqqPUPQZ7zPqYlWpTh+LQ9bhYNu2xJL6k1SJN4WVe2A=
|
||||
github.com/Shopify/sarama v1.38.1/go.mod h1:iwv9a67Ha8VNa+TifujYoWGxWnu2kNVAQdSdZ4X2o5g=
|
||||
github.com/Shopify/toxiproxy/v2 v2.5.0 h1:i4LPT+qrSlKNtQf5QliVjdP08GyAH8+BUIc9gT0eahc=
|
||||
github.com/apache/flink-statefun/statefun-sdk-go/v3 v3.2.0 h1:OfLhhWnnOfBUvzbQuhE7hCKJdlBW41nV3CfCF/q7UJs=
|
||||
github.com/apache/flink-statefun/statefun-sdk-go/v3 v3.2.0/go.mod h1:uHiPJsi71a161NMH/ISkkSPIXenkcG9A2m+uhT8UlJ4=
|
||||
github.com/arangodb/go-driver v1.4.1 h1:Jg0N7XKxiKwjswmAcMCnefWmt81KJEqybqRAGJDRWlo=
|
||||
github.com/arangodb/go-driver v1.4.1/go.mod h1:UTtaxTUMmyPWzKc2dsWWOZzZ3yM6aHWxn/eubGa3YmQ=
|
||||
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e h1:Xg+hGrY2LcQBbxd0ZFdbGSyRKTYMZCfBbw/pMJFOk1g=
|
||||
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e/go.mod h1:mq7Shfa/CaixoDxiyAAc5jZ6CVBAyPaNQCGS7mkj4Ho=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e h1:vUmf0yezR0y7jJ5pceLHthLaYf4bA5T14B6q39S4q2Q=
|
||||
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e/go.mod h1:YTIHhz/QFSYnu/EhlF2SpU2Uk+32abacUYA5ZPljz1A=
|
||||
github.com/eapache/go-resiliency v1.3.0 h1:RRL0nge+cWGlxXbUzJ7yMcq6w2XBEr19dCN6HECGaT0=
|
||||
github.com/eapache/go-resiliency v1.3.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230111030713-bf00bc1b83b6 h1:8yY/I9ndfrgrXUbOGObLHKBR4Fl3nZXwM2c7OYTT8hM=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230111030713-bf00bc1b83b6/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0=
|
||||
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
|
||||
github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=
|
||||
github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
|
||||
github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
|
||||
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.3 h1:iTonLeSJOn7MVUtyMT+arAn5AKAPrkilzhGw8wE/Tq8=
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.3/go.mod h1:dqRwJGXznQrzw6cWmyo6kH+E7jksEQG/CyVWsJEsJO0=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||
github.com/klauspost/compress v1.15.14 h1:i7WCKDToww0wA+9qrUZ1xOjp218vfFo3nTU6UHp+gOc=
|
||||
github.com/klauspost/compress v1.15.14/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
|
||||
github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
|
||||
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
|
||||
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
|
||||
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
|
||||
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
github.com/yumaojun03/dmidecode v0.1.4 h1:ZmHBHs5sE5z1clgpry9tmuWeo2FBFi018MiSAWr+5n8=
|
||||
github.com/yumaojun03/dmidecode v0.1.4/go.mod h1:34bbsMNMNjDbijDpRuqd+2ZapDKxvhO+FlgGgOgS6G8=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/zcalusic/sysinfo v0.9.5 h1:ivoHyj9aIAYkwzo1+8QgJ5s4oeE6Etx9FmZtqa4wJjQ=
|
||||
github.com/zcalusic/sysinfo v0.9.5/go.mod h1:Z/gPVufBrFc8X5sef3m6kkw3r3nlNFp+I6bvASfvBZQ=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220725212005-46097bf591d3/go.mod h1:AaygXjzTFtRAg2ttMY5RMuhpJ3cNnI0XpyFJD1iQRSM=
|
||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c=
|
||||
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||
google.golang.org/grpc v1.52.1 h1:2NpOPk5g5Xtb0qebIEs7hNIa++PdtZLo2AQUpc1YnSU=
|
||||
google.golang.org/grpc v1.52.1/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
157
pkg/agent/agent.go
Normal file
157
pkg/agent/agent.go
Normal file
@ -0,0 +1,157 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"git.fg-tech.ru/listware/go-core/pkg/executor"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/module"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/baseboard"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/bios"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/cpu"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/mem"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/netlink"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/node"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/os"
|
||||
proxy "git.fg-tech.ru/listware/proxy/pkg/module"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
log = logrus.New()
|
||||
)
|
||||
|
||||
type Agent struct {
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
|
||||
// init values
|
||||
baseboard baseboard.Baseboard
|
||||
bios bios.BIOS
|
||||
cpu cpu.CPU
|
||||
node node.Node
|
||||
os os.OS
|
||||
|
||||
dimmDevs map[string]mem.MemoryDevice
|
||||
links map[string]netlink.Netlink
|
||||
|
||||
executor executor.Executor
|
||||
|
||||
m module.Module
|
||||
}
|
||||
|
||||
// Run agent
|
||||
func Run() (err error) {
|
||||
a := &Agent{}
|
||||
a.ctx, a.cancel = context.WithCancel(context.Background())
|
||||
|
||||
if a.executor, err = executor.New(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if a.baseboard, err = baseboard.New(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if a.bios, err = bios.New(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if a.cpu, err = cpu.New(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if a.node, err = node.New(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if a.os, err = os.New(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if a.dimmDevs, err = mem.Inventory(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if a.links, err = netlink.New(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return a.run()
|
||||
}
|
||||
|
||||
func appendPath(paths ...string) string {
|
||||
return strings.Join(paths, ".")
|
||||
}
|
||||
|
||||
func (a *Agent) hostname() string {
|
||||
return a.node.Hostname
|
||||
}
|
||||
|
||||
func (a *Agent) nodepath() string {
|
||||
return appendPath(a.hostname(), types.NodeContainerPath)
|
||||
}
|
||||
|
||||
func (a *Agent) baseboardpath() string {
|
||||
return appendPath(types.BaseboardLink, a.nodepath())
|
||||
}
|
||||
|
||||
func (a *Agent) biospath() string {
|
||||
return appendPath(types.BiosLink, a.nodepath())
|
||||
}
|
||||
|
||||
func (a *Agent) cpupath() string {
|
||||
return appendPath(types.CpuLink, a.nodepath())
|
||||
}
|
||||
|
||||
func (a *Agent) ospath() string {
|
||||
return appendPath(types.OsLink, a.nodepath())
|
||||
}
|
||||
|
||||
func (a *Agent) dimmpath(dev string) string {
|
||||
return appendPath(dev, a.nodepath())
|
||||
}
|
||||
|
||||
func (a *Agent) dimmspath() string {
|
||||
return appendPath(memMask, a.nodepath())
|
||||
}
|
||||
|
||||
func (a *Agent) netlinkpath(os string) string {
|
||||
return appendPath(os, a.nodepath())
|
||||
}
|
||||
|
||||
func (a *Agent) netlinkspath() string {
|
||||
return appendPath(netlinkMask, a.nodepath())
|
||||
}
|
||||
|
||||
func (a *Agent) run() (err error) {
|
||||
defer a.executor.Close()
|
||||
|
||||
log.Infof("run system agent")
|
||||
|
||||
a.osSignalCtrl()
|
||||
|
||||
a.m = proxy.New(namespace, module.WithPort(8181))
|
||||
|
||||
if err = a.m.Bind(types.FunctionPath, a.workerFunction); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// // TODO move to another app
|
||||
// if err = a.m.Bind("monit", monit.Monit); err != nil {
|
||||
// return
|
||||
// }
|
||||
|
||||
go a.m.RegisterAndListen(a.ctx)
|
||||
|
||||
if err = a.entrypoint(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
<-a.ctx.Done()
|
||||
|
||||
return nil
|
||||
}
|
38
pkg/agent/baseboard.go
Normal file
38
pkg/agent/baseboard.go
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/module"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
)
|
||||
|
||||
func (a *Agent) createBaseboard(ctx module.Context) (err error) {
|
||||
create, err := system.CreateChild(ctx.Self().Id, types.BaseboardID, types.BaseboardLink, a.baseboard)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
msg, err := module.ToMessage(create)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Agent) updateBaseboard(ctx module.Context, uuid string) (err error) {
|
||||
update, err := system.UpdateObject(uuid, a.baseboard)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(update)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
37
pkg/agent/bios.go
Normal file
37
pkg/agent/bios.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/module"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
)
|
||||
|
||||
func (a *Agent) createBios(ctx module.Context) (err error) {
|
||||
create, err := system.CreateChild(ctx.Self().Id, types.BiosID, types.BiosLink, a.bios)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(create)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Agent) updateBios(ctx module.Context, uuid string) (err error) {
|
||||
update, err := system.UpdateObject(uuid, a.bios)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(update)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
37
pkg/agent/cpu.go
Normal file
37
pkg/agent/cpu.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/module"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
)
|
||||
|
||||
func (a *Agent) createCpu(ctx module.Context) (err error) {
|
||||
create, err := system.CreateChild(ctx.Self().Id, types.CpuID, types.CpuLink, a.cpu)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(create)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Agent) updateCpu(ctx module.Context, uuid string) (err error) {
|
||||
update, err := system.UpdateObject(uuid, a.cpu)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(update)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
53
pkg/agent/dimm.go
Normal file
53
pkg/agent/dimm.go
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/module"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
)
|
||||
|
||||
func (a *Agent) createDimms(ctx module.Context) (err error) {
|
||||
for _, dev := range a.dimmDevs {
|
||||
dimmFunc, err := genDimmFunction(ctx.Self().Id, a.dimmpath(dev.Name()), dev.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg, err := module.ToMessage(dimmFunc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Agent) createDimm(ctx module.Context, name string) (err error) {
|
||||
create, err := system.CreateChild(ctx.Self().Id, types.MemoryID, name, a.dimmDevs[name])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(create)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Agent) updateDimm(ctx module.Context, id, name string) (err error) {
|
||||
update, err := system.UpdateObject(id, a.dimmDevs[name])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(update)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
82
pkg/agent/entrypoint.go
Normal file
82
pkg/agent/entrypoint.go
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.fg-tech.ru/listware/cmdb/pkg/cmdb/qdsl"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
"git.fg-tech.ru/listware/proto/sdk/pbtypes"
|
||||
)
|
||||
|
||||
func (a *Agent) createLink(route *pbtypes.FunctionRoute) (err error) {
|
||||
function, err := a.getFunction()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
node, err := a.getNode()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// create init link, will trigger 'init'
|
||||
createLink, err := system.CreateLink(function.Id.String(), node.Id.String(), node.Key, function.Type, route)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.executor.ExecSync(a.ctx, createLink)
|
||||
}
|
||||
|
||||
func (a *Agent) entrypoint() (err error) {
|
||||
route := &pbtypes.FunctionRoute{
|
||||
Url: a.m.Addr(),
|
||||
}
|
||||
|
||||
// exists node or create
|
||||
node, err := a.getNode()
|
||||
if err == nil {
|
||||
// search function
|
||||
documents, err := qdsl.Qdsl(a.ctx, fmt.Sprintf("%s.%s", node.Key, types.FunctionPath), qdsl.WithLinkId())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// func on node: exists
|
||||
for _, document := range documents {
|
||||
updateLink, err := system.UpdateAdvancedLink(document.LinkId.String(), route)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.executor.ExecSync(a.ctx, updateLink)
|
||||
}
|
||||
|
||||
return a.createLink(route)
|
||||
}
|
||||
|
||||
// TODO move to register
|
||||
nodes, err := a.getNodes()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
message := &pbtypes.FunctionMessage{
|
||||
Type: types.FunctionPath,
|
||||
Route: route,
|
||||
}
|
||||
|
||||
createNode, err := system.CreateChild(nodes.Id.String(), types.NodeID, a.hostname(), a.node, message)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = a.executor.ExecSync(a.ctx, createNode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.createLink(route)
|
||||
}
|
91
pkg/agent/netlink.go
Normal file
91
pkg/agent/netlink.go
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/module"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/netlink"
|
||||
)
|
||||
|
||||
func (a *Agent) netlink(uuid string) {
|
||||
updateChan, deleteChan := netlink.Subscribe(a.ctx)
|
||||
|
||||
for {
|
||||
select {
|
||||
case link := <-updateChan:
|
||||
netlinkFunc, err := genNetlinkFunction(uuid, a.netlinkpath(link.LinkName()), link, updateEvent)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err = a.executor.ExecAsync(a.ctx, netlinkFunc); err != nil {
|
||||
log.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
case link := <-deleteChan:
|
||||
netlinkFunc, err := genNetlinkFunction(uuid, a.netlinkpath(link.LinkName()), link, deleteEvent)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err = a.executor.ExecAsync(a.ctx, netlinkFunc); err != nil {
|
||||
log.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
case <-a.ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) createNetlinks(ctx module.Context) (err error) {
|
||||
for _, link := range a.links {
|
||||
netlinkFunc, err := genNetlinkFunction(ctx.Self().Id, a.netlinkpath(link.LinkName()), link, updateEvent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg, err := module.ToMessage(netlinkFunc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
}
|
||||
|
||||
go a.netlink(ctx.Self().Id)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Agent) createNetlink(ctx module.Context, link *netlink.Netlink) (err error) {
|
||||
create, err := system.CreateChild(ctx.Self().Id, types.NetlinkID, link.LinkName(), link)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(create)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Agent) updateNetlink(ctx module.Context, uuid string, link netlink.Netlink) (err error) {
|
||||
update, err := system.UpdateObject(uuid, link)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(update)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
118
pkg/agent/node.go
Normal file
118
pkg/agent/node.go
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/module"
|
||||
)
|
||||
|
||||
// readNode generate and exec worker("nodepath") func
|
||||
func (a *Agent) readNode(ctx module.Context, id string) (err error) {
|
||||
nodeFunc, err := genFunction(id, a.nodepath())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(nodeFunc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
||||
|
||||
// readNode generate and exec worker("baseboard", "cpu", etc...) funcs
|
||||
func (a *Agent) readChilds(ctx module.Context, id string) (err error) {
|
||||
update, err := system.UpdateObject(id, a.node)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(update)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
|
||||
baseboardFunc, err := genFunction(id, a.baseboardpath())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err = module.ToMessage(baseboardFunc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
|
||||
osFunc, err := genFunction(id, a.ospath())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err = module.ToMessage(osFunc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
|
||||
biosFunc, err := genFunction(id, a.biospath())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err = module.ToMessage(biosFunc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
|
||||
cpuFunc, err := genFunction(id, a.cpupath())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err = module.ToMessage(cpuFunc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
|
||||
dimmFunc, err := genFunction(id, a.dimmspath())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err = module.ToMessage(dimmFunc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
|
||||
netlinkFunc, err := genFunction(id, a.netlinkspath())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err = module.ToMessage(netlinkFunc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Agent) deleteObject(ctx module.Context, uuid string) (err error) {
|
||||
del, err := system.DeleteObject(uuid)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(del)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
37
pkg/agent/os.go
Normal file
37
pkg/agent/os.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/module"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
)
|
||||
|
||||
func (a *Agent) createOs(ctx module.Context) (err error) {
|
||||
create, err := system.CreateChild(ctx.Self().Id, types.OsID, types.OsLink, a.os)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(create)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Agent) updateOs(ctx module.Context, uuid string) (err error) {
|
||||
update, err := system.UpdateObject(uuid, a.os)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg, err := module.ToMessage(update)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Send(msg)
|
||||
return
|
||||
}
|
38
pkg/agent/query.go
Normal file
38
pkg/agent/query.go
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.fg-tech.ru/listware/cmdb/pkg/cmdb/documents"
|
||||
"git.fg-tech.ru/listware/cmdb/pkg/cmdb/qdsl"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
)
|
||||
|
||||
func (a *Agent) getDocument(query string) (document *documents.Node, err error) {
|
||||
documents, err := qdsl.Qdsl(a.ctx, query, qdsl.WithKey(), qdsl.WithId(), qdsl.WithType())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, document = range documents {
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("document '%s' not found", query)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Agent) getFunction() (document *documents.Node, err error) {
|
||||
// search function_type init 'init.exmt.functions.root'
|
||||
return a.getDocument(types.FunctionPath)
|
||||
}
|
||||
|
||||
func (a *Agent) getNode() (document *documents.Node, err error) {
|
||||
// search function_type init 'dev0.nodes.root'
|
||||
return a.getDocument(a.nodepath())
|
||||
}
|
||||
|
||||
func (a *Agent) getNodes() (document *documents.Node, err error) {
|
||||
// search 'nodes.root'
|
||||
return a.getDocument(types.NodeContainerPath)
|
||||
}
|
35
pkg/agent/signal.go
Normal file
35
pkg/agent/signal.go
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (a *Agent) osSignalCtrl() {
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan,
|
||||
syscall.SIGINT,
|
||||
syscall.SIGTERM,
|
||||
syscall.SIGQUIT,
|
||||
syscall.SIGHUP,
|
||||
syscall.SIGUSR1,
|
||||
syscall.SIGUSR2,
|
||||
)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case sig := <-sigChan:
|
||||
switch sig {
|
||||
case syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT:
|
||||
log.Infof("Get Stop signal")
|
||||
a.cancel()
|
||||
}
|
||||
case <-a.ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
34
pkg/agent/types/baseboard/baseboard.go
Normal file
34
pkg/agent/types/baseboard/baseboard.go
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package baseboard
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Baseboard information.
|
||||
type Baseboard struct {
|
||||
UUID string `json:"uuid,omitemtpy"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Vendor string `json:"vendor,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Serial string `json:"serial,omitempty"`
|
||||
}
|
||||
|
||||
// Inventory interface
|
||||
func New() (b Baseboard, err error) {
|
||||
utils.Init()
|
||||
|
||||
logrus.Infof("baseboard: %s", utils.Sys.Board.Name)
|
||||
|
||||
b = Baseboard{
|
||||
UUID: utils.Sys.HostID,
|
||||
Name: utils.Sys.Board.Name,
|
||||
Vendor: utils.Sys.Board.Vendor,
|
||||
Version: utils.Sys.Board.Version,
|
||||
Serial: utils.Sys.Board.Serial,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
28
pkg/agent/types/bios/bios.go
Normal file
28
pkg/agent/types/bios/bios.go
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package bios
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// BIOS information.
|
||||
type BIOS struct {
|
||||
Vendor string `json:"vendor,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Date string `json:"date,omitempty"`
|
||||
}
|
||||
|
||||
// Inventory interface
|
||||
func New() (b BIOS, err error) {
|
||||
logrus.Infof("bios: %s", utils.Sys.BIOS.Vendor)
|
||||
|
||||
b = BIOS{
|
||||
Vendor: utils.Sys.BIOS.Vendor,
|
||||
Version: utils.Sys.BIOS.Version,
|
||||
Date: utils.Sys.BIOS.Date,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
23
pkg/agent/types/cpu/cpu.go
Normal file
23
pkg/agent/types/cpu/cpu.go
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/zcalusic/sysinfo"
|
||||
)
|
||||
|
||||
// CPU profile
|
||||
type CPU struct {
|
||||
sysinfo.CPU
|
||||
}
|
||||
|
||||
// Inventory \\
|
||||
func New() (c CPU, err error) {
|
||||
logrus.Infof("cpu: %s", utils.Sys.CPU.Model)
|
||||
|
||||
c = CPU{CPU: utils.Sys.CPU}
|
||||
|
||||
return
|
||||
}
|
54
pkg/agent/types/mem/inventory.go
Normal file
54
pkg/agent/types/mem/inventory.go
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package mem
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/yumaojun03/dmidecode"
|
||||
"github.com/yumaojun03/dmidecode/parser/memory"
|
||||
)
|
||||
|
||||
// Channels for get updates
|
||||
var (
|
||||
log = logrus.New()
|
||||
)
|
||||
|
||||
func deviceToProfile(device *memory.MemoryDevice) (dev MemoryDevice) {
|
||||
dev = MemoryDevice{
|
||||
Size: device.Size,
|
||||
FormFactor: device.FormFactor.String(),
|
||||
Device: device.DeviceLocator,
|
||||
Bank: device.BankLocator,
|
||||
Type: device.Type.String(),
|
||||
Speed: device.Speed,
|
||||
Manufacturer: device.Manufacturer,
|
||||
Serial: device.SerialNumber,
|
||||
Part: device.PartNumber,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Inventory implement inventory interface
|
||||
func Inventory() (devs map[string]MemoryDevice, err error) {
|
||||
log.Info("inventory mem")
|
||||
|
||||
devs = make(map[string]MemoryDevice)
|
||||
|
||||
dmi, err := dmidecode.New()
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
return
|
||||
}
|
||||
devices, err := dmi.MemoryDevice()
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, device := range devices {
|
||||
dev := deviceToProfile(device)
|
||||
devs[dev.Name()] = dev
|
||||
}
|
||||
return
|
||||
}
|
25
pkg/agent/types/mem/mem.go
Normal file
25
pkg/agent/types/mem/mem.go
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package mem
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Ram module profile
|
||||
type MemoryDevice struct {
|
||||
Device string `json:"device,omitempty"`
|
||||
Bank string `json:"bank,omitempty"`
|
||||
FormFactor string `json:"form-factor,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
|
||||
Size uint16 `json:"size,omitempty"`
|
||||
Speed uint16 `json:"speed,omitempty"`
|
||||
Manufacturer string `json:"manufacturer,omitempty"`
|
||||
Serial string `json:"serial,omitempty"`
|
||||
Part string `json:"part,omitempty"`
|
||||
}
|
||||
|
||||
func (m *MemoryDevice) Name() string {
|
||||
return strings.ToLower(strings.ReplaceAll(m.Device, "_", "-"))
|
||||
}
|
155
pkg/agent/types/netlink/inventory.go
Normal file
155
pkg/agent/types/netlink/inventory.go
Normal file
@ -0,0 +1,155 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
var (
|
||||
log = logrus.New()
|
||||
)
|
||||
|
||||
func Subscribe(ctx context.Context) (updateChan, deleteChan chan Netlink) {
|
||||
updateChan = make(chan Netlink, 1000)
|
||||
deleteChan = make(chan Netlink, 100)
|
||||
|
||||
go func() {
|
||||
linkUpdateChan := make(chan netlink.LinkUpdate, 100)
|
||||
if err := netlink.LinkSubscribe(linkUpdateChan, ctx.Done()); err != nil {
|
||||
log.Warn(err.Error())
|
||||
return
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case m := <-linkUpdateChan:
|
||||
|
||||
switch m.Header.Type {
|
||||
case syscall.RTM_NEWLINK:
|
||||
if filterLinks(m.Link) {
|
||||
log.Debugf("Handle link type: %s", m.Link.Type())
|
||||
updateChan <- netlinkToLink(m.Link)
|
||||
}
|
||||
case syscall.RTM_DELLINK:
|
||||
if filterLinks(m.Link) {
|
||||
log.Debugf("Handle link type: %s", m.Link.Type())
|
||||
deleteChan <- netlinkToLink(m.Link)
|
||||
}
|
||||
}
|
||||
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
go func() {
|
||||
addrUpdateChan := make(chan netlink.AddrUpdate, 100)
|
||||
if err := netlink.AddrSubscribe(addrUpdateChan, ctx.Done()); err != nil {
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case m := <-addrUpdateChan:
|
||||
if link, err := netlink.LinkByIndex(m.LinkIndex); err == nil {
|
||||
if filterLinks(link) {
|
||||
log.Debugf("Handle address changes: %s", m.LinkAddress.String())
|
||||
updateChan <- netlinkToLink(link)
|
||||
}
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func New() (initLinks map[string]Netlink, err error) {
|
||||
log.Info("inventory links")
|
||||
|
||||
initLinks = make(map[string]Netlink)
|
||||
|
||||
links, err := netlink.LinkList()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, link := range links {
|
||||
if filterLinks(link) {
|
||||
l := netlinkToLink(link)
|
||||
initLinks[l.LinkName()] = l
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// spaghetti filter
|
||||
func filterLinks(link netlink.Link) bool {
|
||||
if link.Type() == "veth" || link.Type() == "bridge" {
|
||||
return false
|
||||
}
|
||||
attrs := link.Attrs()
|
||||
if (attrs.Flags & net.FlagLoopback) != 0 {
|
||||
return false
|
||||
}
|
||||
if attrs.MasterIndex != 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func netlinkToLink(link netlink.Link) Netlink {
|
||||
attrs := link.Attrs()
|
||||
l := Netlink{
|
||||
PortType: "os-def",
|
||||
PortID: attrs.Index - 1,
|
||||
Type: link.Type(),
|
||||
MTU: attrs.MTU,
|
||||
Name: attrs.Name,
|
||||
MacAddr: attrs.HardwareAddr.String(),
|
||||
Alias: attrs.Alias,
|
||||
State: attrs.OperState.String(),
|
||||
}
|
||||
|
||||
if attrs.ParentIndex != 0 {
|
||||
l.PortID = attrs.ParentIndex
|
||||
}
|
||||
switch attrs.EncapType {
|
||||
case "infiniband":
|
||||
l.PortType = "os-ib"
|
||||
l.Type = attrs.EncapType
|
||||
case "ether":
|
||||
l.PortType = "os-eth"
|
||||
}
|
||||
if link.Type() == "vlan" {
|
||||
if vlan, ok := link.(*netlink.Vlan); ok {
|
||||
l.VlanID = vlan.VlanId
|
||||
l.PortType = "os-vlan"
|
||||
l.PortID = (attrs.ParentIndex - 1)
|
||||
}
|
||||
}
|
||||
l.Addrs = addrs(link)
|
||||
|
||||
data, err := os.ReadFile(fmt.Sprintf("/sys/class/net/%s/device/numa_node", l.Name))
|
||||
if err == nil {
|
||||
l.Numa, err = strconv.Atoi(strings.TrimSuffix(string(data), "\n"))
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
}
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
68
pkg/agent/types/netlink/link.go
Normal file
68
pkg/agent/types/netlink/link.go
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
// Addr ...
|
||||
type Addr struct {
|
||||
IP string `json:"ip,omitempty"`
|
||||
Mask string `json:"mask,omitempty"`
|
||||
Network string `json:"network,omitempty"`
|
||||
}
|
||||
|
||||
// Link profile
|
||||
type Netlink struct {
|
||||
PortID int `json:"port-id"`
|
||||
PortType string `json:"port-type"`
|
||||
Type string `json:"type,omitempty"`
|
||||
MTU int `json:"mtu,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
MacAddr string `json:"mac,omitempty"`
|
||||
State string `json:"state,omitempaty"`
|
||||
Alias string `json:"alias,omitempty"`
|
||||
VlanID int `json:"vlan-id,omitempty"`
|
||||
|
||||
Numa int `json:"numa,omitempty"`
|
||||
Addrs []Addr `json:"addrs,omitempty"`
|
||||
}
|
||||
|
||||
func (l *Netlink) LinkName() string {
|
||||
if l.VlanID != 0 {
|
||||
return fmt.Sprintf("%s%d", l.PortType, l.VlanID)
|
||||
}
|
||||
return fmt.Sprintf("%s%d", l.PortType, l.PortID)
|
||||
}
|
||||
|
||||
func addrs(link netlink.Link) (res []Addr) {
|
||||
// Get all IPv4 addrs
|
||||
addrs, _ := netlink.AddrList(link, 2)
|
||||
for _, a := range addrs {
|
||||
var network string
|
||||
ipnet := strings.Split(a.IPNet.String(), "/")
|
||||
if len(ipnet) == 2 {
|
||||
network = fmt.Sprintf("%s/%s", a.IP.Mask(a.Mask).String(), ipnet[1])
|
||||
|
||||
}
|
||||
addr := Addr{
|
||||
IP: a.IP.String(),
|
||||
Mask: ipv4MaskString(a.Mask),
|
||||
Network: network,
|
||||
}
|
||||
res = append(res, addr)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Net mask in dot decimal notation
|
||||
func ipv4MaskString(m []byte) string {
|
||||
if len(m) != 4 {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3])
|
||||
}
|
50
pkg/agent/types/node/node.go
Normal file
50
pkg/agent/types/node/node.go
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package node
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Node profile
|
||||
type Node struct {
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
Domain string `json:"domain,omitempty"`
|
||||
Model string `json:"model,omitempty"`
|
||||
}
|
||||
|
||||
func Name() (string, error) {
|
||||
fqdn := strings.SplitN(utils.Sys.Hostname, ".", 2)
|
||||
if len(fqdn) == 0 {
|
||||
return "", fmt.Errorf("bad fqdn")
|
||||
}
|
||||
return fqdn[0], nil
|
||||
}
|
||||
|
||||
// Inventory interface
|
||||
func New() (n Node, err error) {
|
||||
logrus.Infof("node: %s", utils.Sys.Hostname)
|
||||
|
||||
fqdn := strings.SplitN(utils.Sys.Hostname, ".", 2)
|
||||
if len(fqdn) == 0 {
|
||||
err = fmt.Errorf("bad fqdn")
|
||||
return
|
||||
}
|
||||
var dn string
|
||||
|
||||
if len(fqdn) > 1 {
|
||||
dn = fqdn[1]
|
||||
}
|
||||
|
||||
n = Node{
|
||||
Hostname: fqdn[0],
|
||||
Domain: dn,
|
||||
Model: utils.Sys.Board.Name,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
31
pkg/agent/types/os/os.go
Normal file
31
pkg/agent/types/os/os.go
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package os
|
||||
|
||||
import (
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// OS profile
|
||||
type OS struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Platform string `json:"platform,omitempty"`
|
||||
Family string `json:"family,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
BootTime int64 `json:"boot-time,omitempty"`
|
||||
}
|
||||
|
||||
// Inventory interface
|
||||
func New() (o OS, err error) {
|
||||
logrus.Infof("os: %s %s", utils.Sys.InfoStat.OS, utils.Sys.Platform)
|
||||
|
||||
o = OS{
|
||||
Type: utils.Sys.InfoStat.OS,
|
||||
Platform: utils.Sys.Platform,
|
||||
Family: utils.Sys.PlatformFamily,
|
||||
Version: utils.Sys.PlatformVersion,
|
||||
BootTime: utils.Sys.BootTime.Unix(),
|
||||
}
|
||||
return
|
||||
}
|
37
pkg/agent/types/types.go
Normal file
37
pkg/agent/types/types.go
Normal file
@ -0,0 +1,37 @@
|
||||
package types
|
||||
|
||||
const (
|
||||
NodeID = "types/node"
|
||||
CpuID = "types/cpu"
|
||||
OsID = "types/os"
|
||||
BaseboardID = "types/baseboard"
|
||||
BiosID = "types/bios"
|
||||
MemoryID = "types/memory-device"
|
||||
NetlinkID = "types/netlink"
|
||||
TempID = "types/temp"
|
||||
NodeContainerID = "types/node-container"
|
||||
FunctionContainerID = "types/function-container"
|
||||
FunctionID = "types/function"
|
||||
|
||||
RootID = "system/root"
|
||||
)
|
||||
|
||||
const (
|
||||
CpuLink = "cpu"
|
||||
OsLink = "os"
|
||||
BaseboardLink = "baseboard"
|
||||
BiosLink = "bios"
|
||||
DimmLink = "dimm"
|
||||
NetlinkLink = "os-"
|
||||
TempLink = "temp"
|
||||
NodeContainerLink = "nodes"
|
||||
FunctionContainerLink = "inventory"
|
||||
FunctionLink = "init"
|
||||
)
|
||||
|
||||
const (
|
||||
NodeContainerPath = "nodes.root"
|
||||
FunctionsPath = "functions.root"
|
||||
FunctionContainerPath = "inventory.functions.root"
|
||||
FunctionPath = "init.inventory.functions.root"
|
||||
)
|
70
pkg/agent/utils.go
Normal file
70
pkg/agent/utils.go
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/netlink"
|
||||
"git.fg-tech.ru/listware/proto/sdk/pbtypes"
|
||||
)
|
||||
|
||||
const (
|
||||
namespace = "proxy"
|
||||
|
||||
netlinkMask = "*[?@._type == 'netlink'?]"
|
||||
memMask = "*[?@._type == 'memory-device'?]"
|
||||
)
|
||||
|
||||
const (
|
||||
updateEvent = "update"
|
||||
deleteEvent = "delete"
|
||||
)
|
||||
|
||||
// TODO temp
|
||||
const (
|
||||
cpuDev = "cpu"
|
||||
)
|
||||
|
||||
type Request struct {
|
||||
Query string `json:"query"`
|
||||
Name string `json:"name"`
|
||||
|
||||
// need for subscribe
|
||||
Link netlink.Netlink `json:"link"`
|
||||
// update or delete
|
||||
Event string `json:"event"`
|
||||
}
|
||||
|
||||
func prepareFunc(id string, r Request) (fc *pbtypes.FunctionContext, err error) {
|
||||
ft := &pbtypes.FunctionType{
|
||||
Namespace: namespace,
|
||||
Type: types.FunctionPath,
|
||||
}
|
||||
|
||||
fc = &pbtypes.FunctionContext{
|
||||
Id: id,
|
||||
FunctionType: ft,
|
||||
}
|
||||
fc.Value, err = json.Marshal(r)
|
||||
return
|
||||
}
|
||||
|
||||
// genFunction generate function call with object uuid and qdsl
|
||||
func genFunction(id, query string) (*pbtypes.FunctionContext, error) {
|
||||
r := Request{Query: query}
|
||||
return prepareFunc(id, r)
|
||||
}
|
||||
|
||||
// genDimmFunction generate function call with object uuid and dimm name
|
||||
func genDimmFunction(id, query, name string) (*pbtypes.FunctionContext, error) {
|
||||
r := Request{Query: query, Name: name}
|
||||
return prepareFunc(id, r)
|
||||
}
|
||||
|
||||
// genNetlinkFunction generate function call with object uuid and link object
|
||||
func genNetlinkFunction(id, query string, link netlink.Netlink, event string) (*pbtypes.FunctionContext, error) {
|
||||
r := Request{Query: query, Link: link, Event: event}
|
||||
return prepareFunc(id, r)
|
||||
}
|
126
pkg/agent/worker.go
Normal file
126
pkg/agent/worker.go
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.fg-tech.ru/listware/cmdb/pkg/cmdb/qdsl"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/module"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
)
|
||||
|
||||
func (a *Agent) workerFunction(ctx module.Context) (err error) {
|
||||
var req Request
|
||||
|
||||
if err = json.Unmarshal(ctx.Message(), &req); err != nil {
|
||||
// temp
|
||||
// move def msg to trigger
|
||||
req.Query = a.nodepath()
|
||||
}
|
||||
|
||||
elements, err := qdsl.Qdsl(ctx, req.Query, qdsl.WithName(), qdsl.WithId())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch {
|
||||
case req.Query == types.NodeContainerPath:
|
||||
// find nodes
|
||||
for _, doc := range elements {
|
||||
// uuid of "nodes.root"
|
||||
return a.readNode(ctx, doc.Id.String())
|
||||
}
|
||||
return fmt.Errorf("%s: not found", types.NodeContainerPath)
|
||||
|
||||
case req.Query == a.nodepath():
|
||||
// find node
|
||||
for _, doc := range elements {
|
||||
// uuid of "dev0.nodes.root._"
|
||||
return a.readChilds(ctx, doc.Id.String())
|
||||
}
|
||||
return
|
||||
|
||||
case req.Query == a.baseboardpath():
|
||||
// find baseboard
|
||||
for _, doc := range elements {
|
||||
// uuid of "baseboard.dev0.nodes.root._"
|
||||
return a.updateBaseboard(ctx, doc.Id.String())
|
||||
}
|
||||
return a.createBaseboard(ctx)
|
||||
|
||||
case req.Query == a.cpupath():
|
||||
// find cpu
|
||||
for _, doc := range elements {
|
||||
// uuid of "cpu.dev0.nodes.root._"
|
||||
return a.updateCpu(ctx, doc.Id.String())
|
||||
}
|
||||
return a.createCpu(ctx)
|
||||
|
||||
case req.Query == a.biospath():
|
||||
// find bios
|
||||
for _, doc := range elements {
|
||||
// uuid of "bios.dev0.nodes.root._"
|
||||
return a.updateBios(ctx, doc.Id.String())
|
||||
}
|
||||
return a.createBios(ctx)
|
||||
|
||||
case req.Query == a.ospath():
|
||||
// find os
|
||||
for _, doc := range elements {
|
||||
// uuid of "os.dev0.nodes.root._"
|
||||
return a.updateOs(ctx, doc.Id.String())
|
||||
}
|
||||
return a.createOs(ctx)
|
||||
|
||||
case req.Query == a.dimmspath():
|
||||
for _, doc := range elements {
|
||||
if _, ok := a.dimmDevs[doc.Name]; ok {
|
||||
continue
|
||||
}
|
||||
if err = a.deleteObject(ctx, doc.Id.String()); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return a.createDimms(ctx)
|
||||
|
||||
case req.Query == a.netlinkspath():
|
||||
|
||||
for _, doc := range elements {
|
||||
if _, ok := a.links[doc.Name]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO remove if not exists
|
||||
if err = a.deleteObject(ctx, doc.Id.String()); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return a.createNetlinks(ctx)
|
||||
|
||||
case strings.Contains(req.Query, types.DimmLink):
|
||||
// find dimm
|
||||
for _, doc := range elements {
|
||||
// uuid of "dimm*.dev0.nodes.root._"
|
||||
return a.updateDimm(ctx, doc.Id.String(), req.Name)
|
||||
}
|
||||
return a.createDimm(ctx, req.Name)
|
||||
|
||||
case strings.Contains(req.Query, types.NetlinkLink):
|
||||
for _, doc := range elements {
|
||||
// uuid of "os-*.dev0.nodes.root._"
|
||||
switch req.Event {
|
||||
case updateEvent:
|
||||
return a.updateNetlink(ctx, doc.Id.String(), req.Link)
|
||||
case deleteEvent:
|
||||
return a.deleteObject(ctx, doc.Id.String())
|
||||
}
|
||||
return
|
||||
}
|
||||
return a.createNetlink(ctx, &req.Link)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
56
pkg/bootstrap/bootstrap.go
Normal file
56
pkg/bootstrap/bootstrap.go
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/executor"
|
||||
)
|
||||
|
||||
const (
|
||||
appName = "inventory"
|
||||
)
|
||||
|
||||
func register(ctx context.Context, exec executor.Executor) (err error) {
|
||||
// create types
|
||||
if err = createTypes(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// create objects
|
||||
if err = createObjects(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// create links
|
||||
if err = createLinks(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
message, err := system.Register(appName, registerTypes, registerObjects, registerLinks)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return exec.ExecSync(ctx, message)
|
||||
}
|
||||
|
||||
func Run() (err error) {
|
||||
ctx := context.Background()
|
||||
|
||||
exec, err := executor.New()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer exec.Close()
|
||||
|
||||
if err = register(ctx, exec); err != nil {
|
||||
fmt.Println("register: ", err)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
33
pkg/bootstrap/functions.go
Normal file
33
pkg/bootstrap/functions.go
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.fg-tech.ru/listware/cmdb/pkg/cmdb/qdsl"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
)
|
||||
|
||||
type InitFunction struct{}
|
||||
|
||||
func createInitFunctionObject(ctx context.Context) (err error) {
|
||||
// check if object exists
|
||||
elements, err := qdsl.Qdsl(ctx, "init.inventory.functions.root")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// already exists
|
||||
if len(elements) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
message, err := system.RegisterObject("inventory.functions.root", "types/function", "init", InitFunction{}, true, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
registerObjects = append(registerObjects, message)
|
||||
|
||||
return
|
||||
}
|
91
pkg/bootstrap/links.go
Normal file
91
pkg/bootstrap/links.go
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"git.fg-tech.ru/listware/cmdb/pkg/cmdb/qdsl"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
"git.fg-tech.ru/listware/proto/sdk/pbcmdb"
|
||||
"git.fg-tech.ru/listware/proto/sdk/pbtypes"
|
||||
)
|
||||
|
||||
var (
|
||||
registerLinks = []*pbcmdb.RegisterLinkMessage{}
|
||||
|
||||
createTrigger = &pbcmdb.Trigger{
|
||||
Type: "create",
|
||||
FunctionType: &pbtypes.FunctionType{
|
||||
Namespace: "proxy",
|
||||
Type: types.FunctionPath,
|
||||
},
|
||||
}
|
||||
|
||||
updateTrigger = &pbcmdb.Trigger{
|
||||
Type: "update",
|
||||
FunctionType: &pbtypes.FunctionType{
|
||||
Namespace: "proxy",
|
||||
Type: types.FunctionPath,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// TODO move to go-core?
|
||||
type Link struct {
|
||||
Triggers map[string]map[string]*pbtypes.FunctionType
|
||||
}
|
||||
|
||||
func (l *Link) IsExists(trigger *pbcmdb.Trigger) bool {
|
||||
if trigger, ok := l.Triggers[createTrigger.Type]; ok {
|
||||
if _, ok := trigger[createTrigger.FunctionType.Namespace+"/"+createTrigger.FunctionType.Type]; ok {
|
||||
return ok
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func createLinks(ctx context.Context) (err error) {
|
||||
if err = createFunctionNodeLink(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createFunctionNodeLink(ctx context.Context) (err error) {
|
||||
createTriggerMessage, err := system.RegisterLinkTrigger(types.FunctionID, types.NodeID, createTrigger, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
updateTriggerMessage, err := system.RegisterLinkTrigger(types.FunctionID, types.NodeID, updateTrigger, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
query := "node.function.types.root"
|
||||
|
||||
elements, err := qdsl.Qdsl(ctx, query, qdsl.WithLink())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, element := range elements {
|
||||
var link Link
|
||||
if err := json.Unmarshal(element.Link, &link); err == nil {
|
||||
if !link.IsExists(createTrigger) {
|
||||
registerLinks = append(registerLinks, createTriggerMessage)
|
||||
}
|
||||
if !link.IsExists(updateTrigger) {
|
||||
registerLinks = append(registerLinks, updateTriggerMessage)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
registerLinks = append(registerLinks, createTriggerMessage, updateTriggerMessage)
|
||||
|
||||
return
|
||||
}
|
77
pkg/bootstrap/nodes.go
Normal file
77
pkg/bootstrap/nodes.go
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.fg-tech.ru/listware/cmdb/pkg/cmdb/qdsl"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types"
|
||||
"git.fg-tech.ru/listware/proto/sdk/pbcmdb"
|
||||
)
|
||||
|
||||
var (
|
||||
registerObjects = []*pbcmdb.RegisterObjectMessage{}
|
||||
)
|
||||
|
||||
type InventoryFunctionContainer struct{}
|
||||
|
||||
type NodeContainer struct{}
|
||||
|
||||
func createObjects(ctx context.Context) (err error) {
|
||||
if err = createNodeContainerObject(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = createInventoryMountpointObject(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = createInitFunctionObject(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func createNodeContainerObject(ctx context.Context) (err error) {
|
||||
// check if object exists
|
||||
elements, err := qdsl.Qdsl(ctx, types.NodeContainerPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO already exists
|
||||
if len(elements) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
message, err := system.RegisterObject(types.RootID, types.NodeContainerID, types.NodeContainerLink, NodeContainer{}, true, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
registerObjects = append(registerObjects, message)
|
||||
return
|
||||
}
|
||||
|
||||
func createInventoryMountpointObject(ctx context.Context) (err error) {
|
||||
// check if object exists
|
||||
elements, err := qdsl.Qdsl(ctx, types.FunctionContainerPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO already exists
|
||||
if len(elements) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
message, err := system.RegisterObject(types.FunctionsPath, types.FunctionContainerID, types.FunctionContainerLink, InventoryFunctionContainer{}, false, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
registerObjects = append(registerObjects, message)
|
||||
|
||||
return
|
||||
}
|
108
pkg/bootstrap/types.go
Normal file
108
pkg/bootstrap/types.go
Normal file
@ -0,0 +1,108 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.fg-tech.ru/listware/cmdb/pkg/cmdb/qdsl"
|
||||
"git.fg-tech.ru/listware/cmdb/pkg/cmdb/vertex/types"
|
||||
"git.fg-tech.ru/listware/go-core/pkg/client/system"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/baseboard"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/bios"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/cpu"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/mem"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/netlink"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/node"
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/agent/types/os"
|
||||
"git.fg-tech.ru/listware/proto/sdk/pbcmdb"
|
||||
)
|
||||
|
||||
var (
|
||||
registerTypes = []*pbcmdb.RegisterTypeMessage{}
|
||||
)
|
||||
|
||||
func createTypes(ctx context.Context) (err error) {
|
||||
if err = createNodeType(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if err = createBiosType(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if err = createBaseboardType(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if err = createCpuType(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if err = createOsType(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if err = createNetlinkType(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if err = createMemType(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if err = createNodeContainerType(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func createType(ctx context.Context, pt *types.Type) (err error) {
|
||||
query := fmt.Sprintf("%s.types.root", pt.Schema.Title)
|
||||
elements, err := qdsl.Qdsl(ctx, query)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO already exists
|
||||
if len(elements) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
message, err := system.RegisterType(pt, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
registerTypes = append(registerTypes, message)
|
||||
return
|
||||
}
|
||||
|
||||
func createNodeType(ctx context.Context) (err error) {
|
||||
pt := types.ReflectType(&node.Node{})
|
||||
return createType(ctx, pt)
|
||||
}
|
||||
func createBiosType(ctx context.Context) (err error) {
|
||||
pt := types.ReflectType(&bios.BIOS{})
|
||||
return createType(ctx, pt)
|
||||
}
|
||||
func createBaseboardType(ctx context.Context) (err error) {
|
||||
pt := types.ReflectType(&baseboard.Baseboard{})
|
||||
return createType(ctx, pt)
|
||||
}
|
||||
func createCpuType(ctx context.Context) (err error) {
|
||||
pt := types.ReflectType(&cpu.CPU{})
|
||||
return createType(ctx, pt)
|
||||
}
|
||||
func createOsType(ctx context.Context) (err error) {
|
||||
pt := types.ReflectType(&os.OS{})
|
||||
return createType(ctx, pt)
|
||||
}
|
||||
func createNetlinkType(ctx context.Context) (err error) {
|
||||
pt := types.ReflectType(&netlink.Netlink{})
|
||||
return createType(ctx, pt)
|
||||
}
|
||||
func createMemType(ctx context.Context) (err error) {
|
||||
pt := types.ReflectType(&mem.MemoryDevice{})
|
||||
return createType(ctx, pt)
|
||||
}
|
||||
|
||||
func createNodeContainerType(ctx context.Context) (err error) {
|
||||
pt := types.ReflectType(&NodeContainer{})
|
||||
return createType(ctx, pt)
|
||||
}
|
48
pkg/utils/driver/driver.go
Normal file
48
pkg/utils/driver/driver.go
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
kmodSysPath = "/sys/module"
|
||||
drvsPath = "/sys/bus/pci/drivers"
|
||||
)
|
||||
|
||||
// Driver - disk driver: nvme, uio, etc..
|
||||
type Driver string
|
||||
|
||||
func (drv Driver) String() string {
|
||||
return string(drv)
|
||||
}
|
||||
|
||||
// IsLoaded - check if driver is loaded
|
||||
func (drv Driver) IsLoaded() bool {
|
||||
_, err := os.Stat(path.Join(kmodSysPath, drv.String()))
|
||||
return !os.IsNotExist(err)
|
||||
}
|
||||
|
||||
// Load kernel module
|
||||
func (drv Driver) Load() error {
|
||||
if drv.IsLoaded() {
|
||||
logrus.WithField("driver", drv.String()).Debug("is already loaded")
|
||||
return nil
|
||||
|
||||
}
|
||||
return exec.Command("modprobe", drv.String()).Run()
|
||||
}
|
||||
|
||||
// Unload kernel module
|
||||
func (drv Driver) Unload() error {
|
||||
if !drv.IsLoaded() {
|
||||
logrus.WithField("driver", drv.String()).Debug("is already unloaded")
|
||||
return nil
|
||||
}
|
||||
return exec.Command("modprobe", "--remove", drv.String()).Run()
|
||||
}
|
163
pkg/utils/ipmi/tool.go
Normal file
163
pkg/utils/ipmi/tool.go
Normal file
@ -0,0 +1,163 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package ipmi
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/utils/driver"
|
||||
)
|
||||
|
||||
// https://webcache.googleusercontent.com/search?q=cache:ohTuxLGBYaEJ:https://computercheese.blogspot.com/2014/03/&cd=2&hl=ru&ct=clnk&gl=ru
|
||||
var (
|
||||
// Tool \\
|
||||
Tool = &tool{}
|
||||
// Driver \\
|
||||
Driver = driver.Driver("ipmi_si")
|
||||
)
|
||||
|
||||
type tool struct{}
|
||||
|
||||
func (t *tool) MC() MC {
|
||||
mc := &mgmtController{tool: t}
|
||||
return mc
|
||||
}
|
||||
|
||||
func (t *tool) exec(method string, args ...string) (*bytes.Buffer, error) {
|
||||
a := []string{method}
|
||||
a = append(a, args...)
|
||||
c := exec.Command("ipmitool", a...)
|
||||
stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
|
||||
c.Stdout = stdout
|
||||
c.Stderr = stderr
|
||||
if err := c.Run(); err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", stderr.String(), err)
|
||||
}
|
||||
return stdout, nil
|
||||
}
|
||||
|
||||
// MC - management controller
|
||||
type MC interface {
|
||||
GUID() (string, error)
|
||||
IP() (string, error)
|
||||
Temp() ([4]int, error)
|
||||
Reset() error // rtype: <warm|cold>
|
||||
}
|
||||
|
||||
type mgmtController struct {
|
||||
tool *tool
|
||||
}
|
||||
|
||||
func (mc *mgmtController) GUIDOld() (s string, err error) {
|
||||
bf, err := mc.tool.exec("mc", "guid")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
scanner := bufio.NewScanner(bf)
|
||||
for scanner.Scan() {
|
||||
txt := scanner.Text()
|
||||
if strings.Contains(txt, "System GUID") {
|
||||
kv := strings.Split(txt, ": ")
|
||||
if len(kv) != 2 {
|
||||
err = fmt.Errorf("failed to parse ipmitool output: %s", txt)
|
||||
return
|
||||
}
|
||||
s = kv[1]
|
||||
return
|
||||
}
|
||||
}
|
||||
err = fmt.Errorf("failed to parse ipmitool output: %s", bf)
|
||||
return
|
||||
}
|
||||
|
||||
func (mc *mgmtController) GUID() (s string, err error) {
|
||||
buf, err := mc.tool.exec("raw", "0x06", "0x037")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
rawString := normalize(buf.Bytes())
|
||||
output := make([]string, 5)
|
||||
output[0] = revert(rawString, 0, 7)
|
||||
output[1] = revert(rawString, 1+7, 7+4)
|
||||
output[2] = revert(rawString, 1+7+4, 7+4+4)
|
||||
output[3] = string(rawString[1+7+4+4 : 1+7+4+4+4])
|
||||
output[4] = string(rawString[1+7+4+4+4 : 1+7+4+4+4+12])
|
||||
return strings.Join(output, "-"), err
|
||||
}
|
||||
|
||||
func revert(r []byte, f, t int) (result string) {
|
||||
for i := t; i >= f; i -= 2 {
|
||||
result += string(r[i-1]) + string(r[i])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func normalize(src []byte) []byte {
|
||||
str := strings.ReplaceAll(string(src), " ", "")
|
||||
return []byte(strings.ReplaceAll(str, "\n", ""))
|
||||
}
|
||||
|
||||
func (mc *mgmtController) IP() (s string, err error) {
|
||||
buf, err := mc.tool.exec("raw", "0x0C", "0x02", "0x1", "0x3", "0x0", "0x0")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
rawString := normalize(buf.Bytes())
|
||||
dst := make([]byte, hex.DecodedLen(len(rawString)))
|
||||
if _, err = hex.Decode(dst, rawString); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if dst[0] != 0x11 {
|
||||
err = fmt.Errorf("bad code")
|
||||
return
|
||||
}
|
||||
s = fmt.Sprintf("%d.%d.%d.%d", dst[1], dst[2], dst[3], dst[4])
|
||||
return
|
||||
}
|
||||
|
||||
func (mc *mgmtController) Reset() (err error) {
|
||||
_, err = mc.tool.exec("mc", "reset", "cold")
|
||||
return
|
||||
}
|
||||
|
||||
// ipmitool -b 0x06 -t 0x2c raw 0x2e 0x4b 0x57 0x01 0x00 0x0f 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
|
||||
// -b channel
|
||||
// -t address
|
||||
// header: 57 01 00
|
||||
// cpus (2 из 4 Шт): 2c 2f ff ff
|
||||
// mem (посмотри в IpmiTemperatureStats::SystemTopology::setChannels):
|
||||
//
|
||||
// 2d ff ff ff 2d ff ff ff 2d
|
||||
// ff ff ff 2d ff ff ff 2d ff ff ff 2d ff ff ff 2e
|
||||
// ff ff ff 2d ff ff ff ff ff ff ff ff ff ff ff ff
|
||||
// ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
|
||||
// ff ff ff ff ff ff ff
|
||||
func (mc *mgmtController) Temp() (cpuTemp [4]int, err error) {
|
||||
buf, err := mc.tool.exec("-b", "0x06", "-t", "0x2c", "raw", "0x2e", "0x4b", "0x57", "0x01", "0x00", "0x0f", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
rawString := normalize(buf.Bytes())
|
||||
dst := make([]byte, hex.DecodedLen(len(rawString)))
|
||||
if _, err = hex.Decode(dst, rawString); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if dst[0] != 0x57 || dst[1] != 0x01 || dst[2] != 0x00 {
|
||||
err = fmt.Errorf("bad code")
|
||||
return
|
||||
}
|
||||
|
||||
cpuTemp[0] = int(dst[3])
|
||||
cpuTemp[1] = int(dst[4])
|
||||
cpuTemp[2] = int(dst[5])
|
||||
cpuTemp[3] = int(dst[6])
|
||||
|
||||
return
|
||||
}
|
20
pkg/utils/ipmitool.go
Normal file
20
pkg/utils/ipmitool.go
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
type ipmitool struct {
|
||||
cmd *exec.Cmd
|
||||
stdin io.Reader
|
||||
stdout io.Writer
|
||||
}
|
||||
|
||||
func newIpmiTool() (it *ipmitool, err error) {
|
||||
it = &ipmitool{}
|
||||
// it.cmd, err = exec.Command("")
|
||||
return
|
||||
}
|
54
pkg/utils/pid/file.go
Normal file
54
pkg/utils/pid/file.go
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package pid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// File - is a pid-file
|
||||
type File string
|
||||
|
||||
func (f File) String() string {
|
||||
return string(f)
|
||||
}
|
||||
|
||||
// Write a pid file, but first make sure it doesn't exist with a running pid.
|
||||
func (f File) Write() error {
|
||||
// Read in the pid file as a slice of bytes.
|
||||
if piddata, err := os.ReadFile(f.String()); err == nil {
|
||||
// Convert the file contents to an integer.
|
||||
if pid, err := strconv.Atoi(string(piddata)); err == nil {
|
||||
// Look for the pid in the process list.
|
||||
if process, err := os.FindProcess(pid); err == nil {
|
||||
// Send the process a signal zero kill.
|
||||
if err := process.Signal(syscall.Signal(0)); err == nil {
|
||||
// We only get an error if the pid isn't running, or it's not ours.
|
||||
return fmt.Errorf("pid already running: %d", pid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we get here, then the pidfile didn't exist,
|
||||
// or the pid in it doesn't belong to the user running this app.
|
||||
return os.WriteFile(f.String(), []byte(fmt.Sprintf("%d", os.Getpid())), 0664)
|
||||
}
|
||||
|
||||
// Remove pid file
|
||||
func (f File) Remove() error {
|
||||
return os.Remove(f.String())
|
||||
}
|
||||
|
||||
// PID - process id
|
||||
func (f File) PID() (pid int, err error) {
|
||||
var piddata []byte
|
||||
piddata, err = os.ReadFile(f.String())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pid, err = strconv.Atoi(string(piddata))
|
||||
return
|
||||
}
|
106
pkg/utils/sys.go
Normal file
106
pkg/utils/sys.go
Normal file
@ -0,0 +1,106 @@
|
||||
// Copyright 2022 Listware
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"git.fg-tech.ru/listware/inventory-app/pkg/utils/ipmi"
|
||||
"github.com/shirou/gopsutil/host"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/zcalusic/sysinfo"
|
||||
)
|
||||
|
||||
var (
|
||||
forceUuidEnvName = "FORCE_BASEBOARD_UUID"
|
||||
|
||||
srcUuidEnvName = "SRC_BASEBOARD_UUID"
|
||||
|
||||
log = logrus.New()
|
||||
)
|
||||
|
||||
// Sys info
|
||||
var Sys *sys
|
||||
|
||||
type sys struct {
|
||||
sysinfo.SysInfo
|
||||
*host.InfoStat
|
||||
|
||||
BootTime time.Time
|
||||
}
|
||||
|
||||
func Init() {
|
||||
Sys = newSys()
|
||||
}
|
||||
|
||||
func newSys() *sys {
|
||||
s := &sys{
|
||||
InfoStat: getHostInfo(),
|
||||
BootTime: bootTime(),
|
||||
}
|
||||
|
||||
s.GetSysInfo()
|
||||
|
||||
if v, ok := os.LookupEnv(forceUuidEnvName); ok {
|
||||
log.Infof("overidden uuid: %s", v)
|
||||
s.InfoStat.HostID = v
|
||||
return s
|
||||
}
|
||||
|
||||
if v, ok := os.LookupEnv(srcUuidEnvName); ok {
|
||||
if v == "dmi" {
|
||||
log.Infof("uuid from dmi: %s", s.InfoStat.HostID)
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
u, err := getUUIDFromIPMI()
|
||||
if u != "" {
|
||||
log.Infof("uuid from ipmi: %s", s.InfoStat.HostID)
|
||||
s.InfoStat.HostID = u
|
||||
} else {
|
||||
log.Warnf("can't read uuid from ipmi, using dmi: %v", err)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func getUUIDFromIPMI() (string, error) {
|
||||
drvWasLoaded := ipmi.Driver.IsLoaded()
|
||||
if !drvWasLoaded {
|
||||
if err := ipmi.Driver.Load(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
uuid, err := ipmi.Tool.MC().GUID()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !drvWasLoaded {
|
||||
err = ipmi.Driver.Unload()
|
||||
}
|
||||
return uuid, err
|
||||
}
|
||||
|
||||
func getHostInfo() *host.InfoStat {
|
||||
hostInfo, err := host.Info()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return hostInfo
|
||||
}
|
||||
|
||||
// Random func
|
||||
func Random(min, max int) int {
|
||||
rand.Seed(time.Now().Unix())
|
||||
return rand.Intn(max-min) + min
|
||||
}
|
||||
|
||||
func bootTime() time.Time {
|
||||
if bt, err := host.BootTime(); err == nil {
|
||||
return time.Unix(int64(bt), 0)
|
||||
}
|
||||
return time.Now()
|
||||
}
|
Loading…
Reference in New Issue
Block a user