Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
7b258c96
Unverified
Commit
7b258c96
authored
Oct 19, 2017
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cmd/puppeth: concurrent server dials and health checks
parent
8c78449a
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
142 additions
and
93 deletions
+142
-93
wizard.go
cmd/puppeth/wizard.go
+3
-1
wizard_intro.go
cmd/puppeth/wizard_intro.go
+18
-6
wizard_netstats.go
cmd/puppeth/wizard_netstats.go
+121
-86
No files found.
cmd/puppeth/wizard.go
View file @
7b258c96
...
...
@@ -28,6 +28,7 @@ import (
"sort"
"strconv"
"strings"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
...
...
@@ -75,7 +76,8 @@ type wizard struct {
servers
map
[
string
]
*
sshClient
// SSH connections to servers to administer
services
map
[
string
][]
string
// Ethereum services known to be running on servers
in
*
bufio
.
Reader
// Wrapper around stdin to allow reading user input
in
*
bufio
.
Reader
// Wrapper around stdin to allow reading user input
lock
sync
.
Mutex
// Lock to protect configs during concurrent service discovery
}
// read reads a single line from stdin, trimming if from spaces.
...
...
cmd/puppeth/wizard_intro.go
View file @
7b258c96
...
...
@@ -24,6 +24,7 @@ import (
"os"
"path/filepath"
"strings"
"sync"
"github.com/ethereum/go-ethereum/log"
)
...
...
@@ -80,14 +81,25 @@ func (w *wizard) run() {
}
else
if
err
:=
json
.
Unmarshal
(
blob
,
&
w
.
conf
);
err
!=
nil
{
log
.
Crit
(
"Previous configuration corrupted"
,
"path"
,
w
.
conf
.
path
,
"err"
,
err
)
}
else
{
// Dial all previously known servers concurrently
var
pend
sync
.
WaitGroup
for
server
,
pubkey
:=
range
w
.
conf
.
Servers
{
log
.
Info
(
"Dialing previously configured server"
,
"server"
,
server
)
client
,
err
:=
dial
(
server
,
pubkey
)
if
err
!=
nil
{
log
.
Error
(
"Previous server unreachable"
,
"server"
,
server
,
"err"
,
err
)
}
w
.
servers
[
server
]
=
client
pend
.
Add
(
1
)
go
func
(
server
string
,
pubkey
[]
byte
)
{
defer
pend
.
Done
()
log
.
Info
(
"Dialing previously configured server"
,
"server"
,
server
)
client
,
err
:=
dial
(
server
,
pubkey
)
if
err
!=
nil
{
log
.
Error
(
"Previous server unreachable"
,
"server"
,
server
,
"err"
,
err
)
}
w
.
lock
.
Lock
()
w
.
servers
[
server
]
=
client
w
.
lock
.
Unlock
()
}(
server
,
pubkey
)
}
pend
.
Wait
()
w
.
networkStats
()
}
// Basics done, loop ad infinitum about what to do
...
...
cmd/puppeth/wizard_netstats.go
View file @
7b258c96
...
...
@@ -21,6 +21,7 @@ import (
"os"
"sort"
"strings"
"sync"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/log"
...
...
@@ -34,112 +35,143 @@ func (w *wizard) networkStats() {
log
.
Error
(
"No remote machines to gather stats from"
)
return
}
protips
:=
new
(
protips
)
// Clear out some previous configs to refill from current scan
w
.
conf
.
ethstats
=
""
w
.
conf
.
bootFull
=
w
.
conf
.
bootFull
[
:
0
]
w
.
conf
.
bootLight
=
w
.
conf
.
bootLight
[
:
0
]
// Iterate over all the specified hosts and check their status
stats
:=
make
(
serverStats
)
var
pend
sync
.
WaitGroup
stats
:=
make
(
serverStats
)
for
server
,
pubkey
:=
range
w
.
conf
.
Servers
{
client
:=
w
.
servers
[
server
]
logger
:=
log
.
New
(
"server"
,
server
)
logger
.
Info
(
"Starting remote server health-check"
)
stat
:=
&
serverStat
{
address
:
client
.
address
,
services
:
make
(
map
[
string
]
map
[
string
]
string
),
}
stats
[
client
.
server
]
=
stat
if
client
==
nil
{
conn
,
err
:=
dial
(
server
,
pubkey
)
if
err
!=
nil
{
logger
.
Error
(
"Failed to establish remote connection"
,
"err"
,
err
)
stat
.
failure
=
err
.
Error
()
continue
pend
.
Add
(
1
)
// Gather the service stats for each server concurrently
go
func
(
server
string
,
pubkey
[]
byte
)
{
defer
pend
.
Done
()
stat
:=
w
.
gatherStats
(
server
,
pubkey
,
w
.
servers
[
server
])
// All status checks complete, report and check next server
w
.
lock
.
Lock
()
defer
w
.
lock
.
Unlock
()
delete
(
w
.
services
,
server
)
for
service
:=
range
stat
.
services
{
w
.
services
[
server
]
=
append
(
w
.
services
[
server
],
service
)
}
client
=
conn
stats
[
server
]
=
stat
}(
server
,
pubkey
)
}
pend
.
Wait
()
// Print any collected stats and return
stats
.
render
()
}
// gatherStats gathers service statistics for a particular remote server.
func
(
w
*
wizard
)
gatherStats
(
server
string
,
pubkey
[]
byte
,
client
*
sshClient
)
*
serverStat
{
// Gather some global stats to feed into the wizard
var
(
genesis
string
ethstats
string
bootFull
[]
string
bootLight
[]
string
)
// Ensure a valid SSH connection to the remote server
logger
:=
log
.
New
(
"server"
,
server
)
logger
.
Info
(
"Starting remote server health-check"
)
stat
:=
&
serverStat
{
address
:
client
.
address
,
services
:
make
(
map
[
string
]
map
[
string
]
string
),
}
if
client
==
nil
{
conn
,
err
:=
dial
(
server
,
pubkey
)
if
err
!=
nil
{
logger
.
Error
(
"Failed to establish remote connection"
,
"err"
,
err
)
stat
.
failure
=
err
.
Error
()
return
stat
}
// Client connected one way or another, run health-checks
logger
.
Debug
(
"Checking for nginx availability"
)
if
infos
,
err
:=
checkNginx
(
client
,
w
.
network
);
err
!=
nil
{
if
err
!=
ErrServiceUnknown
{
stat
.
services
[
"nginx"
]
=
map
[
string
]
string
{
"offline"
:
err
.
Error
()}
}
}
else
{
stat
.
services
[
"nginx"
]
=
infos
.
Report
()
client
=
conn
}
// Client connected one way or another, run health-checks
logger
.
Debug
(
"Checking for nginx availability"
)
if
infos
,
err
:=
checkNginx
(
client
,
w
.
network
);
err
!=
nil
{
if
err
!=
ErrServiceUnknown
{
stat
.
services
[
"nginx"
]
=
map
[
string
]
string
{
"offline"
:
err
.
Error
()}
}
logger
.
Debug
(
"Checking for ethstats availability"
)
if
infos
,
err
:=
checkEthstats
(
client
,
w
.
network
);
err
!=
nil
{
if
err
!=
ErrServiceUnknown
{
stat
.
services
[
"ethstats"
]
=
map
[
string
]
string
{
"offline"
:
err
.
Error
()}
}
}
else
{
stat
.
services
[
"ethstats"
]
=
infos
.
Report
()
protips
.
ethstats
=
infos
.
config
}
else
{
stat
.
services
[
"nginx"
]
=
infos
.
Report
()
}
logger
.
Debug
(
"Checking for ethstats availability"
)
if
infos
,
err
:=
checkEthstats
(
client
,
w
.
network
);
err
!=
nil
{
if
err
!=
ErrServiceUnknown
{
stat
.
services
[
"ethstats"
]
=
map
[
string
]
string
{
"offline"
:
err
.
Error
()}
}
logger
.
Debug
(
"Checking for bootnode availability"
)
if
infos
,
err
:=
checkNode
(
client
,
w
.
network
,
true
);
err
!=
nil
{
if
err
!=
ErrServiceUnknown
{
stat
.
services
[
"bootnode"
]
=
map
[
string
]
string
{
"offline"
:
err
.
Error
()}
}
}
else
{
stat
.
services
[
"bootnode"
]
=
infos
.
Report
()
protips
.
genesis
=
string
(
infos
.
genesis
)
protips
.
bootFull
=
append
(
protips
.
bootFull
,
infos
.
enodeFull
)
if
infos
.
enodeLight
!=
""
{
protips
.
bootLight
=
append
(
protips
.
bootLight
,
infos
.
enodeLight
)
}
}
else
{
stat
.
services
[
"ethstats"
]
=
infos
.
Report
()
ethstats
=
infos
.
config
}
logger
.
Debug
(
"Checking for bootnode availability"
)
if
infos
,
err
:=
checkNode
(
client
,
w
.
network
,
true
);
err
!=
nil
{
if
err
!=
ErrServiceUnknown
{
stat
.
services
[
"bootnode"
]
=
map
[
string
]
string
{
"offline"
:
err
.
Error
()}
}
logger
.
Debug
(
"Checking for sealnode availability"
)
if
infos
,
err
:=
checkNode
(
client
,
w
.
network
,
false
);
err
!=
nil
{
if
err
!=
ErrServiceUnknown
{
stat
.
services
[
"sealnode"
]
=
map
[
string
]
string
{
"offline"
:
err
.
Error
()}
}
}
else
{
stat
.
services
[
"sealnode"
]
=
infos
.
Report
()
protips
.
genesis
=
string
(
infos
.
genesis
)
}
else
{
stat
.
services
[
"bootnode"
]
=
infos
.
Report
()
genesis
=
string
(
infos
.
genesis
)
bootFull
=
append
(
bootFull
,
infos
.
enodeFull
)
if
infos
.
enodeLight
!=
""
{
bootLight
=
append
(
bootLight
,
infos
.
enodeLight
)
}
logger
.
Debug
(
"Checking for faucet availability"
)
if
infos
,
err
:=
checkFaucet
(
client
,
w
.
network
);
err
!=
nil
{
if
err
!=
ErrServiceUnknown
{
stat
.
services
[
"faucet"
]
=
map
[
string
]
string
{
"offline"
:
err
.
Error
()}
}
}
else
{
stat
.
services
[
"faucet"
]
=
infos
.
Report
()
}
logger
.
Debug
(
"Checking for sealnode availability"
)
if
infos
,
err
:=
checkNode
(
client
,
w
.
network
,
false
);
err
!=
nil
{
if
err
!=
ErrServiceUnknown
{
stat
.
services
[
"sealnode"
]
=
map
[
string
]
string
{
"offline"
:
err
.
Error
()}
}
logger
.
Debug
(
"Checking for dashboard availability"
)
if
infos
,
err
:=
checkDashboard
(
client
,
w
.
network
);
err
!=
nil
{
if
err
!=
ErrServiceUnknown
{
stat
.
services
[
"dashboard"
]
=
map
[
string
]
string
{
"offline"
:
err
.
Error
()}
}
}
else
{
stat
.
services
[
"dashboard"
]
=
infos
.
Report
()
}
else
{
stat
.
services
[
"sealnode"
]
=
infos
.
Report
()
genesis
=
string
(
infos
.
genesis
)
}
logger
.
Debug
(
"Checking for faucet availability"
)
if
infos
,
err
:=
checkFaucet
(
client
,
w
.
network
);
err
!=
nil
{
if
err
!=
ErrServiceUnknown
{
stat
.
services
[
"faucet"
]
=
map
[
string
]
string
{
"offline"
:
err
.
Error
()}
}
// All status checks complete, report and check next server
delete
(
w
.
services
,
server
)
for
service
:=
range
stat
.
services
{
w
.
services
[
server
]
=
append
(
w
.
services
[
server
],
service
)
}
else
{
stat
.
services
[
"faucet"
]
=
infos
.
Report
()
}
logger
.
Debug
(
"Checking for dashboard availability"
)
if
infos
,
err
:=
checkDashboard
(
client
,
w
.
network
);
err
!=
nil
{
if
err
!=
ErrServiceUnknown
{
stat
.
services
[
"dashboard"
]
=
map
[
string
]
string
{
"offline"
:
err
.
Error
()}
}
}
else
{
stat
.
services
[
"dashboard"
]
=
infos
.
Report
()
}
// If a genesis block was found, load it into our configs
if
protips
.
genesis
!=
""
&&
w
.
conf
.
genesis
==
nil
{
genesis
:=
new
(
core
.
Genesis
)
if
err
:=
json
.
Unmarshal
([]
byte
(
protips
.
genesis
),
genesis
);
err
!=
nil
{
// Feed and newly discovered information into the wizard
w
.
lock
.
Lock
()
defer
w
.
lock
.
Unlock
()
if
genesis
!=
""
&&
w
.
conf
.
genesis
==
nil
{
g
:=
new
(
core
.
Genesis
)
if
err
:=
json
.
Unmarshal
([]
byte
(
genesis
),
g
);
err
!=
nil
{
log
.
Error
(
"Failed to parse remote genesis"
,
"err"
,
err
)
}
else
{
w
.
conf
.
genesis
=
genesis
protips
.
network
=
genesis
.
Config
.
ChainId
.
Int64
()
w
.
conf
.
genesis
=
g
}
}
if
protips
.
ethstats
!=
""
{
w
.
conf
.
ethstats
=
protips
.
ethstats
if
ethstats
!=
""
{
w
.
conf
.
ethstats
=
ethstats
}
w
.
conf
.
bootFull
=
protips
.
bootFull
w
.
conf
.
bootLight
=
protips
.
bootLight
w
.
conf
.
bootFull
=
append
(
w
.
conf
.
bootFull
,
bootFull
...
)
w
.
conf
.
bootLight
=
append
(
w
.
conf
.
bootLight
,
bootLight
...
)
// Print any collected stats and return
stats
.
render
()
return
stat
}
// serverStat is a collection of service configuration parameters and health
...
...
@@ -205,6 +237,9 @@ func (stats serverStats) render() {
}
sort
.
Strings
(
services
)
if
len
(
services
)
==
0
{
table
.
Append
([]
string
{
server
,
stats
[
server
]
.
address
,
""
,
""
,
""
})
}
for
j
,
service
:=
range
services
{
// Add an empty line between all services
if
j
>
0
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment