Skip to content

Commit 1bddedf

Browse files
Merge pull request #41 from amd/alex_readme_updates
README updates
2 parents fddcad9 + 0dab7a3 commit 1bddedf

File tree

2 files changed

+170
-10
lines changed

2 files changed

+170
-10
lines changed

README.md

Lines changed: 167 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,25 @@
22
Node Scraper is a tool which performs automated data collection and analysis for the purposes of
33
system debug.
44

5+
## Table of Contents
6+
- [Installation](#installation)
7+
- [Install From Source](#install-from-source)
8+
- [CLI Usage](#cli-usage)
9+
- [Execution Methods](#execution-methods)
10+
- [Example: Remote Execution](#example-remote-execution)
11+
- [Example: connection_config.json](#example-connection_configjson)
12+
- [Subcommands](#subcommands)
13+
- ['describe' subcommand](#describe-subcommand)
14+
- ['run-plugins' sub command](#run-plugins-sub-command)
15+
- ['gen-plugin-config' sub command](#gen-plugin-config-sub-command)
16+
- ['summary' sub command](#summary-sub-command)
17+
- [Configs](#configs)
18+
- [Global args](#global-args)
19+
- [Plugin config: `--plugin-configs` command](#plugin-config---plugin-configs-command)
20+
- [Reference config: `gen-reference-config` command](#reference-config-gen-reference-config-command)
21+
- [nodescraper integration](#nodescraper-integration)
22+
23+
524
## Installation
625
### Install From Source
726
Node Scraper requires Python 3.10+ for installation. After cloning this repository,
@@ -72,7 +91,7 @@ To use remote execution, specify `--sys-location REMOTE` and provide a connectio
7291
node-scraper --sys-name <remote_host> --sys-location REMOTE --connection-config ./connection_config.json run-plugins DmesgPlugin
7392
```
7493
75-
##### Example connection_config.json
94+
##### Example: connection_config.json
7695
7796
```json
7897
{
@@ -90,13 +109,13 @@ node-scraper --sys-name <remote_host> --sys-location REMOTE --connection-config
90109
- If using SSH keys, specify `key_filename` instead of `password`.
91110
- The remote user must have permissions to run the requested plugins and access required files. If needed, use the `--skip-sudo` argument to skip plugins requiring sudo.
92111
93-
### Subcommmands
112+
### Subcommands
94113
95114
Plugins to run can be specified in two ways, using a plugin JSON config file or using the
96115
'run-plugins' sub command. These two options are not mutually exclusive and can be used together.
97116
98117
99-
1. **'describe' subcommand**
118+
#### **'describe' subcommand**
100119
101120
You can use the `describe` subcommand to display details about built-in configs or plugins.
102121
List all built-in configs:
@@ -119,7 +138,7 @@ Show details for a specific plugin
119138
node-scraper describe plugin <plugin-name>
120139
```
121140
122-
2. **'run-plugins' sub command**
141+
#### **'run-plugins' sub command**
123142
The plugins to run and their associated arguments can also be specified directly on the CLI using
124143
the 'run-plugins' sub-command. Using this sub-command you can specify a plugin name followed by
125144
the arguments for that particular plugin. Multiple plugins can be specified at once.
@@ -165,7 +184,7 @@ Use plugin configs and 'run-plugins'
165184
node-scraper run-plugins BiosPlugin
166185
```
167186
168-
3. **'gen-plugin-config' sub command**
187+
#### **'gen-plugin-config' sub command**
169188
The 'gen-plugin-config' sub command can be used to generate a plugin config JSON file for a plugin
170189
or list of plugins that can then be customized. Plugin arguments which have default values will be
171190
prepopulated in the JSON file, arguments without default values will have a value of 'null'.
@@ -200,7 +219,7 @@ This would produce the following config:
200219
}
201220
```
202221
203-
4. **'summary' sub command**
222+
#### **'summary' sub command**
204223
The 'summary' subcommand can be used to combine results from multiple runs of node-scraper to a
205224
single summary.csv file. Sample run:
206225
```sh
@@ -210,7 +229,7 @@ This will generate a new file '/<path_to_node-scraper_logs>/summary.csv' file. T
210229
contain the results from all 'nodescraper.csv' files from '/<path_to_node-scarper_logs>'.
211230
212231
213-
### Plugin Configs
232+
### Configs
214233
A plugin JSON config should follow the structure of the plugin config model defined here.
215234
The globals field is a dictionary of global key-value pairs; values in globals will be passed to
216235
any plugin that supports the corresponding key. The plugins field should be a dictionary mapping
@@ -237,7 +256,21 @@ tabular format to the console.
237256
}
238257
```
239258
240-
1. **'--plugin-configs' command**
259+
#### Global args
260+
Global args can be used to skip sudo plugins or enable/disble either collection or analysis.
261+
Below is an example that skips sudo requiring plugins and disables analysis.
262+
263+
```json
264+
"global_args": {
265+
"collection_args": {
266+
"skip_sudo" : 1
267+
},
268+
"collection" : 1,
269+
"analysis" : 0
270+
},
271+
```
272+
273+
#### Plugin config: **'--plugin-configs' command**
241274
A plugin config can be used to compare the system data against the config specifications:
242275
```sh
243276
node-scraper --plugin-configs plugin_config.json
@@ -295,7 +328,7 @@ Here is an example of a comprehensive plugin config that specifies analyzer args
295328
}
296329
```
297330
298-
2. **'gen-reference-config' command**
331+
#### Reference config: **'gen-reference-config' command**
299332
This command can be used to generate a reference config that is populated with current system
300333
configurations. Plugins that use analyzer args (where applicable) will be populated with system
301334
data.
@@ -341,3 +374,128 @@ node-scraper gen-plugin-config --gen-reference-config-from-logs scraper_logs_<pa
341374
```
342375
This will generate a reference config that includes plugins with logged results in
343376
'scraper_log_<path>' and save the new config to 'custom_output_dir/reference_config.json'.
377+
378+
379+
## nodescraper integration
380+
Nodescraper can be integrated inside another Python tool by leveraging its classes and functionality.
381+
See below for a comprehensive example on how to create plugins and run the associated data
382+
collection and analysis.
383+
Sample run command:
384+
```sh
385+
python3 sample.py
386+
```
387+
388+
Sample.py file:
389+
```python
390+
import logging
391+
import sys
392+
from nodescraper.plugins.inband.bios.bios_plugin import BiosPlugin
393+
from nodescraper.plugins.inband.bios.analyzer_args import BiosAnalyzerArgs
394+
from nodescraper.plugins.inband.kernel.kernel_plugin import KernelPlugin
395+
from nodescraper.plugins.inband.kernel.analyzer_args import KernelAnalyzerArgs
396+
from nodescraper.plugins.inband.os.os_plugin import OsPlugin
397+
from nodescraper.plugins.inband.os.analyzer_args import OsAnalyzerArgs
398+
from nodescraper.models.systeminfo import SystemInfo, OSFamily
399+
from nodescraper.enums import EventPriority, SystemLocation
400+
from nodescraper.resultcollators.tablesummary import TableSummary
401+
from nodescraper.connection.inband.inbandmanager import InBandConnectionManager
402+
from nodescraper.connection.inband.sshparams import SSHConnectionParams
403+
from nodescraper.pluginregistry import PluginRegistry
404+
from nodescraper.models.pluginconfig import PluginConfig
405+
from nodescraper.pluginexecutor import PluginExecutor
406+
407+
def main():
408+
409+
#setting up my custom logger
410+
log_level = "INFO"
411+
handlers = [logging.StreamHandler(stream=sys.stdout)]
412+
logging.basicConfig(
413+
force=True,
414+
level=log_level,
415+
format="%(asctime)25s %(levelname)10s %(name)25s | %(message)s",
416+
datefmt="%Y-%m-%d %H:%M:%S %Z",
417+
handlers=handlers,
418+
encoding="utf-8",
419+
)
420+
logging.root.setLevel(logging.INFO)
421+
logging.getLogger("paramiko").setLevel(logging.ERROR)
422+
logger = logging.getLogger("nodescraper")
423+
424+
#setting up system info
425+
system_info = SystemInfo(name="test_host",
426+
platform="X",
427+
os_familty=OSFamily.LINUX,
428+
sku="some_sku")
429+
430+
#initiate plugins
431+
bios_plugin = BiosPlugin(system_info=system_info, logger=logger)
432+
kernel_plugin = KernelPlugin(system_info=system_info, logger=logger)
433+
434+
#launch data collection
435+
_ = bios_plugin.collect()
436+
_ = kernel_plugin.collect()
437+
438+
#launch data analysis
439+
bios_plugin.analyze(analysis_args=BiosAnalyzerArgs(exp_bios_version="XYZ"))
440+
kernel_plugin.analyze(analysis_args=KernelAnalyzerArgs(exp_kernel="ABC"))
441+
442+
#log plugin data models
443+
logger.info(kernel_plugin.data.model_dump())
444+
logger.info(bios_plugin.data.model_dump())
445+
446+
#alternate method
447+
all_res = []
448+
449+
#launch plugin collection & analysis
450+
bios_result = bios_plugin.run(analysis_args={"exp_bios_version":"ABC"})
451+
all_res.append(bios_result)
452+
table_summary = TableSummary()
453+
table_summary.collate_results(all_res, None)
454+
455+
#remote connection
456+
system_info.location=SystemLocation.REMOTE
457+
ssh_params = SSHConnectionParams(hostname="my_system",
458+
port=22,
459+
username="my_username",
460+
key_filename="/home/user/.ssh/ssh_key")
461+
conn_manager = InBandConnectionManager(system_info=system_info, connection_args=ssh_params)
462+
os_plugin = OsPlugin(system_info=system_info, logger=logger, connection_manager=conn_manager)
463+
os_plugin.run(analysis_args=OsAnalyzerArgs(exp_os="DEF"))
464+
465+
#run multiple plugins through a queue
466+
system_info.location=SystemLocation.LOCAL
467+
config_dict = {
468+
"global_args": {
469+
"collection" : 1,
470+
"analysis" : 1
471+
},
472+
"plugins": {
473+
"BiosPlugin": {
474+
"analysis_args": {
475+
"exp_bios_version": "123",
476+
}
477+
},
478+
"KernelPlugin": {
479+
"analysis_args": {
480+
"exp_kernel": "ABC",
481+
}
482+
}
483+
},
484+
"result_collators": {},
485+
"name": "plugin_config",
486+
"desc": "Auto generated config"
487+
}
488+
489+
config1 = PluginConfig(**config_dict)
490+
plugin_executor = PluginExecutor(
491+
logger=logger,
492+
plugin_configs=[config1],
493+
system_info=system_info
494+
)
495+
results = plugin_executor.run_queue()
496+
497+
498+
499+
if __name__ == "__main__":
500+
main()
501+
```

nodescraper/connection/inband/inbandmanager.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ def connect(
120120
return self.result
121121

122122
try:
123-
self.logger.info("Initializing SSH connection to system")
123+
self.logger.info(
124+
"Initializing SSH connection to system '%s'", self.connection_args.hostname
125+
)
124126
self.connection = RemoteShell(self.connection_args)
125127
self.connection.connect_ssh()
126128
self._check_os_family()

0 commit comments

Comments
 (0)