Compare commits
225 commits
Author | SHA1 | Date | |
---|---|---|---|
4242832396 | |||
13b84b4da1 | |||
837860e31a | |||
c1a7f661a3 | |||
|
7d268ea0e8 | ||
|
9d496c6854 | ||
|
6ef23eae4d | ||
12ceea413c | |||
7a968deee9 | |||
d55cbd62fc | |||
59ce76fc29 | |||
|
c3d3e6857a | ||
|
56627c1aa9 | ||
|
8dde35dd31 | ||
|
de88ca85b9 | ||
|
514627aa72 | ||
|
4b54a0a3db | ||
|
e44fd2fe78 | ||
|
1429fedb9d | ||
|
818c835711 | ||
|
40af19e801 | ||
|
1d69f4e2f0 | ||
|
a7104b6b94 | ||
|
ee41fb4fc2 | ||
|
e04d0c6d59 | ||
|
c9a57de843 | ||
|
f512e7a0a9 | ||
|
116334be2f | ||
|
ba4cdb217b | ||
|
7ab7bbb9e1 | ||
|
b6a3acd6b4 | ||
|
bb05e12f6e | ||
|
fa51ca31ca | ||
|
0fdb56e01d | ||
|
19a158ec82 | ||
|
08360bafbb | ||
|
e0d734d0ca | ||
|
dc224e209b | ||
|
7259c7602d | ||
|
8cba98ec43 | ||
|
ab96965767 | ||
|
221ac16e87 | ||
|
9204ae2187 | ||
|
528ecc09b0 | ||
|
117b39350e | ||
|
4cf054278f | ||
|
b82dc80fe3 | ||
|
49b269efa6 | ||
|
cedb6818a3 | ||
|
a9af96bba2 | ||
|
282f914665 | ||
|
ca2a69b66f | ||
|
778814b0a1 | ||
|
e0685e7167 | ||
|
ba0be73d3c | ||
|
bf65da0c58 | ||
|
5b0df6ca05 | ||
|
2d8ec831e6 | ||
|
fde6211f5b | ||
|
e96a50379b | ||
|
633b6d3851 | ||
|
04c1f83e74 | ||
|
9b06584fed | ||
|
f7cdd92fa3 | ||
|
53769db3e4 | ||
|
bce02a5e7c | ||
|
368d793704 | ||
|
776f951e3b | ||
|
84f1f00ffe | ||
|
8c12fa8e86 | ||
|
5d0f0bf2fa | ||
|
4bd4b6bb94 | ||
|
d286fde999 | ||
|
dfe937d54e | ||
|
042a6fcf35 | ||
|
f4d7796094 | ||
|
0b9087fa41 | ||
|
79a08359ae | ||
|
29d2f23986 | ||
|
838ffd8e41 | ||
|
ea66becd3d | ||
|
0cff7d3477 | ||
|
be770a947a | ||
|
6181800cb3 | ||
|
2f23844dfd | ||
|
5f0aae6c01 | ||
|
6717b43cc9 | ||
|
05bfc69f26 | ||
|
d06931852f | ||
|
46354865d3 | ||
|
3dbeb5b9de | ||
|
dfb6b234ba | ||
|
9e797c376e | ||
|
cf2cc54da4 | ||
|
2a4f24f00a | ||
|
a7b965a8b5 | ||
|
ddf2e4d1cc | ||
|
7bf955d601 | ||
|
dd4d935fb2 | ||
|
ce83364ff9 | ||
|
75f14fa895 | ||
|
bb08813700 | ||
|
ad951b9288 | ||
|
b53dfa9b59 | ||
|
3b8917aaf3 | ||
|
18773a2dff | ||
|
84a9aca141 | ||
|
a7c6ae68e2 | ||
|
0f210e16f2 | ||
|
e789619b34 | ||
|
af9df9ab4b | ||
|
b092079820 | ||
|
021c5db7d3 | ||
|
1fc0aee929 | ||
|
7cfcd685f3 | ||
|
d1ee380ffb | ||
|
305d4d41ec | ||
|
34c1619ce8 | ||
|
fcb038f4b6 | ||
|
5d9602402b | ||
|
71c603620b | ||
|
2f09cf8d42 | ||
|
58775c0950 | ||
|
8a46af19b8 | ||
|
bdc450ef6a | ||
|
794f9787f0 | ||
|
86527af1c0 | ||
|
b738f4bfef | ||
|
aaea0a2477 | ||
|
9eafcbf215 | ||
|
95d7f98389 | ||
|
576eb07dd7 | ||
|
337e272eea | ||
|
a1af028df6 | ||
|
58c18fc2da | ||
|
3639662961 | ||
|
1d98d3c8e9 | ||
|
dc582b5de6 | ||
|
51efa8edba | ||
|
c4eb8f34ac | ||
|
7147670255 | ||
|
9e934af835 | ||
|
2a1196b52d | ||
|
77a84b365f | ||
|
0f2cb531ae | ||
|
00653628c6 | ||
|
7999244096 | ||
|
137728be1f | ||
|
0fe17c9687 | ||
|
28955612be | ||
|
fc930b9ef4 | ||
|
e20e6a7dee | ||
|
e95a66d93a | ||
|
feab0f1a58 | ||
|
0a903596dc | ||
|
3aea4fbc3b | ||
|
54526d3d0b | ||
|
a866e20548 | ||
|
f8c0732c2b | ||
|
a59690469b | ||
|
da5e8ad2e7 | ||
|
df18f6ea00 | ||
|
4f0db3478f | ||
|
d1a0ec2324 | ||
|
e6472c623d | ||
|
1685ecab16 | ||
|
18e3480574 | ||
|
839d9a908c | ||
|
875ad5c92e | ||
|
ebee42bb48 | ||
|
70146b8614 | ||
|
f936aeb717 | ||
|
9611400b22 | ||
|
53cb29a6d4 | ||
|
70e5d407f5 | ||
|
67a564855b | ||
|
0894e645a8 | ||
|
95d2ae420e | ||
|
275e1850c6 | ||
|
9aedb46530 | ||
|
a60c0cd70c | ||
|
bd5037996b | ||
|
665531cb87 | ||
|
21ddf3f312 | ||
|
f654187074 | ||
|
a896d118d7 | ||
|
a71d992a51 | ||
|
c6a1e48956 | ||
|
b331bcb934 | ||
|
feec16c4fe | ||
|
d227f35964 | ||
|
b94f246196 | ||
|
754a284fd1 | ||
|
683e6cacb1 | ||
|
41f0b04d00 | ||
|
9dedbea47a | ||
|
28fc87c9e2 | ||
|
29d2bff805 | ||
|
bd5b45fc6d | ||
|
26413fe0e8 | ||
|
f06da32fc3 | ||
|
996c10d95b | ||
|
ace8f69eab | ||
|
312f472e9c | ||
|
a42cf2eb48 | ||
|
dc4f90d490 | ||
|
5590f39131 | ||
|
bb7c8c8f94 | ||
|
a5bc16d3b1 | ||
|
bab2d26ad0 | ||
|
bdc2cbeb8f | ||
|
2280169cd9 | ||
|
b36d61e610 | ||
|
3aa851413e | ||
|
405cce3995 | ||
|
86a8d73873 | ||
|
957e5f4fb9 | ||
|
5f66d31ef0 | ||
|
46af158d49 | ||
|
60f6e16cf7 | ||
|
357ddc07f2 | ||
|
6c3466cb55 | ||
|
6497261708 | ||
|
c458e88b57 | ||
|
8ef94272a1 |
68 changed files with 18673 additions and 1476 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
use nix
|
25
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
25
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Configuration file**
|
||||||
|
Paste here your netbox agent configuration file
|
||||||
|
|
||||||
|
**Environment:**
|
||||||
|
- OS: [e.g. Ubuntu 18.04]
|
||||||
|
- Netbox agent version [e.g. master, v0.6.0]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -179,3 +179,8 @@ dmypy.json
|
||||||
.pyre/
|
.pyre/
|
||||||
|
|
||||||
# End of https://www.gitignore.io/api/emacs,python
|
# End of https://www.gitignore.io/api/emacs,python
|
||||||
|
|
||||||
|
netbox-docker
|
||||||
|
/.vscode
|
||||||
|
.direnv
|
||||||
|
.pre-commit-config.yaml
|
||||||
|
|
19
.travis.yml
19
.travis.yml
|
@ -2,20 +2,23 @@ sudo: false
|
||||||
dist: xenial
|
dist: xenial
|
||||||
language: python
|
language: python
|
||||||
|
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- python: 3.5
|
- python: 3.5
|
||||||
env: TOXENV=py35
|
env: TOXENV=pytest
|
||||||
- python: 3.6
|
- python: 3.6
|
||||||
env: TOXENV=py36
|
env: TOXENV=pytest
|
||||||
- python: 3.7
|
- python: 3.7
|
||||||
env: TOXENV=py37
|
env: TOXENV=pytest
|
||||||
- python: pypy3
|
- python: pypy3
|
||||||
env: TOXENV=pypy3
|
env: TOXENV=pytest
|
||||||
- python: 3.5
|
- python: 3.5
|
||||||
env: TOXENV=pep8
|
env: TOXENV=flake8
|
||||||
- python: 3.7
|
- python: 3.7
|
||||||
env: TOXENV=pep8
|
env: TOXENV=flake8
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
|
@ -23,7 +26,7 @@ cache:
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- pip install tox
|
- pip install tox
|
||||||
- if [[ $TOXENV == py* ]]; then pip install coveralls; fi
|
- if [[ $TOXENV == pytest ]]; then pip install coveralls; fi
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- tox
|
- tox
|
||||||
|
@ -32,4 +35,4 @@ notifications:
|
||||||
email: false
|
email: false
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
- if [[ $TOXENV == py* ]]; then coveralls; fi
|
- if [[ $TOXENV == pytest ]]; then coveralls; fi
|
||||||
|
|
1
MANIFEST.in
Normal file
1
MANIFEST.in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
include requirements.txt
|
183
README.md
183
README.md
|
@ -1,5 +1,4 @@
|
||||||
# Netbox agent
|
# Netbox agent [![Build Status](https://travis-ci.com/Solvik/netbox-agent.svg?branch=master)](https://travis-ci.com/Solvik/netbox-agent)
|
||||||
|
|
||||||
|
|
||||||
This project aims to create hardware automatically into [Netbox](https://github.com/netbox-community/netbox) based on standard tools (dmidecode, lldpd, parsing /sys/, etc).
|
This project aims to create hardware automatically into [Netbox](https://github.com/netbox-community/netbox) based on standard tools (dmidecode, lldpd, parsing /sys/, etc).
|
||||||
|
|
||||||
|
@ -7,21 +6,22 @@ The goal is to generate an existing infrastructure on Netbox and have the abilit
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
* Create servers, chassis and blade through standard tools (`dmidecode`)
|
* Create virtual machines, servers, chassis and blade through standard tools (`dmidecode`)
|
||||||
* Create physical, bonding and vlan network interfaces with IPs (IPv4 & IPv6)
|
* Create physical, bonding and vlan network interfaces with IPs (IPv4 & IPv6)
|
||||||
* Create IPMI interface if found
|
* Create IPMI interface if found
|
||||||
* Create or get existing VLAN and associate it to interfaces
|
* Create or get existing VLAN and associate it to interfaces
|
||||||
* Generic ability to guess datacenters and rack location through drivers (`cmd` and `file` and custom ones)
|
* Generic ability to guess datacenters and rack location through drivers (`cmd` and `file` and custom ones)
|
||||||
* Update existing `Device` and `Interface`
|
* Update existing `Device` and `Interface`
|
||||||
* Handle blade moving (new slot, new chassis)
|
* Handle blade moving (new slot, new chassis)
|
||||||
|
* Handle blade GPU expansions
|
||||||
* Automatic cabling (server's interface to switch's interface) using lldp
|
* Automatic cabling (server's interface to switch's interface) using lldp
|
||||||
* Local inventory using `Inventory Item` for CPU, RAM, RAID cards, physical disks (behind raid cards)
|
* Local inventory using `Inventory Item` for CPU, GPU, RAM, RAID cards, physical disks (behind raid cards)
|
||||||
* PSUs creation and power consumption reporting (based on vendor's tools)
|
* PSUs creation and power consumption reporting (based on vendor's tools)
|
||||||
|
|
||||||
# Requirements
|
# Requirements
|
||||||
|
|
||||||
- Netbox >= 2.6
|
- Netbox >= 3.7
|
||||||
- Python >= 3.4
|
- Python >= 3.7
|
||||||
- [pynetbox](https://github.com/digitalocean/pynetbox/)
|
- [pynetbox](https://github.com/digitalocean/pynetbox/)
|
||||||
- [python3-netaddr](https://github.com/drkjam/netaddr)
|
- [python3-netaddr](https://github.com/drkjam/netaddr)
|
||||||
- [python3-netifaces](https://github.com/al45tair/netifaces)
|
- [python3-netifaces](https://github.com/al45tair/netifaces)
|
||||||
|
@ -33,35 +33,112 @@ The goal is to generate an existing infrastructure on Netbox and have the abilit
|
||||||
- lldpd
|
- lldpd
|
||||||
- lshw
|
- lshw
|
||||||
|
|
||||||
# Known limitations
|
## Inventory requirement
|
||||||
|
- hpassacli
|
||||||
|
- storcli
|
||||||
|
- omreport
|
||||||
|
|
||||||
* The project is only compatible with Linux.
|
# Installation
|
||||||
Since it uses `ethtool` and parses `/sys/` directory, it's not compatible with *BSD distributions.
|
|
||||||
* Netbox `>=2.6.0,<=2.6.2` has a caching problem ; if the cache lifetime is too high, the script can get stale data after modification.
|
```
|
||||||
We advise to set `CACHE_TIME` to `0`.
|
# pip3 install netbox-agent
|
||||||
|
```
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
The agent can be run from a shell and get its configuration from either the configuration file or environment variables.
|
||||||
|
|
||||||
|
Configuration values are overridden based on the following precedence: command line arguments (might include config file) > environment variables > default config file > defaults.
|
||||||
|
|
||||||
|
```
|
||||||
|
# netbox_agent -c /etc/netbox_agent.yaml --register
|
||||||
|
INFO:root:Creating chassis blade (serial: QTFCQ574502EF)
|
||||||
|
INFO:root:Creating blade (serial: QTFCQ574502D2) myserver on chassis QTFCQ574502EF
|
||||||
|
INFO:root:Setting device (QTFCQ574502D2) new slot on Slot 9 (Chassis QTFCQ574502EF)..
|
||||||
|
INFO:root:Interface a8:1e:84:f2:9e:6a not found, creating..
|
||||||
|
INFO:root:Creating NIC enp1s0f1 (a8:1e:84:f2:9e:6a) on myserver
|
||||||
|
INFO:root:Interface 02:42:7a:89:cf:a4 not found, creating..
|
||||||
|
INFO:root:Creating NIC br-07ea1e4a2f0e (02:42:7a:89:cf:a4) on myserver
|
||||||
|
INFO:root:Create new IP 172.19.0.1/16 on br-07ea1e4a2f0e
|
||||||
|
INFO:root:Interface a8:1e:84:f2:9e:69 not found, creating..
|
||||||
|
INFO:root:Creating NIC enp1s0f0 (a8:1e:84:f2:9e:69) on myserver
|
||||||
|
INFO:root:Create new IP 42.42.42.42/24 on enp1s0f0
|
||||||
|
INFO:root:Create new IP fe80::aa1e:84ff:fef2:9e69/64 on enp1s0f0
|
||||||
|
INFO:root:Interface a8:1e:84:cd:9d:d6 not found, creating..
|
||||||
|
INFO:root:Creating NIC IPMI (a8:1e:84:cd:9d:d6) on myserver
|
||||||
|
INFO:root:Create new IP 10.191.122.10/24 on IPMI
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need, you can update only specific informations like:
|
||||||
|
* Network
|
||||||
|
* Inventory
|
||||||
|
* Location
|
||||||
|
* PSUs
|
||||||
|
|
||||||
|
```
|
||||||
|
# ip a add 42.42.42.43/24 dev enp1s0f1
|
||||||
|
# netbox_agent -c /etc/netbox_agent.yaml --update-network
|
||||||
|
INFO:root:Create new IP 42.42.42.43/24 on enp1s0f1
|
||||||
|
# netbox_agent --update-inventory
|
||||||
|
INFO:root:Creating Disk Samsung SSD 850 S2RBNX0K101698D
|
||||||
|
```
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
|
|
||||||
```
|
```
|
||||||
|
# Netbox configuration
|
||||||
netbox:
|
netbox:
|
||||||
url: 'http://netbox.internal.company.com'
|
url: 'http://netbox.internal.company.com'
|
||||||
token: supersecrettoken
|
token: supersecrettoken
|
||||||
|
# uncomment to disable ssl verification
|
||||||
|
# ssl_verify: false
|
||||||
|
# uncomment to use the system's CA certificates
|
||||||
|
# ssl_ca_certs_file: /etc/ssl/certs/ca-certificates.crt
|
||||||
|
|
||||||
|
# Network configuration
|
||||||
network:
|
network:
|
||||||
|
# Regex to ignore interfaces
|
||||||
ignore_interfaces: "(dummy.*|docker.*)"
|
ignore_interfaces: "(dummy.*|docker.*)"
|
||||||
|
# Regex to ignore IP addresses
|
||||||
ignore_ips: (127\.0\.0\..*)
|
ignore_ips: (127\.0\.0\..*)
|
||||||
# enable auto-cabling
|
# enable auto-cabling by parsing LLDP answers
|
||||||
lldp: true
|
lldp: true
|
||||||
|
|
||||||
|
#
|
||||||
|
# You can use these to change the Netbox roles.
|
||||||
|
# These are the defaults.
|
||||||
|
#
|
||||||
|
#device:
|
||||||
|
# chassis_role: "Server Chassis"
|
||||||
|
# blade_role: "Blade"
|
||||||
|
# server_role: "Server"
|
||||||
|
# tags: server, blade, ,just a comma,delimited,list
|
||||||
|
# custom_fields: field1=value1,field2=value2#
|
||||||
|
#
|
||||||
|
# Can use this to set the tenant
|
||||||
|
#
|
||||||
|
#tenant:
|
||||||
|
# driver: "file:/tmp/tenant"
|
||||||
|
# regex: "(.*)"
|
||||||
|
|
||||||
|
## Enable virtual machine support
|
||||||
|
# virtual:
|
||||||
|
# # not mandatory, can be guessed
|
||||||
|
# enabled: True
|
||||||
|
# # see https://netbox.company.com/virtualization/clusters/
|
||||||
|
# cluster_name: my_vm_cluster
|
||||||
|
|
||||||
|
# Enable datacenter location feature in Netbox
|
||||||
datacenter_location:
|
datacenter_location:
|
||||||
driver: "cmd:cat /etc/qualification | tr [a-z] [A-Z]"
|
driver: "cmd:cat /etc/qualification | tr [A-Z] [a-z]"
|
||||||
regex: "DATACENTER: (?P<datacenter>[A-Za-z0-9]+)"
|
regex: "datacenter: (?P<datacenter>[A-Za-z0-9]+)"
|
||||||
# driver: 'cmd:lldpctl'
|
# driver: 'cmd:lldpctl'
|
||||||
# regex: 'SysName: .*\.([A-Za-z0-9]+)'
|
# regex: 'SysName: .*\.([A-Za-z0-9]+)'
|
||||||
#
|
#
|
||||||
# driver: "file:/tmp/datacenter"
|
# driver: "file:/tmp/datacenter"
|
||||||
# regex: "(.*)"
|
# regex: "(.*)"
|
||||||
|
|
||||||
|
# Enable rack location feature in Netbox
|
||||||
rack_location:
|
rack_location:
|
||||||
# driver: 'cmd:lldpctl'
|
# driver: 'cmd:lldpctl'
|
||||||
# match SysName: sw-dist-a1.dc42
|
# match SysName: sw-dist-a1.dc42
|
||||||
|
@ -70,6 +147,7 @@ rack_location:
|
||||||
# driver: "file:/tmp/datacenter"
|
# driver: "file:/tmp/datacenter"
|
||||||
# regex: "(.*)"
|
# regex: "(.*)"
|
||||||
|
|
||||||
|
# Enable local inventory reporting
|
||||||
inventory: true
|
inventory: true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -84,6 +162,36 @@ The `get_blade_slot` method return the name of the `Device Bay`.
|
||||||
|
|
||||||
Certain vendors don't report the blade slot in `dmidecode`, so we can use the `slot_location` regex feature of the configuration file.
|
Certain vendors don't report the blade slot in `dmidecode`, so we can use the `slot_location` regex feature of the configuration file.
|
||||||
|
|
||||||
|
Some blade servers can be equipped with additional hardware using expansion blades, next to the processing blade, such as GPU expansion, or drives bay expansion. By default, the hardware from the expnasion is associated with the blade server itself, but it's possible to register the expansion as its own device using the `--expansion-as-device` command line parameter, or by setting `expansion_as_device` to `true` in the configuration file.
|
||||||
|
|
||||||
|
## Drives attributes processing
|
||||||
|
|
||||||
|
It is possible to process drives extended attributes such as the drive's physical or logical identifier, logical drive RAID type, size, consistency and so on.
|
||||||
|
|
||||||
|
Those attributes as set as `custom_fields` in Netbox, and need to be registered properly before being able to specify them during the inventory phase.
|
||||||
|
|
||||||
|
As the custom fields have to be created prior being able to register the disks extended attributes, this feature is only activated using the `--process-virtual-drives` command line parameter, or by setting `process_virtual_drives` to `true` in the configuration file.
|
||||||
|
|
||||||
|
The custom fields to create as `DCIM > inventory item` `Text` are described below.
|
||||||
|
|
||||||
|
```
|
||||||
|
NAME LABEL DESCRIPTION
|
||||||
|
mount_point Mount point Device mount point(s)
|
||||||
|
pd_identifier Physical disk identifier Physical disk identifier in the RAID controller
|
||||||
|
vd_array Virtual drive array Virtual drive array the disk is member of
|
||||||
|
vd_consistency Virtual drive consistency Virtual disk array consistency
|
||||||
|
vd_device Virtual drive device Virtual drive system device
|
||||||
|
vd_raid_type Virtual drive RAID Virtual drive array RAID type
|
||||||
|
vd_size Virtual drive size Virtual drive array size
|
||||||
|
```
|
||||||
|
|
||||||
|
In the current implementation, the disks attributes ore not updated: if a disk with the correct serial number is found, it's sufficient to consider it as up to date.
|
||||||
|
|
||||||
|
To force the reprocessing of the disks extended attributes, the `--force-disk-refresh` command line option can be used: it removes all existing disks to before populating them with the correct parsing. Unless this option is specified, the extended attributes won't be modified unless a disk is replaced.
|
||||||
|
|
||||||
|
It is possible to dump the physical/virtual disks map on the filesystem under the JSON notation to ease or automate disks management. The file path has to be provided using the `--dump-disks-map` command line parameter.
|
||||||
|
|
||||||
|
|
||||||
## Anycast IP
|
## Anycast IP
|
||||||
|
|
||||||
The default behavior of the agent is to assign an interface to an IP.
|
The default behavior of the agent is to assign an interface to an IP.
|
||||||
|
@ -95,11 +203,21 @@ In order to handle this case, user need to set Netbox IP's mode to `Anycast` so
|
||||||
|
|
||||||
Tested on:
|
Tested on:
|
||||||
|
|
||||||
## Dell Inc.
|
## Virtual Machines
|
||||||
|
|
||||||
|
* Hyper-V
|
||||||
|
* VMWare
|
||||||
|
* VirtualBox
|
||||||
|
* AWS
|
||||||
|
* GCP
|
||||||
|
|
||||||
|
## [Dell Inc.](https://github.com/Solvik/netbox-agent/blob/master/netbox_agent/vendors/dell.py)
|
||||||
|
|
||||||
### Blades
|
### Blades
|
||||||
|
|
||||||
|
* PowerEdge MX7000
|
||||||
* PowerEdge M1000e (your `DeviceType` should have slots named `Slot 01` and so on)
|
* PowerEdge M1000e (your `DeviceType` should have slots named `Slot 01` and so on)
|
||||||
|
* PowerEdge MX740c
|
||||||
* PowerEdge M640
|
* PowerEdge M640
|
||||||
* PowerEdge M630
|
* PowerEdge M630
|
||||||
* PowerEdge M620
|
* PowerEdge M620
|
||||||
|
@ -109,7 +227,7 @@ Tested on:
|
||||||
|
|
||||||
* DSS7500
|
* DSS7500
|
||||||
|
|
||||||
## HP / HPE
|
## [HP / HPE](https://github.com/Solvik/netbox-agent/blob/master/netbox_agent/vendors/hp.py)
|
||||||
|
|
||||||
### Blades
|
### Blades
|
||||||
|
|
||||||
|
@ -117,6 +235,8 @@ Tested on:
|
||||||
* HP ProLiant BL460c Gen8
|
* HP ProLiant BL460c Gen8
|
||||||
* HP ProLiant BL460c Gen9
|
* HP ProLiant BL460c Gen9
|
||||||
* HP ProLiant BL460c Gen10
|
* HP ProLiant BL460c Gen10
|
||||||
|
* HP ProLiant BL460c Gen10 Graphics Exp its expansion HP ProLiant BL460c Graphics Expansion Blade
|
||||||
|
* HP Moonshot 1500 Enclosure (your `DeviceType` should have slots batch create with `Bay c[1-45n1]`) with HP ProLiant m750, m710x, m510 Server Cartridge
|
||||||
|
|
||||||
### Pizzas
|
### Pizzas
|
||||||
|
|
||||||
|
@ -125,18 +245,18 @@ Tested on:
|
||||||
* ProLiant SL4540 Gen9
|
* ProLiant SL4540 Gen9
|
||||||
* ProLiant XL450 Gen10
|
* ProLiant XL450 Gen10
|
||||||
|
|
||||||
## Supermicro
|
## [Supermicro](https://github.com/Solvik/netbox-agent/blob/master/netbox_agent/vendors/supermicro.py)
|
||||||
|
|
||||||
### Blades
|
### Blades
|
||||||
|
|
||||||
Feel free to send me a dmidecode output for Supermicro's blade!
|
* SBI-* and SBA-* should be supported, but I need dmidecode output example to support automatic blade location
|
||||||
|
|
||||||
### Pizzas
|
### Pizzas
|
||||||
|
|
||||||
* SSG-6028R
|
* SSG-6028R
|
||||||
* SYS-6018R
|
* SYS-6018R
|
||||||
|
|
||||||
## QCT
|
## [QCT](https://github.com/Solvik/netbox-agent/blob/master/netbox_agent/vendors/qct.py)
|
||||||
|
|
||||||
### Blades
|
### Blades
|
||||||
|
|
||||||
|
@ -146,6 +266,27 @@ Feel free to send me a dmidecode output for Supermicro's blade!
|
||||||
|
|
||||||
* Nothing ATM, feel free to send me a dmidecode or make a PR!
|
* Nothing ATM, feel free to send me a dmidecode or make a PR!
|
||||||
|
|
||||||
# TODO
|
# Known limitations
|
||||||
|
|
||||||
- [ ] `CustomFields` support with firmware versions for Device (BIOS), RAID Cards and disks
|
* The project is only compatible with Linux.
|
||||||
|
Since it uses `ethtool` and parses `/sys/` directory, it's not compatible with *BSD distributions.
|
||||||
|
* Netbox `>=2.6.0,<=2.6.2` has a caching problem ; if the cache lifetime is too high, the script can get stale data after modification.
|
||||||
|
We advise to set `CACHE_TIME` to `0`.
|
||||||
|
|
||||||
|
# Developing
|
||||||
|
|
||||||
|
If you want to run the agent while adding features or just for debugging purposes
|
||||||
|
|
||||||
|
```
|
||||||
|
# git clone https://github.com/Solvik/netbox-agent.git
|
||||||
|
# cd netbox-agent
|
||||||
|
# python3 -m netbox_agent.cli --register
|
||||||
|
```
|
||||||
|
|
||||||
|
On a personal note, I use the docker image from [netbox-community/netbox-docker](https://github.com/netbox-community/netbox-docker)
|
||||||
|
```
|
||||||
|
# git clone https://github.com/netbox-community/netbox-docker
|
||||||
|
# cd netbox-docker
|
||||||
|
# docker-compose pull
|
||||||
|
# docker-compose up
|
||||||
|
```
|
||||||
|
|
55
default.nix
Normal file
55
default.nix
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
{
|
||||||
|
sources ? import ./npins,
|
||||||
|
pkgs ? import sources.nixpkgs { },
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
checks = (import sources.git-hooks).run {
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
hooks =
|
||||||
|
{
|
||||||
|
commitizen.enable = true;
|
||||||
|
}
|
||||||
|
// (pkgs.lib.genAttrs
|
||||||
|
[
|
||||||
|
"black"
|
||||||
|
"isort"
|
||||||
|
"ruff"
|
||||||
|
]
|
||||||
|
(hook: {
|
||||||
|
enable = true;
|
||||||
|
stages = [ "pre-push" ];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
python3 = pkgs.python3.override {
|
||||||
|
packageOverrides = self: _: {
|
||||||
|
netifaces2 = self.callPackage ./nix/netifaces2.nix { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
devShell = pkgs.mkShell {
|
||||||
|
name = "netbox-agent.dev";
|
||||||
|
|
||||||
|
packages = [
|
||||||
|
(python3.withPackages (ps: [
|
||||||
|
ps.pynetbox
|
||||||
|
ps.netaddr
|
||||||
|
ps.netifaces2
|
||||||
|
ps.pyyaml
|
||||||
|
ps.jsonargparse
|
||||||
|
ps.python-slugify
|
||||||
|
ps.packaging
|
||||||
|
ps.distro
|
||||||
|
]))
|
||||||
|
] ++ checks.enabledPackages;
|
||||||
|
|
||||||
|
shellHook = ''
|
||||||
|
${checks.shellHook}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
|
-r requirements.txt
|
||||||
|
|
||||||
pytest
|
pytest
|
||||||
pytest-cov
|
pytest-cov
|
||||||
mypy
|
flake8
|
||||||
flake8==3.7.8
|
flake8-isort
|
||||||
pep8-naming==0.8.2
|
tox
|
||||||
flake8-quotes==2.1.0
|
|
||||||
flake8-import-order==0.18.1
|
|
||||||
Sphinx
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
netbox:
|
netbox:
|
||||||
url: 'http://netbox.internal.company.com'
|
url: 'http://netbox.internal.company.com'
|
||||||
token: supersecrettoken
|
token: supersecrettoken
|
||||||
|
# uncomment to disable ssl verification
|
||||||
|
# ssl_verify: false
|
||||||
|
|
||||||
network:
|
network:
|
||||||
ignore_interfaces: "(dummy.*|docker.*)"
|
ignore_interfaces: "(dummy.*|docker.*)"
|
||||||
|
@ -8,9 +10,26 @@ network:
|
||||||
# enable auto-cabling
|
# enable auto-cabling
|
||||||
lldp: true
|
lldp: true
|
||||||
|
|
||||||
|
#
|
||||||
|
# You can use these to change the roles.
|
||||||
|
#
|
||||||
|
#device:
|
||||||
|
# chassis_role: "Server Chassis"
|
||||||
|
# blade_role: "Blade"
|
||||||
|
# server_role: "Server"
|
||||||
|
# tags: server, blade, ,just a comma,delimited,list
|
||||||
|
# custom_fields: field1=value1,field2=value2
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Use this to set the tenant
|
||||||
|
#
|
||||||
|
#tenant:
|
||||||
|
# driver: "file:/tmp/tenant"
|
||||||
|
# regex: "(.*)"
|
||||||
|
|
||||||
datacenter_location:
|
datacenter_location:
|
||||||
driver: "cmd:cat /etc/qualification | tr [a-z] [A-Z]"
|
driver: "cmd:cat /etc/qualification | tr [A-Z] [a-z]"
|
||||||
regex: "DATACENTER: (?P<datacenter>[A-Za-z0-9]+)"
|
regex: "datacenter: (?P<datacenter>[A-Za-z0-9]+)"
|
||||||
# driver: 'cmd:lldpctl'
|
# driver: 'cmd:lldpctl'
|
||||||
# regex: 'SysName: .*\.([A-Za-z0-9]+)'
|
# regex: 'SysName: .*\.([A-Za-z0-9]+)'
|
||||||
#
|
#
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from pkg_resources import DistributionNotFound, get_distribution
|
from importlib.metadata import PackageNotFoundError
|
||||||
|
from importlib.metadata import version as _get_version
|
||||||
|
|
||||||
try:
|
try:
|
||||||
__version__ = get_distribution(__name__).version
|
__version__ = _get_version(__name__)
|
||||||
except DistributionNotFound:
|
except PackageNotFoundError:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -1,37 +1,63 @@
|
||||||
from netbox_agent.logging import logging # NOQA
|
from packaging import version
|
||||||
from netbox_agent.vendors.dell import DellHost
|
|
||||||
import netbox_agent.dmidecode as dmidecode
|
import netbox_agent.dmidecode as dmidecode
|
||||||
from netbox_agent.config import config
|
from netbox_agent.config import config
|
||||||
|
from netbox_agent.config import netbox_instance as nb
|
||||||
|
from netbox_agent.logging import logging # NOQA
|
||||||
|
from netbox_agent.vendors.dell import DellHost
|
||||||
|
from netbox_agent.vendors.generic import GenericHost
|
||||||
from netbox_agent.vendors.hp import HPHost
|
from netbox_agent.vendors.hp import HPHost
|
||||||
from netbox_agent.vendors.qct import QCTHost
|
from netbox_agent.vendors.qct import QCTHost
|
||||||
from netbox_agent.vendors.supermicro import SupermicroHost
|
from netbox_agent.vendors.supermicro import SupermicroHost
|
||||||
|
from netbox_agent.virtualmachine import VirtualMachine, is_vm
|
||||||
|
|
||||||
MANUFACTURERS = {
|
MANUFACTURERS = {
|
||||||
'Dell Inc.': DellHost,
|
"Dell Inc.": DellHost,
|
||||||
'HP': HPHost,
|
"HP": HPHost,
|
||||||
'HPE': HPHost,
|
"HPE": HPHost,
|
||||||
'Supermicro': SupermicroHost,
|
"Supermicro": SupermicroHost,
|
||||||
'Quanta Cloud Technology Inc.': QCTHost,
|
"Quanta Cloud Technology Inc.": QCTHost,
|
||||||
}
|
"Generic": GenericHost,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def run(config):
|
def run(config):
|
||||||
manufacturer = dmidecode.get_by_type('Chassis')[0].get('Manufacturer')
|
dmi = dmidecode.parse()
|
||||||
server = MANUFACTURERS[manufacturer](dmi=dmidecode)
|
|
||||||
|
|
||||||
|
if config.virtual.enabled or is_vm(dmi):
|
||||||
|
if not config.virtual.cluster_name:
|
||||||
|
raise Exception(
|
||||||
|
"virtual.cluster_name parameter is mandatory because it's a VM"
|
||||||
|
)
|
||||||
|
server = VirtualMachine(dmi=dmi)
|
||||||
|
else:
|
||||||
|
manufacturer = dmidecode.get_by_type(dmi, "Chassis")[0].get("Manufacturer")
|
||||||
|
try:
|
||||||
|
server = MANUFACTURERS[manufacturer](dmi=dmi)
|
||||||
|
except KeyError:
|
||||||
|
server = GenericHost(dmi=dmi)
|
||||||
|
|
||||||
|
if version.parse(nb.version) < version.parse("3.7"):
|
||||||
|
print("netbox-agent is not compatible with Netbox prior to version 3.7")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if (
|
||||||
|
config.register
|
||||||
|
or config.update_all
|
||||||
|
or config.update_network
|
||||||
|
or config.update_location
|
||||||
|
or config.update_inventory
|
||||||
|
or config.update_psu
|
||||||
|
):
|
||||||
|
server.netbox_create_or_update(config)
|
||||||
if config.debug:
|
if config.debug:
|
||||||
server.print_debug()
|
server.print_debug()
|
||||||
if config.register:
|
|
||||||
server.netbox_create(config)
|
|
||||||
if config.update_all or config.update_network or config.update_location or \
|
|
||||||
config.update_inventory or config.update_psu:
|
|
||||||
server.netbox_update(config)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
return run(config)
|
return 0 if run(config) else 1
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,68 +1,186 @@
|
||||||
import logging
|
import logging
|
||||||
import pynetbox
|
|
||||||
import jsonargparse
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import jsonargparse
|
||||||
|
import pynetbox
|
||||||
|
import requests
|
||||||
|
import urllib3
|
||||||
|
|
||||||
|
|
||||||
def get_config():
|
def get_config():
|
||||||
p = jsonargparse.ArgumentParser(
|
p = jsonargparse.ArgumentParser(
|
||||||
default_config_files=[
|
default_config_files=[
|
||||||
'/etc/netbox_agent.yaml',
|
"/etc/netbox_agent.yaml",
|
||||||
'~/.config/netbox_agent.yaml',
|
"~/.config/netbox_agent.yaml",
|
||||||
'~/.netbox_agent.yaml',
|
"~/.netbox_agent.yaml",
|
||||||
],
|
],
|
||||||
prog='netbox_agent',
|
prog="netbox_agent",
|
||||||
description="Netbox agent to run on your infrastructure's servers",
|
description="Netbox agent to run on your infrastructure's servers",
|
||||||
|
env_prefix="NETBOX_AGENT_",
|
||||||
|
default_env=True,
|
||||||
)
|
)
|
||||||
p.add_argument('-c', '--config', action=jsonargparse.ActionConfigFile)
|
p.add_argument("-c", "--config", action=jsonargparse.ActionConfigFile)
|
||||||
|
|
||||||
p.add_argument('-r', '--register', action='store_true', help='Register server to Netbox')
|
p.add_argument(
|
||||||
p.add_argument('-u', '--update-all', action='store_true', help='Update all infos in Netbox')
|
"-r", "--register", action="store_true", help="Register server to Netbox"
|
||||||
p.add_argument('-d', '--debug', action='store_true', help='Print debug infos')
|
)
|
||||||
p.add_argument('--update-network', action='store_true', help='Update network')
|
p.add_argument(
|
||||||
p.add_argument('--update-inventory', action='store_true', help='Update inventory')
|
"-u", "--update-all", action="store_true", help="Update all infos in Netbox"
|
||||||
p.add_argument('--update-location', action='store_true', help='Update location')
|
)
|
||||||
p.add_argument('--update-psu', action='store_true', help='Update PSU')
|
p.add_argument("-d", "--debug", action="store_true", help="Print debug infos")
|
||||||
|
p.add_argument("--update-network", action="store_true", help="Update network")
|
||||||
|
p.add_argument("--update-inventory", action="store_true", help="Update inventory")
|
||||||
|
p.add_argument("--update-location", action="store_true", help="Update location")
|
||||||
|
p.add_argument("--update-psu", action="store_true", help="Update PSU")
|
||||||
|
p.add_argument(
|
||||||
|
"--purge-old-devices",
|
||||||
|
action="store_true",
|
||||||
|
help="Purge existing (old ?) devices having same name but different serial",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--expansion-as-device",
|
||||||
|
action="store_true",
|
||||||
|
help="Manage blade expansions as external devices",
|
||||||
|
)
|
||||||
|
|
||||||
p.add_argument('--log_level', default='debug')
|
p.add_argument("--log_level", default="debug")
|
||||||
p.add_argument('--netbox.url', help='Netbox URL')
|
p.add_argument("--netbox.ssl_ca_certs_file", help="SSL CA certificates file")
|
||||||
p.add_argument('--netbox.token', help='Netbox API Token')
|
p.add_argument("--netbox.url", help="Netbox URL")
|
||||||
p.add_argument('--hostname_cmd', default=None,
|
p.add_argument("--netbox.token", help="Netbox API Token")
|
||||||
help="Command to output hostname, used as Device's name in netbox")
|
p.add_argument(
|
||||||
p.add_argument('--datacenter_location.driver',
|
"--netbox.ssl_verify",
|
||||||
help='Datacenter location driver, ie: cmd, file')
|
default=True,
|
||||||
p.add_argument('--datacenter_location.driver_file',
|
action="store_true",
|
||||||
help='Datacenter location custom driver file path')
|
help="Disable SSL verification",
|
||||||
p.add_argument('--datacenter_location.regex',
|
)
|
||||||
help='Datacenter location regex to extract Netbox DC slug')
|
p.add_argument(
|
||||||
p.add_argument('--rack_location.driver', help='Rack location driver, ie: cmd, file')
|
"--virtual.enabled", action="store_true", help="Is a virtual machine or not"
|
||||||
p.add_argument('--rack_location.driver_file', help='Rack location custom driver file path')
|
)
|
||||||
p.add_argument('--rack_location.regex', help='Rack location regex to extract Rack name')
|
p.add_argument("--virtual.cluster_name", help="Cluster name of VM")
|
||||||
p.add_argument('--slot_location.driver', help='Slot location driver, ie: cmd, file')
|
p.add_argument(
|
||||||
p.add_argument('--slot_location.driver_file', help='Slot location custom driver file path')
|
"--hostname_cmd",
|
||||||
p.add_argument('--slot_location.regex', help='Slot location regex to extract slot name')
|
default=None,
|
||||||
p.add_argument('--network.ignore_interfaces', default=r'(dummy.*|docker.*)',
|
help="Command to output hostname, used as Device's name in netbox",
|
||||||
help='Regex to ignore interfaces')
|
)
|
||||||
p.add_argument('--network.ignore_ips', default=r'^(127\.0\.0\..*|fe80.*|::1.*)',
|
p.add_argument(
|
||||||
help='Regex to ignore IPs')
|
"--device.platform",
|
||||||
p.add_argument('--network.lldp', help='Enable auto-cabling feature through LLDP infos')
|
default=None,
|
||||||
p.add_argument('--inventory', action='store_true',
|
help="Override device platform. Here we use OS distribution.",
|
||||||
help='Enable HW inventory (CPU, Memory, RAID Cards, Disks) feature')
|
)
|
||||||
|
p.add_argument("--device.tags", default=r"", help="tags to use for a host")
|
||||||
|
p.add_argument(
|
||||||
|
"--preserve-tags",
|
||||||
|
action="store_true",
|
||||||
|
help="Append new unique tags, preserve those already present",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--device.custom_fields",
|
||||||
|
default=r"",
|
||||||
|
help="custom_fields to use for a host, eg: field1=v1,field2=v2",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--device.blade_role", default=r"Blade", help="role to use for a blade server"
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--device.chassis_role",
|
||||||
|
default=r"Server Chassis",
|
||||||
|
help="role to use for a chassis",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--device.server_role", default=r"Server", help="role to use for a server"
|
||||||
|
)
|
||||||
|
p.add_argument("--tenant.driver", help="tenant driver, ie cmd, file")
|
||||||
|
p.add_argument("--tenant.driver_file", help="tenant driver custom driver file path")
|
||||||
|
p.add_argument("--tenant.regex", help="tenant regex to extract Netbox tenant slug")
|
||||||
|
p.add_argument(
|
||||||
|
"--datacenter_location.driver", help="Datacenter location driver, ie: cmd, file"
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--datacenter_location.driver_file",
|
||||||
|
help="Datacenter location custom driver file path",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--datacenter_location.regex",
|
||||||
|
help="Datacenter location regex to extract Netbox DC slug",
|
||||||
|
)
|
||||||
|
p.add_argument("--rack_location.driver", help="Rack location driver, ie: cmd, file")
|
||||||
|
p.add_argument(
|
||||||
|
"--rack_location.driver_file", help="Rack location custom driver file path"
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--rack_location.regex", help="Rack location regex to extract Rack name"
|
||||||
|
)
|
||||||
|
p.add_argument("--slot_location.driver", help="Slot location driver, ie: cmd, file")
|
||||||
|
p.add_argument(
|
||||||
|
"--slot_location.driver_file", help="Slot location custom driver file path"
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--slot_location.regex", help="Slot location regex to extract slot name"
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--network.ignore_interfaces",
|
||||||
|
default=r"(dummy.*|docker.*)",
|
||||||
|
help="Regex to ignore interfaces",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--network.ignore_ips",
|
||||||
|
default=r"^(127\.0\.0\..*|fe80.*|::1.*)",
|
||||||
|
help="Regex to ignore IPs",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--network.ipmi", default=True, help="Enable gathering IPMI information"
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--network.lldp", help="Enable auto-cabling feature through LLDP infos"
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--inventory",
|
||||||
|
action="store_true",
|
||||||
|
help="Enable HW inventory (CPU, Memory, RAID Cards, Disks) feature",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--process-virtual-drives",
|
||||||
|
action="store_true",
|
||||||
|
help="Process virtual drives information from RAID "
|
||||||
|
"controllers to fill disk custom_fields",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--force-disk-refresh",
|
||||||
|
action="store_true",
|
||||||
|
help="Forces disks detection reprocessing",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--dump-disks-map", help="File path to dump physical/virtual disks map"
|
||||||
|
)
|
||||||
|
|
||||||
options = p.parse_args()
|
options = p.parse_args()
|
||||||
return options
|
return options
|
||||||
|
|
||||||
|
|
||||||
|
config = get_config()
|
||||||
|
|
||||||
|
|
||||||
def get_netbox_instance():
|
def get_netbox_instance():
|
||||||
config = get_config()
|
|
||||||
if config.netbox.url is None or config.netbox.token is None:
|
if config.netbox.url is None or config.netbox.token is None:
|
||||||
logging.error('Netbox URL and token are mandatory')
|
logging.error("Netbox URL and token are mandatory")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
return pynetbox.api(
|
|
||||||
|
nb = pynetbox.api(
|
||||||
url=get_config().netbox.url,
|
url=get_config().netbox.url,
|
||||||
token=get_config().netbox.token,
|
token=get_config().netbox.token,
|
||||||
)
|
)
|
||||||
|
ca_certs_file = config.netbox.ssl_ca_certs_file
|
||||||
|
if ca_certs_file is not None:
|
||||||
|
session = requests.Session()
|
||||||
|
session.verify = ca_certs_file
|
||||||
|
nb.http_session = session
|
||||||
|
elif config.netbox.ssl_verify is False:
|
||||||
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||||
|
session = requests.Session()
|
||||||
|
session.verify = False
|
||||||
|
nb.http_session = session
|
||||||
|
|
||||||
|
return nb
|
||||||
|
|
||||||
|
|
||||||
config = get_config()
|
|
||||||
netbox_instance = get_netbox_instance()
|
netbox_instance = get_netbox_instance()
|
||||||
|
|
|
@ -1,78 +1,83 @@
|
||||||
|
import logging
|
||||||
import re as _re
|
import re as _re
|
||||||
import subprocess as _subprocess
|
import subprocess as _subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from netbox_agent.misc import is_tool
|
from netbox_agent.misc import is_tool
|
||||||
import logging
|
|
||||||
|
|
||||||
_handle_re = _re.compile('^Handle\\s+(.+),\\s+DMI\\s+type\\s+(\\d+),\\s+(\\d+)\\s+bytes$')
|
_handle_re = _re.compile(
|
||||||
_in_block_re = _re.compile('^\\t\\t(.+)$')
|
"^Handle\\s+(.+),\\s+DMI\\s+type\\s+(\\d+),\\s+(\\d+)\\s+bytes$"
|
||||||
_record_re = _re.compile('\\t(.+):\\s+(.+)$')
|
)
|
||||||
_record2_re = _re.compile('\\t(.+):$')
|
_in_block_re = _re.compile("^\\t\\t(.+)$")
|
||||||
|
_record_re = _re.compile("\\t(.+):\\s+(.+)$")
|
||||||
|
_record2_re = _re.compile("\\t(.+):$")
|
||||||
|
|
||||||
_type2str = {
|
_type2str = {
|
||||||
0: 'BIOS',
|
0: "BIOS",
|
||||||
1: 'System',
|
1: "System",
|
||||||
2: 'Baseboard',
|
2: "Baseboard",
|
||||||
3: 'Chassis',
|
3: "Chassis",
|
||||||
4: 'Processor',
|
4: "Processor",
|
||||||
5: 'Memory Controller',
|
5: "Memory Controller",
|
||||||
6: 'Memory Module',
|
6: "Memory Module",
|
||||||
7: 'Cache',
|
7: "Cache",
|
||||||
8: 'Port Connector',
|
8: "Port Connector",
|
||||||
9: 'System Slots',
|
9: "System Slots",
|
||||||
10: ' On Board Devices',
|
10: " On Board Devices",
|
||||||
11: ' OEM Strings',
|
11: " OEM Strings",
|
||||||
12: ' System Configuration Options',
|
12: " System Configuration Options",
|
||||||
13: ' BIOS Language',
|
13: " BIOS Language",
|
||||||
14: ' Group Associations',
|
14: " Group Associations",
|
||||||
15: ' System Event Log',
|
15: " System Event Log",
|
||||||
16: ' Physical Memory Array',
|
16: " Physical Memory Array",
|
||||||
17: ' Memory Device',
|
17: " Memory Device",
|
||||||
18: ' 32-bit Memory Error',
|
18: " 32-bit Memory Error",
|
||||||
19: ' Memory Array Mapped Address',
|
19: " Memory Array Mapped Address",
|
||||||
20: ' Memory Device Mapped Address',
|
20: " Memory Device Mapped Address",
|
||||||
21: ' Built-in Pointing Device',
|
21: " Built-in Pointing Device",
|
||||||
22: ' Portable Battery',
|
22: " Portable Battery",
|
||||||
23: ' System Reset',
|
23: " System Reset",
|
||||||
24: ' Hardware Security',
|
24: " Hardware Security",
|
||||||
25: ' System Power Controls',
|
25: " System Power Controls",
|
||||||
26: ' Voltage Probe',
|
26: " Voltage Probe",
|
||||||
27: ' Cooling Device',
|
27: " Cooling Device",
|
||||||
28: ' Temperature Probe',
|
28: " Temperature Probe",
|
||||||
29: ' Electrical Current Probe',
|
29: " Electrical Current Probe",
|
||||||
30: ' Out-of-band Remote Access',
|
30: " Out-of-band Remote Access",
|
||||||
31: ' Boot Integrity Services',
|
31: " Boot Integrity Services",
|
||||||
32: ' System Boot',
|
32: " System Boot",
|
||||||
33: ' 64-bit Memory Error',
|
33: " 64-bit Memory Error",
|
||||||
34: ' Management Device',
|
34: " Management Device",
|
||||||
35: ' Management Device Component',
|
35: " Management Device Component",
|
||||||
36: ' Management Device Threshold Data',
|
36: " Management Device Threshold Data",
|
||||||
37: ' Memory Channel',
|
37: " Memory Channel",
|
||||||
38: ' IPMI Device',
|
38: " IPMI Device",
|
||||||
39: ' Power Supply',
|
39: " Power Supply",
|
||||||
40: ' Additional Information',
|
40: " Additional Information",
|
||||||
41: ' Onboard Devices Extended Information',
|
41: " Onboard Devices Extended Information",
|
||||||
42: ' Management Controller Host Interface'
|
42: " Management Controller Host Interface",
|
||||||
}
|
}
|
||||||
_str2type = {}
|
_str2type = {}
|
||||||
for type_id, type_str in _type2str.items():
|
for type_id, type_str in _type2str.items():
|
||||||
_str2type[type_str] = type_id
|
_str2type[type_str] = type_id
|
||||||
|
|
||||||
|
|
||||||
def parse():
|
def parse(output=None):
|
||||||
"""
|
"""
|
||||||
parse the full output of the dmidecode
|
parse the full output of the dmidecode
|
||||||
command and return a dic containing the parsed information
|
command and return a dic containing the parsed information
|
||||||
"""
|
"""
|
||||||
buffer = _execute_cmd()
|
if output:
|
||||||
|
buffer = output
|
||||||
|
else:
|
||||||
|
buffer = _execute_cmd()
|
||||||
if isinstance(buffer, bytes):
|
if isinstance(buffer, bytes):
|
||||||
buffer = buffer.decode('utf-8')
|
buffer = buffer.decode("utf-8")
|
||||||
_data = _parse(buffer)
|
_data = _parse(buffer)
|
||||||
return _data
|
return _data
|
||||||
|
|
||||||
|
|
||||||
def get_by_type(type_id):
|
def get_by_type(data, type_id):
|
||||||
"""
|
"""
|
||||||
filter the output of dmidecode per type
|
filter the output of dmidecode per type
|
||||||
0 BIOS
|
0 BIOS
|
||||||
|
@ -124,27 +129,33 @@ def get_by_type(type_id):
|
||||||
if type_id is None:
|
if type_id is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
data = parse()
|
|
||||||
result = []
|
result = []
|
||||||
for entry in data.values():
|
for entry in data.values():
|
||||||
if entry['DMIType'] == type_id:
|
if entry["DMIType"] == type_id:
|
||||||
result.append(entry)
|
result.append(entry)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _execute_cmd():
|
def _execute_cmd():
|
||||||
if not is_tool('dmidecode'):
|
if not is_tool("dmidecode"):
|
||||||
logging.error('Dmidecode does not seem to be present on your system. Add it your path or '
|
logging.error(
|
||||||
'check the compatibility of this project with your distro.')
|
"Dmidecode does not seem to be present on your system. Add it your path or "
|
||||||
|
"check the compatibility of this project with your distro."
|
||||||
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
return _subprocess.check_output(['dmidecode', ], stderr=_subprocess.PIPE)
|
return _subprocess.check_output(
|
||||||
|
[
|
||||||
|
"dmidecode",
|
||||||
|
],
|
||||||
|
stderr=_subprocess.PIPE,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _parse(buffer):
|
def _parse(buffer):
|
||||||
output_data = {}
|
output_data = {}
|
||||||
# Each record is separated by double newlines
|
# Each record is separated by double newlines
|
||||||
split_output = buffer.split('\n\n')
|
split_output = buffer.split("\n\n")
|
||||||
|
|
||||||
for record in split_output:
|
for record in split_output:
|
||||||
record_element = record.splitlines()
|
record_element = record.splitlines()
|
||||||
|
@ -162,21 +173,21 @@ def _parse(buffer):
|
||||||
dmi_handle = handle_data[0]
|
dmi_handle = handle_data[0]
|
||||||
|
|
||||||
output_data[dmi_handle] = {}
|
output_data[dmi_handle] = {}
|
||||||
output_data[dmi_handle]['DMIType'] = int(handle_data[1])
|
output_data[dmi_handle]["DMIType"] = int(handle_data[1])
|
||||||
output_data[dmi_handle]['DMISize'] = int(handle_data[2])
|
output_data[dmi_handle]["DMISize"] = int(handle_data[2])
|
||||||
|
|
||||||
# Okay, we know 2nd line == name
|
# Okay, we know 2nd line == name
|
||||||
output_data[dmi_handle]['DMIName'] = record_element[1]
|
output_data[dmi_handle]["DMIName"] = record_element[1]
|
||||||
|
|
||||||
in_block_elemet = ''
|
in_block_elemet = ""
|
||||||
in_block_list = ''
|
in_block_list = ""
|
||||||
|
|
||||||
# Loop over the rest of the record, gathering values
|
# Loop over the rest of the record, gathering values
|
||||||
for i in range(2, len(record_element), 1):
|
for i in range(2, len(record_element), 1):
|
||||||
if i >= len(record_element):
|
if i >= len(record_element):
|
||||||
break
|
break
|
||||||
# Check whether we are inside a \t\t block
|
# Check whether we are inside a \t\t block
|
||||||
if in_block_elemet != '':
|
if in_block_elemet != "":
|
||||||
in_block_data = _in_block_re.findall(record_element[i])
|
in_block_data = _in_block_re.findall(record_element[i])
|
||||||
|
|
||||||
if in_block_data:
|
if in_block_data:
|
||||||
|
@ -190,7 +201,7 @@ def _parse(buffer):
|
||||||
else:
|
else:
|
||||||
# We are out of the \t\t block; reset it again, and let
|
# We are out of the \t\t block; reset it again, and let
|
||||||
# the parsing continue
|
# the parsing continue
|
||||||
in_block_elemet = ''
|
in_block_elemet = ""
|
||||||
|
|
||||||
record_data = _record_re.findall(record_element[i])
|
record_data = _record_re.findall(record_element[i])
|
||||||
|
|
||||||
|
@ -206,7 +217,7 @@ def _parse(buffer):
|
||||||
# This is an array of data - let the loop know we are inside
|
# This is an array of data - let the loop know we are inside
|
||||||
# an array block
|
# an array block
|
||||||
in_block_elemet = record_data2[0]
|
in_block_elemet = record_data2[0]
|
||||||
in_block_list = ''
|
in_block_list = ""
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import re
|
||||||
|
|
||||||
|
|
||||||
def get(value, regex):
|
def get(value, regex):
|
||||||
for line in open(value, 'r'):
|
for line in open(value, "r"):
|
||||||
r = re.search(regex, line)
|
r = re.search(regex, line)
|
||||||
if r and len(r.groups()) > 0:
|
if r and len(r.groups()) > 0:
|
||||||
return r.groups()[0]
|
return r.groups()[0]
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
import re
|
import re
|
||||||
from shutil import which
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from shutil import which
|
||||||
|
|
||||||
# Originally from https://github.com/opencoff/useful-scripts/blob/master/linktest.py
|
# Originally from https://github.com/opencoff/useful-scripts/blob/master/linktest.py
|
||||||
|
|
||||||
# mapping fields from ethtool output to simple names
|
# mapping fields from ethtool output to simple names
|
||||||
field_map = {
|
field_map = {
|
||||||
'Supported ports': 'ports',
|
"Supported ports": "ports",
|
||||||
'Supported link modes': 'sup_link_modes',
|
"Supported link modes": "sup_link_modes",
|
||||||
'Supports auto-negotiation': 'sup_autoneg',
|
"Supports auto-negotiation": "sup_autoneg",
|
||||||
'Advertised link modes': 'adv_link_modes',
|
"Advertised link modes": "adv_link_modes",
|
||||||
'Advertised auto-negotiation': 'adv_autoneg',
|
"Advertised auto-negotiation": "adv_autoneg",
|
||||||
'Speed': 'speed',
|
"Speed": "speed",
|
||||||
'Duplex': 'duplex',
|
"Duplex": "duplex",
|
||||||
'Port': 'port',
|
"Port": "port",
|
||||||
'Auto-negotiation': 'autoneg',
|
"Auto-negotiation": "autoneg",
|
||||||
'Link detected': 'link',
|
"Link detected": "link",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,12 +25,13 @@ def merge_two_dicts(x, y):
|
||||||
return z
|
return z
|
||||||
|
|
||||||
|
|
||||||
class Ethtool():
|
class Ethtool:
|
||||||
"""
|
"""
|
||||||
This class aims to parse ethtool output
|
This class aims to parse ethtool output
|
||||||
There is several bindings to have something proper, but it requires
|
There is several bindings to have something proper, but it requires
|
||||||
compilation and other requirements.
|
compilation and other requirements.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, interface, *args, **kwargs):
|
def __init__(self, interface, *args, **kwargs):
|
||||||
self.interface = interface
|
self.interface = interface
|
||||||
|
|
||||||
|
@ -39,39 +40,40 @@ class Ethtool():
|
||||||
parse ethtool output
|
parse ethtool output
|
||||||
"""
|
"""
|
||||||
|
|
||||||
output = subprocess.getoutput('ethtool {}'.format(self.interface))
|
output = subprocess.getoutput("ethtool {}".format(self.interface))
|
||||||
|
|
||||||
fields = {}
|
fields = {}
|
||||||
field = ''
|
field = ""
|
||||||
fields['speed'] = '-'
|
fields["speed"] = "-"
|
||||||
fields['link'] = '-'
|
fields["link"] = "-"
|
||||||
fields['duplex'] = '-'
|
fields["duplex"] = "-"
|
||||||
for line in output.split('\n')[1:]:
|
for line in output.split("\n")[1:]:
|
||||||
line = line.rstrip()
|
line = line.rstrip()
|
||||||
r = line.find(':')
|
r = line.find(":")
|
||||||
if r > 0:
|
if r > 0:
|
||||||
field = line[:r].strip()
|
field = line[:r].strip()
|
||||||
if field not in field_map:
|
if field not in field_map:
|
||||||
continue
|
continue
|
||||||
field = field_map[field]
|
field = field_map[field]
|
||||||
output = line[r+1:].strip()
|
output = line[r + 1 :].strip()
|
||||||
fields[field] = output
|
fields[field] = output
|
||||||
else:
|
else:
|
||||||
if len(field) > 0 and \
|
if len(field) > 0 and field in field_map:
|
||||||
field in field_map:
|
fields[field] += " " + line.strip()
|
||||||
fields[field] += ' ' + line.strip()
|
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
def _parse_ethtool_module_output(self):
|
def _parse_ethtool_module_output(self):
|
||||||
status, output = subprocess.getstatusoutput('ethtool -m {}'.format(self.interface))
|
status, output = subprocess.getstatusoutput(
|
||||||
if status != 0:
|
"ethtool -m {}".format(self.interface)
|
||||||
return {}
|
)
|
||||||
r = re.search(r'Identifier.*\((\w+)\)', output)
|
if status == 0:
|
||||||
if r and len(r.groups()) > 0:
|
r = re.search(r"Identifier.*\((\w+)\)", output)
|
||||||
return {'form_factor': r.groups()[0]}
|
if r and len(r.groups()) > 0:
|
||||||
|
return {"form_factor": r.groups()[0]}
|
||||||
|
return {}
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
if which('ethtool') is None:
|
if which("ethtool") is None:
|
||||||
return None
|
return None
|
||||||
output = self._parse_ethtool_output()
|
output = self._parse_ethtool_output()
|
||||||
output.update(self._parse_ethtool_module_output())
|
output.update(self._parse_ethtool_module_output())
|
||||||
|
|
|
@ -1,24 +1,31 @@
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
import pynetbox
|
import pynetbox
|
||||||
|
|
||||||
from netbox_agent.config import netbox_instance as nb, config
|
from netbox_agent.config import config
|
||||||
from netbox_agent.misc import is_tool, get_vendor
|
from netbox_agent.config import netbox_instance as nb
|
||||||
|
from netbox_agent.lshw import LSHW
|
||||||
|
from netbox_agent.misc import get_vendor, is_tool
|
||||||
from netbox_agent.raid.hp import HPRaid
|
from netbox_agent.raid.hp import HPRaid
|
||||||
from netbox_agent.raid.omreport import OmreportRaid
|
from netbox_agent.raid.omreport import OmreportRaid
|
||||||
from netbox_agent.raid.storcli import StorcliRaid
|
from netbox_agent.raid.storcli import StorcliRaid
|
||||||
from netbox_agent.lshw import LSHW
|
|
||||||
|
|
||||||
INVENTORY_TAG = {
|
INVENTORY_TAG = {
|
||||||
'cpu': {'name': 'hw:cpu', 'slug': 'hw-cpu'},
|
"cpu": {"name": "hw:cpu", "slug": "hw-cpu"},
|
||||||
'disk': {'name': 'hw:disk', 'slug': 'hw-disk'},
|
"gpu": {"name": "hw:gpu", "slug": "hw-gpu"},
|
||||||
'interface': {'name': 'hw:interface', 'slug': 'hw-interface'},
|
"disk": {"name": "hw:disk", "slug": "hw-disk"},
|
||||||
'memory': {'name': 'hw:memory', 'slug': 'hw-memory'},
|
"interface": {"name": "hw:interface", "slug": "hw-interface"},
|
||||||
'motherboard': {'name': 'hw:motherboard', 'slug': 'hw-motherboard'},
|
"memory": {"name": "hw:memory", "slug": "hw-memory"},
|
||||||
'raid_card': {'name': 'hw:raid_card', 'slug': 'hw-raid-card'},
|
"motherboard": {"name": "hw:motherboard", "slug": "hw-motherboard"},
|
||||||
}
|
"raid_card": {"name": "hw:raid_card", "slug": "hw-raid-card"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Inventory():
|
class Inventory:
|
||||||
"""
|
"""
|
||||||
Better Inventory items coming, see:
|
Better Inventory items coming, see:
|
||||||
- https://github.com/netbox-community/netbox/issues/3087
|
- https://github.com/netbox-community/netbox/issues/3087
|
||||||
|
@ -29,6 +36,7 @@ class Inventory():
|
||||||
* cpu
|
* cpu
|
||||||
* raid cards
|
* raid cards
|
||||||
* disks
|
* disks
|
||||||
|
* gpus
|
||||||
|
|
||||||
methods that:
|
methods that:
|
||||||
* get local item
|
* get local item
|
||||||
|
@ -41,10 +49,11 @@ class Inventory():
|
||||||
- no scan of NVMe devices
|
- no scan of NVMe devices
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, server):
|
def __init__(self, server, update_expansion=False):
|
||||||
self.create_netbox_tags()
|
self.create_netbox_tags()
|
||||||
self.server = server
|
self.server = server
|
||||||
netbox_server = self.server.get_netbox_server()
|
self.update_expansion = update_expansion
|
||||||
|
netbox_server = self.server.get_netbox_server(update_expansion)
|
||||||
|
|
||||||
self.device_id = netbox_server.id if netbox_server else None
|
self.device_id = netbox_server.id if netbox_server else None
|
||||||
self.raid = None
|
self.raid = None
|
||||||
|
@ -53,16 +62,17 @@ class Inventory():
|
||||||
self.lshw = LSHW()
|
self.lshw = LSHW()
|
||||||
|
|
||||||
def create_netbox_tags(self):
|
def create_netbox_tags(self):
|
||||||
|
ret = []
|
||||||
for key, tag in INVENTORY_TAG.items():
|
for key, tag in INVENTORY_TAG.items():
|
||||||
nb_tag = nb.extras.tags.get(
|
nb_tag = nb.extras.tags.get(name=tag["name"])
|
||||||
name=tag['name']
|
|
||||||
)
|
|
||||||
if not nb_tag:
|
if not nb_tag:
|
||||||
nb_tag = nb.extras.tags.create(
|
nb_tag = nb.extras.tags.create(
|
||||||
name=tag['name'],
|
name=tag["name"],
|
||||||
slug=tag['slug'],
|
slug=tag["slug"],
|
||||||
comments=tag['name'],
|
comments=tag["name"],
|
||||||
)
|
)
|
||||||
|
ret.append(nb_tag)
|
||||||
|
return ret
|
||||||
|
|
||||||
def find_or_create_manufacturer(self, name):
|
def find_or_create_manufacturer(self, name):
|
||||||
if name is None:
|
if name is None:
|
||||||
|
@ -72,29 +82,28 @@ class Inventory():
|
||||||
name=name,
|
name=name,
|
||||||
)
|
)
|
||||||
if not manufacturer:
|
if not manufacturer:
|
||||||
logging.info('Creating missing manufacturer {name}'.format(name=name))
|
logging.info("Creating missing manufacturer {name}".format(name=name))
|
||||||
manufacturer = nb.dcim.manufacturers.create(
|
manufacturer = nb.dcim.manufacturers.create(
|
||||||
name=name,
|
name=name,
|
||||||
slug=name.replace(' ', '-').replace('.', '').lower(),
|
slug=re.sub("[^A-Za-z0-9]+", "-", name).lower(),
|
||||||
)
|
)
|
||||||
|
|
||||||
logging.info('Creating missing manufacturer {name}'.format(name=name))
|
logging.info("Creating missing manufacturer {name}".format(name=name))
|
||||||
|
|
||||||
return manufacturer
|
return manufacturer
|
||||||
|
|
||||||
def get_netbox_inventory(self, device_id, tag):
|
def get_netbox_inventory(self, device_id, tag):
|
||||||
try:
|
try:
|
||||||
items = nb.dcim.inventory_items.filter(
|
items = nb.dcim.inventory_items.filter(device_id=device_id, tag=tag)
|
||||||
device_id=device_id,
|
|
||||||
tag=tag
|
|
||||||
)
|
|
||||||
except pynetbox.core.query.RequestError:
|
except pynetbox.core.query.RequestError:
|
||||||
logging.info('Tag {tag} is missing, returning empty array.'.format(tag=tag))
|
logging.info("Tag {tag} is missing, returning empty array.".format(tag=tag))
|
||||||
items = []
|
items = []
|
||||||
|
|
||||||
return items
|
return list(items)
|
||||||
|
|
||||||
def create_netbox_inventory_item(self, device_id, tags, vendor, name, serial, description):
|
def create_netbox_inventory_item(
|
||||||
|
self, device_id, tags, vendor, name, serial, description
|
||||||
|
):
|
||||||
manufacturer = self.find_or_create_manufacturer(vendor)
|
manufacturer = self.find_or_create_manufacturer(vendor)
|
||||||
|
|
||||||
_ = nb.dcim.inventory_items.create(
|
_ = nb.dcim.inventory_items.create(
|
||||||
|
@ -102,26 +111,25 @@ class Inventory():
|
||||||
manufacturer=manufacturer.id,
|
manufacturer=manufacturer.id,
|
||||||
discovered=True,
|
discovered=True,
|
||||||
tags=tags,
|
tags=tags,
|
||||||
name='{}'.format(name),
|
name="{}".format(name),
|
||||||
serial='{}'.format(serial),
|
serial="{}".format(serial),
|
||||||
description=description
|
description=description,
|
||||||
)
|
)
|
||||||
|
|
||||||
logging.info('Creating inventory item {} {}/{} {} '.format(
|
logging.info(
|
||||||
vendor,
|
"Creating inventory item {} {}/{} {} ".format(
|
||||||
name,
|
vendor, name, serial, description
|
||||||
serial,
|
)
|
||||||
description)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_hw_motherboards(self):
|
def get_hw_motherboards(self):
|
||||||
motherboards = []
|
motherboards = []
|
||||||
|
|
||||||
m = {}
|
m = {}
|
||||||
m['serial'] = self.lshw.motherboard_serial
|
m["serial"] = self.lshw.motherboard_serial
|
||||||
m['vendor'] = self.lshw.vendor
|
m["vendor"] = self.lshw.vendor
|
||||||
m['name'] = '{} {}'.format(self.lshw.vendor, self.lshw.motherboard)
|
m["name"] = "{} {}".format(self.lshw.vendor, self.lshw.motherboard)
|
||||||
m['description'] = '{} Motherboard'.format(self.lshw.motherboard)
|
m["description"] = "{} Motherboard".format(self.lshw.motherboard)
|
||||||
|
|
||||||
motherboards.append(m)
|
motherboards.append(m)
|
||||||
|
|
||||||
|
@ -131,27 +139,29 @@ class Inventory():
|
||||||
|
|
||||||
motherboards = self.get_hw_motherboards()
|
motherboards = self.get_hw_motherboards()
|
||||||
nb_motherboards = self.get_netbox_inventory(
|
nb_motherboards = self.get_netbox_inventory(
|
||||||
device_id=self.device_id,
|
device_id=self.device_id, tag=INVENTORY_TAG["motherboard"]["slug"]
|
||||||
tag=INVENTORY_TAG['motherboard']['slug'])
|
)
|
||||||
|
|
||||||
for nb_motherboard in nb_motherboards:
|
for nb_motherboard in nb_motherboards:
|
||||||
if nb_motherboard.serial not in [x['serial'] for x in motherboards]:
|
if nb_motherboard.serial not in [x["serial"] for x in motherboards]:
|
||||||
logging.info('Deleting unknown motherboard {vendor} {motherboard}/{serial}'.format(
|
logging.info(
|
||||||
motherboard=self.lshw.motherboard,
|
"Deleting unknown motherboard {motherboard}/{serial}".format(
|
||||||
serial=nb_motherboard.serial,
|
motherboard=self.lshw.motherboard,
|
||||||
))
|
serial=nb_motherboard.serial,
|
||||||
|
)
|
||||||
|
)
|
||||||
nb_motherboard.delete()
|
nb_motherboard.delete()
|
||||||
|
|
||||||
# create interfaces that are not in netbox
|
# create interfaces that are not in netbox
|
||||||
for motherboard in motherboards:
|
for motherboard in motherboards:
|
||||||
if motherboard.get('serial') not in [x.serial for x in nb_motherboards]:
|
if motherboard.get("serial") not in [x.serial for x in nb_motherboards]:
|
||||||
self.create_netbox_inventory_item(
|
self.create_netbox_inventory_item(
|
||||||
device_id=self.device_id,
|
device_id=self.device_id,
|
||||||
tags=[INVENTORY_TAG['motherboard']['name']],
|
tags=[{"name": INVENTORY_TAG["motherboard"]["name"]}],
|
||||||
vendor='{}'.format(motherboard.get('vendor', 'N/A')),
|
vendor="{}".format(motherboard.get("vendor", "N/A")),
|
||||||
serial='{}'.format(motherboard.get('serial', 'No SN')),
|
serial="{}".format(motherboard.get("serial", "No SN")),
|
||||||
name='{}'.format(motherboard.get('name')),
|
name="{}".format(motherboard.get("name")),
|
||||||
description='{}'.format(motherboard.get('description'))
|
description="{}".format(motherboard.get("description")),
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_netbox_interface(self, iface):
|
def create_netbox_interface(self, iface):
|
||||||
|
@ -160,84 +170,93 @@ class Inventory():
|
||||||
device=self.device_id,
|
device=self.device_id,
|
||||||
manufacturer=manufacturer.id,
|
manufacturer=manufacturer.id,
|
||||||
discovered=True,
|
discovered=True,
|
||||||
tags=[INVENTORY_TAG['interface']['name']],
|
tags=[{"name": INVENTORY_TAG["interface"]["name"]}],
|
||||||
name="{}".format(iface['product']),
|
name="{}".format(iface["product"]),
|
||||||
serial='{}'.format(iface['serial']),
|
serial="{}".format(iface["serial"]),
|
||||||
description='{} {}'.format(iface['description'], iface['name'])
|
description="{} {}".format(iface["description"], iface["name"]),
|
||||||
)
|
)
|
||||||
|
|
||||||
def do_netbox_interfaces(self):
|
def do_netbox_interfaces(self):
|
||||||
nb_interfaces = self.get_netbox_inventory(
|
nb_interfaces = self.get_netbox_inventory(
|
||||||
device_id=self.device_id,
|
device_id=self.device_id, tag=INVENTORY_TAG["interface"]["slug"]
|
||||||
tag=INVENTORY_TAG['interface']['slug'])
|
)
|
||||||
interfaces = self.lshw.interfaces
|
interfaces = self.lshw.interfaces
|
||||||
|
|
||||||
# delete interfaces that are in netbox but not locally
|
# delete interfaces that are in netbox but not locally
|
||||||
# use the serial_number has the comparison element
|
# use the serial_number has the comparison element
|
||||||
for nb_interface in nb_interfaces:
|
for nb_interface in nb_interfaces:
|
||||||
if nb_interface.serial not in [x['serial'] for x in interfaces]:
|
if nb_interface.serial not in [x["serial"] for x in interfaces]:
|
||||||
logging.info('Deleting unknown interface {serial}'.format(
|
logging.info(
|
||||||
serial=nb_interface.serial,
|
"Deleting unknown interface {serial}".format(
|
||||||
))
|
serial=nb_interface.serial,
|
||||||
|
)
|
||||||
|
)
|
||||||
nb_interface.delete()
|
nb_interface.delete()
|
||||||
|
|
||||||
# create interfaces that are not in netbox
|
# create interfaces that are not in netbox
|
||||||
for iface in interfaces:
|
for iface in interfaces:
|
||||||
if iface.get('serial') not in [x.serial for x in nb_interfaces]:
|
if iface.get("serial") not in [x.serial for x in nb_interfaces]:
|
||||||
self.create_netbox_interface(iface)
|
self.create_netbox_interface(iface)
|
||||||
|
|
||||||
def create_netbox_cpus(self):
|
def create_netbox_cpus(self):
|
||||||
for cpu in self.lshw.get_hw_linux('cpu'):
|
for cpu in self.lshw.get_hw_linux("cpu"):
|
||||||
manufacturer = self.find_or_create_manufacturer(cpu["vendor"])
|
manufacturer = self.find_or_create_manufacturer(cpu["vendor"])
|
||||||
_ = nb.dcim.inventory_items.create(
|
_ = nb.dcim.inventory_items.create(
|
||||||
device=self.device_id,
|
device=self.device_id,
|
||||||
manufacturer=manufacturer.id,
|
manufacturer=manufacturer.id,
|
||||||
discovered=True,
|
discovered=True,
|
||||||
tags=[INVENTORY_TAG['cpu']['name']],
|
tags=[{"name": INVENTORY_TAG["cpu"]["name"]}],
|
||||||
name=cpu['product'],
|
name=cpu["product"],
|
||||||
description='CPU {}'.format(cpu['location']),
|
description="CPU {}".format(cpu["location"]),
|
||||||
# asset_tag=cpu['location']
|
# asset_tag=cpu['location']
|
||||||
)
|
)
|
||||||
|
|
||||||
logging.info('Creating CPU model {}'.format(cpu['product']))
|
logging.info("Creating CPU model {}".format(cpu["product"]))
|
||||||
|
|
||||||
def do_netbox_cpus(self):
|
def do_netbox_cpus(self):
|
||||||
cpus = self.lshw.get_hw_linux('cpu')
|
cpus = self.lshw.get_hw_linux("cpu")
|
||||||
nb_cpus = self.get_netbox_inventory(
|
nb_cpus = self.get_netbox_inventory(
|
||||||
device_id=self.device_id,
|
device_id=self.device_id,
|
||||||
tag=INVENTORY_TAG['cpu']['slug'],
|
tag=INVENTORY_TAG["cpu"]["slug"],
|
||||||
)
|
)
|
||||||
|
|
||||||
if not len(nb_cpus) or \
|
if not len(nb_cpus) or len(nb_cpus) and len(cpus) != len(nb_cpus):
|
||||||
len(nb_cpus) and len(cpus) != len(nb_cpus):
|
|
||||||
for x in nb_cpus:
|
for x in nb_cpus:
|
||||||
x.delete()
|
x.delete()
|
||||||
|
|
||||||
self.create_netbox_cpus()
|
self.create_netbox_cpus()
|
||||||
|
|
||||||
def get_raid_cards(self):
|
def get_raid_cards(self, filter_cards=False):
|
||||||
raid_class = None
|
raid_class = None
|
||||||
if self.server.manufacturer == 'Dell':
|
if self.server.manufacturer in ("Dell", "Huawei"):
|
||||||
if is_tool('omreport'):
|
if is_tool("omreport"):
|
||||||
raid_class = OmreportRaid
|
raid_class = OmreportRaid
|
||||||
if is_tool('storcli'):
|
if is_tool("storcli"):
|
||||||
raid_class = StorcliRaid
|
raid_class = StorcliRaid
|
||||||
elif self.server.manufacturer == 'HP':
|
elif self.server.manufacturer in ("HP", "HPE"):
|
||||||
if is_tool('ssacli'):
|
if is_tool("ssacli"):
|
||||||
raid_class = HPRaid
|
raid_class = HPRaid
|
||||||
|
|
||||||
if not raid_class:
|
if not raid_class:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.raid = raid_class()
|
self.raid = raid_class()
|
||||||
controllers = self.raid.get_controllers()
|
|
||||||
if len(self.raid.get_controllers()):
|
if (
|
||||||
return controllers
|
filter_cards
|
||||||
|
and config.expansion_as_device
|
||||||
|
and self.server.own_expansion_slot()
|
||||||
|
):
|
||||||
|
return [
|
||||||
|
c
|
||||||
|
for c in self.raid.get_controllers()
|
||||||
|
if c.is_external() is self.update_expansion
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
return self.raid.get_controllers()
|
||||||
|
|
||||||
def create_netbox_raid_card(self, raid_card):
|
def create_netbox_raid_card(self, raid_card):
|
||||||
manufacturer = self.find_or_create_manufacturer(
|
manufacturer = self.find_or_create_manufacturer(raid_card.get_manufacturer())
|
||||||
raid_card.get_manufacturer()
|
|
||||||
)
|
|
||||||
|
|
||||||
name = raid_card.get_product_name()
|
name = raid_card.get_product_name()
|
||||||
serial = raid_card.get_serial_number()
|
serial = raid_card.get_serial_number()
|
||||||
|
@ -245,15 +264,17 @@ class Inventory():
|
||||||
device=self.device_id,
|
device=self.device_id,
|
||||||
discovered=True,
|
discovered=True,
|
||||||
manufacturer=manufacturer.id if manufacturer else None,
|
manufacturer=manufacturer.id if manufacturer else None,
|
||||||
tags=[INVENTORY_TAG['raid_card']['name']],
|
tags=[{"name": INVENTORY_TAG["raid_card"]["name"]}],
|
||||||
name='{}'.format(name),
|
name="{}".format(name),
|
||||||
serial='{}'.format(serial),
|
serial="{}".format(serial),
|
||||||
description='RAID Card',
|
description="RAID Card",
|
||||||
|
)
|
||||||
|
logging.info(
|
||||||
|
"Creating RAID Card {name} (SN: {serial})".format(
|
||||||
|
name=name,
|
||||||
|
serial=serial,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
logging.info('Creating RAID Card {name} (SN: {serial})'.format(
|
|
||||||
name=name,
|
|
||||||
serial=serial,
|
|
||||||
))
|
|
||||||
return nb_raid_card
|
return nb_raid_card
|
||||||
|
|
||||||
def do_netbox_raid_cards(self):
|
def do_netbox_raid_cards(self):
|
||||||
|
@ -268,18 +289,19 @@ class Inventory():
|
||||||
"""
|
"""
|
||||||
|
|
||||||
nb_raid_cards = self.get_netbox_inventory(
|
nb_raid_cards = self.get_netbox_inventory(
|
||||||
device_id=self.device_id,
|
device_id=self.device_id, tag=[INVENTORY_TAG["raid_card"]["slug"]]
|
||||||
tag=[INVENTORY_TAG['raid_card']['slug']]
|
)
|
||||||
)
|
raid_cards = self.get_raid_cards(filter_cards=True)
|
||||||
raid_cards = self.get_raid_cards()
|
|
||||||
|
|
||||||
# delete cards that are in netbox but not locally
|
# delete cards that are in netbox but not locally
|
||||||
# use the serial_number has the comparison element
|
# use the serial_number has the comparison element
|
||||||
for nb_raid_card in nb_raid_cards:
|
for nb_raid_card in nb_raid_cards:
|
||||||
if nb_raid_card.serial not in [x.get_serial_number() for x in raid_cards]:
|
if nb_raid_card.serial not in [x.get_serial_number() for x in raid_cards]:
|
||||||
logging.info('Deleting unknown locally RAID Card {serial}'.format(
|
logging.info(
|
||||||
serial=nb_raid_card.serial,
|
"Deleting unknown locally RAID Card {serial}".format(
|
||||||
))
|
serial=nb_raid_card.serial,
|
||||||
|
)
|
||||||
|
)
|
||||||
nb_raid_card.delete()
|
nb_raid_card.delete()
|
||||||
|
|
||||||
# create card that are not in netbox
|
# create card that are not in netbox
|
||||||
|
@ -287,56 +309,70 @@ class Inventory():
|
||||||
if raid_card.get_serial_number() not in [x.serial for x in nb_raid_cards]:
|
if raid_card.get_serial_number() not in [x.serial for x in nb_raid_cards]:
|
||||||
self.create_netbox_raid_card(raid_card)
|
self.create_netbox_raid_card(raid_card)
|
||||||
|
|
||||||
def is_virtual_disk(self, disk):
|
def is_virtual_disk(self, disk, raid_devices):
|
||||||
logicalname = disk.get('logicalname')
|
disk_type = disk.get("type")
|
||||||
description = disk.get('description')
|
logicalname = disk.get("logicalname")
|
||||||
size = disk.get('size')
|
description = disk.get("description")
|
||||||
product = disk.get('product')
|
size = disk.get("size")
|
||||||
|
product = disk.get("product")
|
||||||
|
if (
|
||||||
|
logicalname in raid_devices
|
||||||
|
or disk_type is None
|
||||||
|
or product is None
|
||||||
|
or description is None
|
||||||
|
):
|
||||||
|
return True
|
||||||
non_raid_disks = [
|
non_raid_disks = [
|
||||||
'MR9361-8i',
|
"MR9361-8i",
|
||||||
]
|
]
|
||||||
|
|
||||||
if size is None and logicalname is None or \
|
if (
|
||||||
'virtual' in product.lower() or 'logical' in product.lower() or \
|
logicalname in raid_devices
|
||||||
product in non_raid_disks or \
|
or product in non_raid_disks
|
||||||
description == 'SCSI Enclosure' or \
|
or "virtual" in product.lower()
|
||||||
'volume' in description.lower():
|
or "logical" in product.lower()
|
||||||
|
or "volume" in description.lower()
|
||||||
|
or "dvd-ram" in description.lower()
|
||||||
|
or description == "SCSI Enclosure"
|
||||||
|
or (size is None and logicalname is None)
|
||||||
|
):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_hw_disks(self):
|
def get_hw_disks(self):
|
||||||
disks = []
|
disks = []
|
||||||
|
|
||||||
|
for raid_card in self.get_raid_cards(filter_cards=True):
|
||||||
|
disks.extend(raid_card.get_physical_disks())
|
||||||
|
|
||||||
|
raid_devices = [
|
||||||
|
d.get("custom_fields", {}).get("vd_device")
|
||||||
|
for d in disks
|
||||||
|
if d.get("custom_fields", {}).get("vd_device")
|
||||||
|
]
|
||||||
|
|
||||||
for disk in self.lshw.get_hw_linux("storage"):
|
for disk in self.lshw.get_hw_linux("storage"):
|
||||||
if self.is_virtual_disk(disk):
|
if self.is_virtual_disk(disk, raid_devices):
|
||||||
continue
|
continue
|
||||||
|
size = round(int(disk.get("size", 0)) / 1073741824, 1)
|
||||||
logicalname = disk.get('logicalname')
|
d = {
|
||||||
description = disk.get('description')
|
"name": "",
|
||||||
size = disk.get('size', 0)
|
"Size": "{} GB".format(size),
|
||||||
product = disk.get('product')
|
"logicalname": disk.get("logicalname"),
|
||||||
serial = disk.get('serial')
|
"description": disk.get("description"),
|
||||||
|
"SN": disk.get("serial"),
|
||||||
d = {}
|
"Model": disk.get("product"),
|
||||||
d["name"] = ""
|
"Type": disk.get("type"),
|
||||||
d['Size'] = '{} GB'.format(int(size/1024/1024/1024))
|
}
|
||||||
d['logicalname'] = logicalname
|
if disk.get("vendor"):
|
||||||
d['description'] = description
|
d["Vendor"] = disk["vendor"]
|
||||||
d['SN'] = serial
|
|
||||||
d['Model'] = product
|
|
||||||
if disk.get('vendor'):
|
|
||||||
d['Vendor'] = disk['vendor']
|
|
||||||
else:
|
else:
|
||||||
d['Vendor'] = get_vendor(disk['product'])
|
d["Vendor"] = get_vendor(disk["product"])
|
||||||
disks.append(d)
|
disks.append(d)
|
||||||
|
|
||||||
for raid_card in self.get_raid_cards():
|
|
||||||
disks += raid_card.get_physical_disks()
|
|
||||||
|
|
||||||
# remove duplicate serials
|
# remove duplicate serials
|
||||||
seen = set()
|
seen = set()
|
||||||
uniq = [x for x in disks if x['SN'] not in seen and not seen.add(x['SN'])]
|
uniq = [x for x in disks if x["SN"] not in seen and not seen.add(x["SN"])]
|
||||||
return uniq
|
return uniq
|
||||||
|
|
||||||
def create_netbox_disk(self, disk):
|
def create_netbox_disk(self, disk):
|
||||||
|
@ -344,115 +380,184 @@ class Inventory():
|
||||||
if "Vendor" in disk:
|
if "Vendor" in disk:
|
||||||
manufacturer = self.find_or_create_manufacturer(disk["Vendor"])
|
manufacturer = self.find_or_create_manufacturer(disk["Vendor"])
|
||||||
|
|
||||||
logicalname = disk.get('logicalname')
|
name = "{} ({})".format(disk["Model"], disk["Size"])
|
||||||
desc = disk.get('description')
|
description = disk["Type"]
|
||||||
# nonraid disk
|
sn = disk.get("SN", "unknown")
|
||||||
if logicalname and desc:
|
|
||||||
if type(logicalname) is list:
|
|
||||||
logicalname = logicalname[0]
|
|
||||||
name = '{} - {} ({})'.format(
|
|
||||||
desc,
|
|
||||||
logicalname,
|
|
||||||
disk.get('Size', 0))
|
|
||||||
description = 'Device {}'.format(disk.get('logicalname', 'Unknown'))
|
|
||||||
else:
|
|
||||||
name = '{} ({})'.format(disk['Model'], disk['Size'])
|
|
||||||
description = '{}'.format(disk['Type'])
|
|
||||||
|
|
||||||
_ = nb.dcim.inventory_items.create(
|
parms = {
|
||||||
device=self.device_id,
|
"device": self.device_id,
|
||||||
discovered=True,
|
"discovered": True,
|
||||||
tags=[INVENTORY_TAG['disk']['name']],
|
"tags": [{"name": INVENTORY_TAG["disk"]["name"]}],
|
||||||
name=name,
|
"name": name,
|
||||||
serial=disk['SN'],
|
"serial": sn,
|
||||||
part_id=disk['Model'],
|
"part_id": disk["Model"],
|
||||||
description=description,
|
"description": description,
|
||||||
manufacturer=manufacturer.id if manufacturer else None
|
"manufacturer": getattr(manufacturer, "id", None),
|
||||||
|
}
|
||||||
|
if config.process_virtual_drives:
|
||||||
|
parms["custom_fields"] = disk.get("custom_fields", {})
|
||||||
|
|
||||||
|
_ = nb.dcim.inventory_items.create(**parms)
|
||||||
|
|
||||||
|
logging.info(
|
||||||
|
"Creating Disk {model} {serial}".format(
|
||||||
|
model=disk["Model"],
|
||||||
|
serial=sn,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
logging.info('Creating Disk {model} {serial}'.format(
|
def dump_disks_map(self, disks):
|
||||||
model=disk['Model'],
|
disk_map = [d["custom_fields"] for d in disks if "custom_fields" in d]
|
||||||
serial=disk['SN'],
|
if config.dump_disks_map == "-":
|
||||||
))
|
f = sys.stdout
|
||||||
|
else:
|
||||||
|
f = open(config.dump_disks_map, "w")
|
||||||
|
f.write(json.dumps(disk_map, separators=(",", ":"), indent=4, sort_keys=True))
|
||||||
|
if config.dump_disks_map != "-":
|
||||||
|
f.close()
|
||||||
|
|
||||||
def do_netbox_disks(self):
|
def do_netbox_disks(self):
|
||||||
nb_disks = self.get_netbox_inventory(
|
nb_disks = self.get_netbox_inventory(
|
||||||
device_id=self.device_id,
|
device_id=self.device_id, tag=INVENTORY_TAG["disk"]["slug"]
|
||||||
tag=INVENTORY_TAG['disk']['slug'])
|
)
|
||||||
disks = self.get_hw_disks()
|
disks = self.get_hw_disks()
|
||||||
|
if config.dump_disks_map:
|
||||||
|
try:
|
||||||
|
self.dump_disks_map(disks)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error("Failed to dump disks map: {}".format(e))
|
||||||
|
logging.debug(traceback.format_exc())
|
||||||
|
disk_serials = [d["SN"] for d in disks if "SN" in d]
|
||||||
|
|
||||||
# delete disks that are in netbox but not locally
|
# delete disks that are in netbox but not locally
|
||||||
# use the serial_number has the comparison element
|
# use the serial_number has the comparison element
|
||||||
for nb_disk in nb_disks:
|
for nb_disk in nb_disks:
|
||||||
if nb_disk.serial not in [x['SN'] for x in disks if x.get('SN')]:
|
if nb_disk.serial not in disk_serials or config.force_disk_refresh:
|
||||||
logging.info('Deleting unknown locally Disk {serial}'.format(
|
logging.info(
|
||||||
serial=nb_disk.serial,
|
"Deleting unknown locally Disk {serial}".format(
|
||||||
))
|
serial=nb_disk.serial,
|
||||||
|
)
|
||||||
|
)
|
||||||
nb_disk.delete()
|
nb_disk.delete()
|
||||||
|
|
||||||
|
if config.force_disk_refresh:
|
||||||
|
nb_disks = self.get_netbox_inventory(
|
||||||
|
device_id=self.device_id, tag=INVENTORY_TAG["disk"]["slug"]
|
||||||
|
)
|
||||||
|
|
||||||
# create disks that are not in netbox
|
# create disks that are not in netbox
|
||||||
for disk in disks:
|
for disk in disks:
|
||||||
if disk.get('SN') not in [x.serial for x in nb_disks]:
|
if disk.get("SN") not in [d.serial for d in nb_disks]:
|
||||||
self.create_netbox_disk(disk)
|
self.create_netbox_disk(disk)
|
||||||
|
|
||||||
def create_netbox_memory(self, memory):
|
def create_netbox_memory(self, memory):
|
||||||
manufacturer = self.find_or_create_manufacturer(memory['vendor'])
|
manufacturer = self.find_or_create_manufacturer(memory["vendor"])
|
||||||
name = 'Slot {} ({}GB)'.format(memory['slot'], memory['size'])
|
name = "Slot {} ({}GB)".format(memory["slot"], memory["size"])
|
||||||
nb_memory = nb.dcim.inventory_items.create(
|
nb_memory = nb.dcim.inventory_items.create(
|
||||||
device=self.device_id,
|
device=self.device_id,
|
||||||
discovered=True,
|
discovered=True,
|
||||||
manufacturer=manufacturer.id,
|
manufacturer=manufacturer.id,
|
||||||
tags=[INVENTORY_TAG['memory']['name']],
|
tags=[{"name": INVENTORY_TAG["memory"]["name"]}],
|
||||||
name=name,
|
name=name,
|
||||||
part_id=memory['product'],
|
part_id=memory["product"],
|
||||||
serial=memory['serial'],
|
serial=memory["serial"],
|
||||||
description=memory['description'],
|
description=memory["description"],
|
||||||
)
|
)
|
||||||
|
|
||||||
logging.info('Creating Memory {location} {type} {size}GB'.format(
|
logging.info(
|
||||||
location=memory['slot'],
|
"Creating Memory {location} {type} {size}GB".format(
|
||||||
type=memory['product'],
|
location=memory["slot"],
|
||||||
size=memory['size'],
|
type=memory["product"],
|
||||||
))
|
size=memory["size"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return nb_memory
|
return nb_memory
|
||||||
|
|
||||||
def do_netbox_memories(self):
|
def do_netbox_memories(self):
|
||||||
memories = self.lshw.memories
|
memories = self.lshw.memories
|
||||||
nb_memories = self.get_netbox_inventory(
|
nb_memories = self.get_netbox_inventory(
|
||||||
device_id=self.device_id,
|
device_id=self.device_id, tag=INVENTORY_TAG["memory"]["slug"]
|
||||||
tag=INVENTORY_TAG['memory']['slug']
|
)
|
||||||
)
|
|
||||||
|
|
||||||
for nb_memory in nb_memories:
|
for nb_memory in nb_memories:
|
||||||
if nb_memory.serial not in [x['serial'] for x in memories]:
|
if nb_memory.serial not in [x["serial"] for x in memories]:
|
||||||
logging.info('Deleting unknown locally Memory {serial}'.format(
|
logging.info(
|
||||||
serial=nb_memory.serial,
|
"Deleting unknown locally Memory {serial}".format(
|
||||||
))
|
serial=nb_memory.serial,
|
||||||
|
)
|
||||||
|
)
|
||||||
nb_memory.delete()
|
nb_memory.delete()
|
||||||
|
|
||||||
for memory in memories:
|
for memory in memories:
|
||||||
if memory.get('serial') not in [x.serial for x in nb_memories]:
|
if memory.get("serial") not in [x.serial for x in nb_memories]:
|
||||||
self.create_netbox_memory(memory)
|
self.create_netbox_memory(memory)
|
||||||
|
|
||||||
def create(self):
|
def create_netbox_gpus(self, gpus):
|
||||||
if config.inventory is None:
|
for gpu in gpus:
|
||||||
return False
|
if "product" in gpu and len(gpu["product"]) > 50:
|
||||||
self.do_netbox_cpus()
|
gpu["product"] = gpu["product"][:48] + ".."
|
||||||
self.do_netbox_memories()
|
|
||||||
self.do_netbox_raid_cards()
|
|
||||||
self.do_netbox_disks()
|
|
||||||
self.do_netbox_interfaces()
|
|
||||||
self.do_netbox_motherboard()
|
|
||||||
return True
|
|
||||||
|
|
||||||
def update(self):
|
manufacturer = self.find_or_create_manufacturer(gpu["vendor"])
|
||||||
|
_ = nb.dcim.inventory_items.create(
|
||||||
|
device=self.device_id,
|
||||||
|
manufacturer=manufacturer.id,
|
||||||
|
discovered=True,
|
||||||
|
tags=[{"name": INVENTORY_TAG["gpu"]["name"]}],
|
||||||
|
name=gpu["product"],
|
||||||
|
description=gpu["description"],
|
||||||
|
)
|
||||||
|
|
||||||
|
logging.info("Creating GPU model {}".format(gpu["product"]))
|
||||||
|
|
||||||
|
def is_external_gpu(self, gpu):
|
||||||
|
is_3d_gpu = gpu["description"].startswith("3D")
|
||||||
|
return (
|
||||||
|
self.server.is_blade()
|
||||||
|
and self.server.own_gpu_expansion_slot()
|
||||||
|
and is_3d_gpu
|
||||||
|
)
|
||||||
|
|
||||||
|
def do_netbox_gpus(self):
|
||||||
|
gpus = []
|
||||||
|
gpu_models = {}
|
||||||
|
for gpu in self.lshw.get_hw_linux("gpu"):
|
||||||
|
# Filters GPU if an expansion bay is detected:
|
||||||
|
# The internal (VGA) GPU only goes into the blade inventory,
|
||||||
|
# the external (3D) GPU goes into the expansion blade.
|
||||||
|
if (
|
||||||
|
config.expansion_as_device
|
||||||
|
and self.update_expansion ^ self.is_external_gpu(gpu)
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
gpus.append(gpu)
|
||||||
|
gpu_models.setdefault(gpu["product"], 0)
|
||||||
|
gpu_models[gpu["product"]] += 1
|
||||||
|
|
||||||
|
nb_gpus = self.get_netbox_inventory(
|
||||||
|
device_id=self.device_id,
|
||||||
|
tag=INVENTORY_TAG["gpu"]["slug"],
|
||||||
|
)
|
||||||
|
nb_gpu_models = {}
|
||||||
|
for gpu in nb_gpus:
|
||||||
|
nb_gpu_models.setdefault(str(gpu), 0)
|
||||||
|
nb_gpu_models[str(gpu)] += 1
|
||||||
|
up_to_date = set(gpu_models) == set(nb_gpu_models)
|
||||||
|
if not gpus or not up_to_date:
|
||||||
|
for x in nb_gpus:
|
||||||
|
x.delete()
|
||||||
|
if gpus and not up_to_date:
|
||||||
|
self.create_netbox_gpus(gpus)
|
||||||
|
|
||||||
|
def create_or_update(self):
|
||||||
if config.inventory is None or config.update_inventory is None:
|
if config.inventory is None or config.update_inventory is None:
|
||||||
return False
|
return False
|
||||||
self.do_netbox_cpus()
|
if self.update_expansion is False:
|
||||||
self.do_netbox_memories()
|
self.do_netbox_cpus()
|
||||||
self.do_netbox_raid_cards()
|
self.do_netbox_memories()
|
||||||
|
self.do_netbox_interfaces()
|
||||||
|
self.do_netbox_motherboard()
|
||||||
|
self.do_netbox_gpus()
|
||||||
self.do_netbox_disks()
|
self.do_netbox_disks()
|
||||||
self.do_netbox_interfaces()
|
self.do_netbox_raid_cards()
|
||||||
self.do_netbox_motherboard()
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import logging
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
from netaddr import IPNetwork
|
||||||
|
|
||||||
class IPMI():
|
|
||||||
|
class IPMI:
|
||||||
"""
|
"""
|
||||||
Parse IPMI output
|
Parse IPMI output
|
||||||
ie:
|
ie:
|
||||||
|
@ -33,17 +35,43 @@ class IPMI():
|
||||||
: O=OEM
|
: O=OEM
|
||||||
Bad Password Threshold : Not Available
|
Bad Password Threshold : Not Available
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.ret, self.output = subprocess.getstatusoutput('ipmitool lan print')
|
self.ret, self.output = subprocess.getstatusoutput("ipmitool lan print")
|
||||||
if self.ret != 0:
|
if self.ret != 0:
|
||||||
logging.error('Cannot get ipmi info: {}'.format(self.output))
|
logging.error("Cannot get ipmi info: {}".format(self.output))
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
ret = {}
|
_ipmi = {}
|
||||||
if self.ret != 0:
|
if self.ret != 0:
|
||||||
return ret
|
return _ipmi
|
||||||
|
|
||||||
for line in self.output.splitlines():
|
for line in self.output.splitlines():
|
||||||
key = line.split(':')[0].strip()
|
key = line.split(":")[0].strip()
|
||||||
value = ':'.join(line.split(':')[1:]).strip()
|
if key not in [
|
||||||
ret[key] = value
|
"802.1q VLAN ID",
|
||||||
|
"IP Address",
|
||||||
|
"Subnet Mask",
|
||||||
|
"MAC Address",
|
||||||
|
]:
|
||||||
|
continue
|
||||||
|
value = ":".join(line.split(":")[1:]).strip()
|
||||||
|
_ipmi[key] = value
|
||||||
|
|
||||||
|
ret = {}
|
||||||
|
ret["name"] = "IPMI"
|
||||||
|
ret["mtu"] = 1500
|
||||||
|
ret["bonding"] = False
|
||||||
|
ret["mac"] = _ipmi["MAC Address"]
|
||||||
|
ret["vlan"] = (
|
||||||
|
int(_ipmi["802.1q VLAN ID"])
|
||||||
|
if _ipmi["802.1q VLAN ID"] != "Disabled"
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
ip = _ipmi["IP Address"]
|
||||||
|
netmask = _ipmi["Subnet Mask"]
|
||||||
|
address = str(IPNetwork("{}/{}".format(ip, netmask)))
|
||||||
|
|
||||||
|
ret["ip"] = [address]
|
||||||
|
ret["ipmi"] = True
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
from netbox_agent.misc import is_tool
|
||||||
|
|
||||||
class LLDP():
|
|
||||||
def __init__(self):
|
class LLDP:
|
||||||
self.output = subprocess.getoutput('lldpctl -f keyvalue')
|
def __init__(self, output=None):
|
||||||
|
if not is_tool("lldpctl"):
|
||||||
|
logging.debug("lldpd package seems to be missing or daemon not running.")
|
||||||
|
if output:
|
||||||
|
self.output = output
|
||||||
|
else:
|
||||||
|
self.output = subprocess.getoutput("lldpctl -f keyvalue")
|
||||||
self.data = self.parse()
|
self.data = self.parse()
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
|
@ -11,7 +19,7 @@ class LLDP():
|
||||||
vlans = {}
|
vlans = {}
|
||||||
vid = None
|
vid = None
|
||||||
for entry in self.output.splitlines():
|
for entry in self.output.splitlines():
|
||||||
if '=' not in entry:
|
if "=" not in entry:
|
||||||
continue
|
continue
|
||||||
path, value = entry.strip().split("=", 1)
|
path, value = entry.strip().split("=", 1)
|
||||||
split_path = path.split(".")
|
split_path = path.split(".")
|
||||||
|
@ -23,36 +31,41 @@ class LLDP():
|
||||||
vlans[interface] = {}
|
vlans[interface] = {}
|
||||||
|
|
||||||
for path_component in path_components:
|
for path_component in path_components:
|
||||||
current_dict[path_component] = current_dict.get(path_component, {})
|
if not isinstance(current_dict.get(path_component), dict):
|
||||||
current_dict = current_dict[path_component]
|
current_dict[path_component] = {}
|
||||||
if 'vlan-id' in path:
|
current_dict = current_dict.get(path_component)
|
||||||
|
if "vlan-id" in path:
|
||||||
vid = value
|
vid = value
|
||||||
vlans[interface][value] = vlans[interface].get(vid, {})
|
vlans[interface][value] = vlans[interface].get(vid, {})
|
||||||
elif path.endswith('vlan'):
|
elif path.endswith("vlan"):
|
||||||
vid = value.replace('vlan-', '')
|
vid = value.replace("vlan-", "")
|
||||||
vlans[interface][vid] = vlans[interface].get(vid, {})
|
vlans[interface][vid] = vlans[interface].get(vid, {})
|
||||||
elif 'pvid' in path:
|
elif "pvid" in path:
|
||||||
vlans[interface][vid]['pvid'] = True
|
vlans[interface][vid]["pvid"] = True
|
||||||
if 'vlan' not in path:
|
if "vlan" not in path:
|
||||||
current_dict[final] = value
|
current_dict[final] = value
|
||||||
for interface, vlan in vlans.items():
|
for interface, vlan in vlans.items():
|
||||||
output_dict['lldp'][interface]['vlan'] = vlan
|
output_dict["lldp"][interface]["vlan"] = vlan
|
||||||
|
if not output_dict:
|
||||||
|
logging.debug("No LLDP output, please check your network config.")
|
||||||
return output_dict
|
return output_dict
|
||||||
|
|
||||||
def get_switch_ip(self, interface):
|
def get_switch_ip(self, interface):
|
||||||
# lldp.eth0.chassis.mgmt-ip=100.66.7.222
|
# lldp.eth0.chassis.mgmt-ip=100.66.7.222
|
||||||
if self.data['lldp'].get(interface) is None:
|
if self.data["lldp"].get(interface) is None:
|
||||||
return None
|
return None
|
||||||
return self.data['lldp'][interface]['chassis']['mgmt-ip']
|
return self.data["lldp"][interface]["chassis"].get("mgmt-ip")
|
||||||
|
|
||||||
def get_switch_port(self, interface):
|
def get_switch_port(self, interface):
|
||||||
# lldp.eth0.port.descr=GigabitEthernet1/0/1
|
# lldp.eth0.port.descr=GigabitEthernet1/0/1
|
||||||
if self.data['lldp'].get(interface) is None:
|
if self.data["lldp"].get(interface) is None:
|
||||||
return None
|
return None
|
||||||
return self.data['lldp'][interface]['port']['descr']
|
if self.data["lldp"][interface]["port"].get("ifname"):
|
||||||
|
return self.data["lldp"][interface]["port"]["ifname"]
|
||||||
|
return self.data["lldp"][interface]["port"]["descr"]
|
||||||
|
|
||||||
def get_switch_vlan(self, interface):
|
def get_switch_vlan(self, interface):
|
||||||
# lldp.eth0.vlan.vlan-id=296
|
# lldp.eth0.vlan.vlan-id=296
|
||||||
if self.data['lldp'].get(interface) is None:
|
if self.data["lldp"].get(interface) is None:
|
||||||
return None
|
return None
|
||||||
return self.data['lldp'][interface]['vlan']
|
return self.data["lldp"][interface]["vlan"]
|
||||||
|
|
|
@ -4,7 +4,7 @@ import importlib.machinery
|
||||||
from netbox_agent.config import config
|
from netbox_agent.config import config
|
||||||
|
|
||||||
|
|
||||||
class LocationBase():
|
class LocationBase:
|
||||||
"""
|
"""
|
||||||
This class is used to guess the location in order to push the information
|
This class is used to guess the location in order to push the information
|
||||||
in Netbox for a `Device`
|
in Netbox for a `Device`
|
||||||
|
@ -17,6 +17,7 @@ class LocationBase():
|
||||||
There's also a support for an external driver file outside of this project in case
|
There's also a support for an external driver file outside of this project in case
|
||||||
the logic isn't supported here.
|
the logic isn't supported here.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, driver, driver_value, driver_file, regex, *args, **kwargs):
|
def __init__(self, driver, driver_value, driver_file, regex, *args, **kwargs):
|
||||||
self.driver = driver
|
self.driver = driver
|
||||||
self.driver_value = driver_value
|
self.driver_value = driver_value
|
||||||
|
@ -26,15 +27,19 @@ class LocationBase():
|
||||||
if self.driver_file:
|
if self.driver_file:
|
||||||
try:
|
try:
|
||||||
# FIXME: Works with Python 3.3+, support older version?
|
# FIXME: Works with Python 3.3+, support older version?
|
||||||
loader = importlib.machinery.SourceFileLoader('driver_file', self.driver_file)
|
loader = importlib.machinery.SourceFileLoader(
|
||||||
|
"driver_file", self.driver_file
|
||||||
|
)
|
||||||
self.driver = loader.load_module()
|
self.driver = loader.load_module()
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError("Couldn't import {} as a module".format(self.driver_file))
|
raise ImportError(
|
||||||
|
"Couldn't import {} as a module".format(self.driver_file)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if self.driver:
|
if self.driver:
|
||||||
try:
|
try:
|
||||||
self.driver = importlib.import_module(
|
self.driver = importlib.import_module(
|
||||||
'netbox_agent.drivers.{}'.format(self.driver)
|
"netbox_agent.drivers.{}".format(self.driver)
|
||||||
)
|
)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError("Driver {} doesn't exists".format(self.driver))
|
raise ImportError("Driver {} doesn't exists".format(self.driver))
|
||||||
|
@ -42,19 +47,40 @@ class LocationBase():
|
||||||
def get(self):
|
def get(self):
|
||||||
if self.driver is None:
|
if self.driver is None:
|
||||||
return None
|
return None
|
||||||
if not hasattr(self.driver, 'get'):
|
if not hasattr(self.driver, "get"):
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"Your driver {} doesn't have a get() function, please fix it".format(self.driver)
|
"Your driver {} doesn't have a get() function, please fix it".format(
|
||||||
|
self.driver
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return getattr(self.driver, 'get')(self.driver_value, self.regex)
|
return getattr(self.driver, "get")(self.driver_value, self.regex)
|
||||||
|
|
||||||
|
|
||||||
|
class Tenant(LocationBase):
|
||||||
|
def __init__(self):
|
||||||
|
driver = config.tenant.driver.split(":")[0] if config.tenant.driver else None
|
||||||
|
driver_value = (
|
||||||
|
":".join(config.tenant.driver.split(":")[1:])
|
||||||
|
if config.tenant.driver
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
driver_file = config.tenant.driver_file
|
||||||
|
regex = config.tenant.regex
|
||||||
|
super().__init__(driver, driver_value, driver_file, regex)
|
||||||
|
|
||||||
|
|
||||||
class Datacenter(LocationBase):
|
class Datacenter(LocationBase):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
driver = config.datacenter_location.driver.split(':')[0] if \
|
driver = (
|
||||||
config.datacenter_location.driver else None
|
config.datacenter_location.driver.split(":")[0]
|
||||||
driver_value = ':'.join(config.datacenter_location.driver.split(':')[1:]) if \
|
if config.datacenter_location.driver
|
||||||
config.datacenter_location.driver else None
|
else None
|
||||||
|
)
|
||||||
|
driver_value = (
|
||||||
|
":".join(config.datacenter_location.driver.split(":")[1:])
|
||||||
|
if config.datacenter_location.driver
|
||||||
|
else None
|
||||||
|
)
|
||||||
driver_file = config.datacenter_location.driver_file
|
driver_file = config.datacenter_location.driver_file
|
||||||
regex = config.datacenter_location.regex
|
regex = config.datacenter_location.regex
|
||||||
super().__init__(driver, driver_value, driver_file, regex)
|
super().__init__(driver, driver_value, driver_file, regex)
|
||||||
|
@ -62,10 +88,16 @@ class Datacenter(LocationBase):
|
||||||
|
|
||||||
class Rack(LocationBase):
|
class Rack(LocationBase):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
driver = config.rack_location.driver.split(':')[0] if \
|
driver = (
|
||||||
config.rack_location.driver else None
|
config.rack_location.driver.split(":")[0]
|
||||||
driver_value = ':'.join(config.rack_location.driver.split(':')[1:]) if \
|
if config.rack_location.driver
|
||||||
config.rack_location.driver else None
|
else None
|
||||||
|
)
|
||||||
|
driver_value = (
|
||||||
|
":".join(config.rack_location.driver.split(":")[1:])
|
||||||
|
if config.rack_location.driver
|
||||||
|
else None
|
||||||
|
)
|
||||||
driver_file = config.rack_location.driver_file
|
driver_file = config.rack_location.driver_file
|
||||||
regex = config.rack_location.regex
|
regex = config.rack_location.regex
|
||||||
super().__init__(driver, driver_value, driver_file, regex)
|
super().__init__(driver, driver_value, driver_file, regex)
|
||||||
|
@ -73,10 +105,16 @@ class Rack(LocationBase):
|
||||||
|
|
||||||
class Slot(LocationBase):
|
class Slot(LocationBase):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
driver = config.slot_location.driver.split(':')[0] if \
|
driver = (
|
||||||
config.slot_location.driver else None
|
config.slot_location.driver.split(":")[0]
|
||||||
driver_value = ':'.join(config.slot_location.driver.split(':')[1:]) if \
|
if config.slot_location.driver
|
||||||
config.slot_location.driver else None
|
else None
|
||||||
|
)
|
||||||
|
driver_value = (
|
||||||
|
":".join(config.slot_location.driver.split(":")[1:])
|
||||||
|
if config.slot_location.driver
|
||||||
|
else None
|
||||||
|
)
|
||||||
driver_file = config.slot_location.driver_file
|
driver_file = config.slot_location.driver_file
|
||||||
regex = config.slot_location.regex
|
regex = config.slot_location.regex
|
||||||
super().__init__(driver, driver_value, driver_file, regex)
|
super().__init__(driver, driver_value, driver_file, regex)
|
||||||
|
|
|
@ -2,10 +2,8 @@ import logging
|
||||||
|
|
||||||
from netbox_agent.config import config
|
from netbox_agent.config import config
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
if config.log_level.lower() == "debug":
|
||||||
if config.log_level == 'debug':
|
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
else:
|
else:
|
||||||
logger.setLevel(logging.INFO)
|
logger.setLevel(logging.INFO)
|
||||||
|
|
|
@ -1,27 +1,32 @@
|
||||||
import subprocess
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from netbox_agent.misc import is_tool
|
from netbox_agent.misc import is_tool
|
||||||
|
|
||||||
|
|
||||||
class LSHW():
|
class LSHW:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
if not is_tool('lshw'):
|
if not is_tool("lshw"):
|
||||||
logging.error('lshw does not seem to be installed')
|
logging.error("lshw does not seem to be installed")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
data = subprocess.getoutput(
|
data = subprocess.getoutput("lshw -quiet -json")
|
||||||
'lshw -quiet -json'
|
json_data = json.loads(data)
|
||||||
)
|
# Starting from version 02.18, `lshw -json` wraps its result in a list
|
||||||
self.hw_info = json.loads(data)
|
# rather than returning directly a dictionary
|
||||||
|
if isinstance(json_data, list):
|
||||||
|
self.hw_info = json_data[0]
|
||||||
|
else:
|
||||||
|
self.hw_info = json_data
|
||||||
self.info = {}
|
self.info = {}
|
||||||
self.memories = []
|
self.memories = []
|
||||||
self.interfaces = []
|
self.interfaces = []
|
||||||
self.cpus = []
|
self.cpus = []
|
||||||
self.power = []
|
self.power = []
|
||||||
self.disks = []
|
self.disks = []
|
||||||
|
self.gpus = []
|
||||||
self.vendor = self.hw_info["vendor"]
|
self.vendor = self.hw_info["vendor"]
|
||||||
self.product = self.hw_info["product"]
|
self.product = self.hw_info["product"]
|
||||||
self.chassis_serial = self.hw_info["serial"]
|
self.chassis_serial = self.hw_info["serial"]
|
||||||
|
@ -53,63 +58,93 @@ class LSHW():
|
||||||
def get_hw_linux(self, hwclass):
|
def get_hw_linux(self, hwclass):
|
||||||
if hwclass == "cpu":
|
if hwclass == "cpu":
|
||||||
return self.cpus
|
return self.cpus
|
||||||
|
if hwclass == "gpu":
|
||||||
|
return self.gpus
|
||||||
if hwclass == "network":
|
if hwclass == "network":
|
||||||
return self.interfaces
|
return self.interfaces
|
||||||
if hwclass == 'storage':
|
if hwclass == "storage":
|
||||||
return self.disks
|
return self.disks
|
||||||
if hwclass == 'memory':
|
if hwclass == "memory":
|
||||||
return self.memories
|
return self.memories
|
||||||
|
|
||||||
def find_network(self, obj):
|
def find_network(self, obj):
|
||||||
d = {}
|
# Some interfaces do not have device (logical) name (eth0, for
|
||||||
d["name"] = obj["logicalname"]
|
# instance), such as not connected network mezzanine cards in blade
|
||||||
d["macaddress"] = obj["serial"]
|
# servers. In such situations, the card will be named `unknown[0-9]`.
|
||||||
d["serial"] = obj["serial"]
|
unkn_intfs = []
|
||||||
d["product"] = obj["product"]
|
for i in self.interfaces:
|
||||||
d["vendor"] = obj["vendor"]
|
# newer versions of lshw can return a list of names, see issue #227
|
||||||
d["description"] = obj["description"]
|
if not isinstance(i["name"], list):
|
||||||
|
if i["name"].startswith("unknown"):
|
||||||
|
unkn_intfs.append(i)
|
||||||
|
else:
|
||||||
|
for j in i["name"]:
|
||||||
|
if j.startswith("unknown"):
|
||||||
|
unkn_intfs.append(j)
|
||||||
|
|
||||||
self.interfaces.append(d)
|
unkn_name = "unknown{}".format(len(unkn_intfs))
|
||||||
|
self.interfaces.append(
|
||||||
|
{
|
||||||
|
"name": obj.get("logicalname", unkn_name),
|
||||||
|
"macaddress": obj.get("serial", ""),
|
||||||
|
"serial": obj.get("serial", ""),
|
||||||
|
"product": obj.get("product", "Unknown NIC"),
|
||||||
|
"vendor": obj.get("vendor", "Unknown"),
|
||||||
|
"description": obj.get("description", ""),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def find_storage(self, obj):
|
def find_storage(self, obj):
|
||||||
if "children" in obj:
|
if "children" in obj:
|
||||||
for device in obj["children"]:
|
for device in obj["children"]:
|
||||||
d = {}
|
self.disks.append(
|
||||||
d["logicalname"] = device.get("logicalname")
|
{
|
||||||
d["product"] = device.get("product")
|
"logicalname": device.get("logicalname"),
|
||||||
d["serial"] = device.get("serial")
|
"product": device.get("product"),
|
||||||
d["version"] = device.get("version")
|
"serial": device.get("serial"),
|
||||||
d["size"] = device.get("size")
|
"version": device.get("version"),
|
||||||
d["description"] = device.get("description")
|
"size": device.get("size"),
|
||||||
|
"description": device.get("description"),
|
||||||
self.disks.append(d)
|
"type": device.get("description"),
|
||||||
|
}
|
||||||
|
)
|
||||||
elif "nvme" in obj["configuration"]["driver"]:
|
elif "nvme" in obj["configuration"]["driver"]:
|
||||||
nvme = json.loads(
|
if not is_tool("nvme"):
|
||||||
subprocess.check_output(["nvme", '-list', '-o', 'json'],
|
logging.error("nvme-cli >= 1.0 does not seem to be installed")
|
||||||
encoding='utf8')) # noqa: E128
|
return
|
||||||
|
try:
|
||||||
d = {}
|
nvme = json.loads(
|
||||||
d["vendor"] = obj["vendor"]
|
subprocess.check_output(
|
||||||
d["version"] = obj["version"]
|
["nvme", "-list", "-o", "json"], encoding="utf8"
|
||||||
d["product"] = obj["product"]
|
)
|
||||||
|
)
|
||||||
d['description'] = "NVME Disk"
|
for device in nvme["Devices"]:
|
||||||
d['product'] = nvme["Devices"][0]["ModelNumber"]
|
d = {
|
||||||
d['size'] = nvme["Devices"][0]["PhysicalSize"]
|
"logicalname": device["DevicePath"],
|
||||||
d['serial'] = nvme["Devices"][0]["SerialNumber"]
|
"product": device["ModelNumber"],
|
||||||
d['logicalname'] = nvme["Devices"][0]["DevicePath"]
|
"serial": device["SerialNumber"],
|
||||||
|
"version": device["Firmware"],
|
||||||
self.disks.append(d)
|
"description": "NVME",
|
||||||
|
"type": "NVME",
|
||||||
|
}
|
||||||
|
if "UsedSize" in device:
|
||||||
|
d["size"] = device["UsedSize"]
|
||||||
|
if "UsedBytes" in device:
|
||||||
|
d["size"] = device["UsedBytes"]
|
||||||
|
self.disks.append(d)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
def find_cpus(self, obj):
|
def find_cpus(self, obj):
|
||||||
c = {}
|
if "product" in obj:
|
||||||
c["product"] = obj["product"]
|
self.cpus.append(
|
||||||
c["vendor"] = obj["vendor"]
|
{
|
||||||
c["description"] = obj["description"]
|
"product": obj.get("product", "Unknown CPU"),
|
||||||
c["location"] = obj["slot"]
|
"vendor": obj.get("vendor", "Unknown vendor"),
|
||||||
|
"description": obj.get("description", ""),
|
||||||
self.cpus.append(c)
|
"location": obj.get("slot", ""),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def find_memories(self, obj):
|
def find_memories(self, obj):
|
||||||
if "children" not in obj:
|
if "children" not in obj:
|
||||||
|
@ -120,16 +155,26 @@ class LSHW():
|
||||||
if "empty" in dimm["description"]:
|
if "empty" in dimm["description"]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
d = {}
|
self.memories.append(
|
||||||
d["slot"] = dimm.get("slot")
|
{
|
||||||
d["description"] = dimm.get("description")
|
"slot": dimm.get("slot"),
|
||||||
d["id"] = dimm.get("id")
|
"description": dimm.get("description"),
|
||||||
d["serial"] = dimm.get("serial", 'N/A')
|
"id": dimm.get("id"),
|
||||||
d["vendor"] = dimm.get("vendor", 'N/A')
|
"serial": dimm.get("serial", "N/A"),
|
||||||
d["product"] = dimm.get("product")
|
"vendor": dimm.get("vendor", "N/A"),
|
||||||
d["size"] = dimm.get("size", 0) / 2 ** 20 / 1024
|
"product": dimm.get("product", "N/A"),
|
||||||
|
"size": dimm.get("size", 0) / 2**20 / 1024,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
self.memories.append(d)
|
def find_gpus(self, obj):
|
||||||
|
if "product" in obj:
|
||||||
|
infos = {
|
||||||
|
"product": obj.get("product", "Unknown GPU"),
|
||||||
|
"vendor": obj.get("vendor", "Unknown"),
|
||||||
|
"description": obj.get("description", ""),
|
||||||
|
}
|
||||||
|
self.gpus.append(infos)
|
||||||
|
|
||||||
def walk_bridge(self, obj):
|
def walk_bridge(self, obj):
|
||||||
if "children" not in obj:
|
if "children" not in obj:
|
||||||
|
@ -138,6 +183,8 @@ class LSHW():
|
||||||
for bus in obj["children"]:
|
for bus in obj["children"]:
|
||||||
if bus["class"] == "storage":
|
if bus["class"] == "storage":
|
||||||
self.find_storage(bus)
|
self.find_storage(bus)
|
||||||
|
if bus["class"] == "display":
|
||||||
|
self.find_gpus(bus)
|
||||||
|
|
||||||
if "children" in bus:
|
if "children" in bus:
|
||||||
for b in bus["children"]:
|
for b in bus["children"]:
|
||||||
|
@ -145,6 +192,8 @@ class LSHW():
|
||||||
self.find_storage(b)
|
self.find_storage(b)
|
||||||
if b["class"] == "network":
|
if b["class"] == "network":
|
||||||
self.find_network(b)
|
self.find_network(b)
|
||||||
|
if b["class"] == "display":
|
||||||
|
self.find_gpus(b)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -1,31 +1,113 @@
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
|
import subprocess
|
||||||
from shutil import which
|
from shutil import which
|
||||||
|
|
||||||
|
from slugify import slugify
|
||||||
|
|
||||||
|
from netbox_agent.config import netbox_instance as nb
|
||||||
|
|
||||||
|
|
||||||
def is_tool(name):
|
def is_tool(name):
|
||||||
'''Check whether `name` is on PATH and marked as executable.'''
|
"""Check whether `name` is on PATH and marked as executable."""
|
||||||
return which(name) is not None
|
return which(name) is not None
|
||||||
|
|
||||||
|
|
||||||
|
def get_device_role(role):
|
||||||
|
device_role = nb.dcim.device_roles.get(name=role)
|
||||||
|
if device_role is None:
|
||||||
|
raise Exception('DeviceRole "{}" does not exist, please create it'.format(role))
|
||||||
|
return device_role
|
||||||
|
|
||||||
|
|
||||||
|
def get_device_type(type):
|
||||||
|
device_type = nb.dcim.device_types.get(model=type)
|
||||||
|
if device_type is None:
|
||||||
|
raise Exception('DeviceType "{}" does not exist, please create it'.format(type))
|
||||||
|
return device_type
|
||||||
|
|
||||||
|
|
||||||
|
def get_device_platform(device_platform):
|
||||||
|
if device_platform is None:
|
||||||
|
try:
|
||||||
|
# Python 3.8+ moved linux_distribution() to distro
|
||||||
|
try:
|
||||||
|
import distro
|
||||||
|
|
||||||
|
linux_distribution = " ".join(distro.linux_distribution())
|
||||||
|
except ImportError:
|
||||||
|
import platform
|
||||||
|
|
||||||
|
linux_distribution = " ".join(platform.linux_distribution())
|
||||||
|
|
||||||
|
if not linux_distribution:
|
||||||
|
return None
|
||||||
|
except (ModuleNotFoundError, NameError, AttributeError):
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
linux_distribution = device_platform
|
||||||
|
|
||||||
|
device_platform = nb.dcim.platforms.get(name=linux_distribution)
|
||||||
|
if device_platform is None:
|
||||||
|
device_platform = nb.dcim.platforms.create(
|
||||||
|
name=linux_distribution, slug=slugify(linux_distribution)
|
||||||
|
)
|
||||||
|
return device_platform
|
||||||
|
|
||||||
|
|
||||||
def get_vendor(name):
|
def get_vendor(name):
|
||||||
vendors = {
|
vendors = {
|
||||||
'PERC': 'Dell',
|
"PERC": "Dell",
|
||||||
'SANDISK': 'SanDisk',
|
"SANDISK": "SanDisk",
|
||||||
'DELL': 'Dell',
|
"DELL": "Dell",
|
||||||
'ST': 'Seagate',
|
"ST": "Seagate",
|
||||||
'CRUCIAL': 'Crucial',
|
"CRUCIAL": "Crucial",
|
||||||
'MICRON': 'Micron',
|
"MICRON": "Micron",
|
||||||
'INTEL': 'Intel',
|
"INTEL": "Intel",
|
||||||
'SAMSUNG': 'Samsung',
|
"SAMSUNG": "Samsung",
|
||||||
'EH0': 'HP',
|
"EH0": "HP",
|
||||||
'HGST': 'HGST',
|
"HGST": "HGST",
|
||||||
'HUH': 'HGST',
|
"HUH": "HGST",
|
||||||
'MB': 'Toshiba',
|
"MB": "Toshiba",
|
||||||
'MC': 'Toshiba',
|
"MC": "Toshiba",
|
||||||
'MD': 'Toshiba',
|
"MD": "Toshiba",
|
||||||
'MG': 'Toshiba',
|
"MG": "Toshiba",
|
||||||
'WD': 'WDC'
|
"WD": "WDC",
|
||||||
}
|
}
|
||||||
for key, value in vendors.items():
|
for key, value in vendors.items():
|
||||||
if name.upper().startswith(key):
|
if name.upper().startswith(key):
|
||||||
return value
|
return value
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def get_hostname(config):
|
||||||
|
if config.hostname_cmd is None:
|
||||||
|
return "{}".format(socket.gethostname())
|
||||||
|
return subprocess.getoutput(config.hostname_cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def create_netbox_tags(tags):
|
||||||
|
ret = []
|
||||||
|
for tag in tags:
|
||||||
|
nb_tag = nb.extras.tags.get(name=tag)
|
||||||
|
if not nb_tag:
|
||||||
|
nb_tag = nb.extras.tags.create(
|
||||||
|
name=tag,
|
||||||
|
slug=slugify(tag),
|
||||||
|
)
|
||||||
|
ret.append(nb_tag)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def get_mount_points():
|
||||||
|
mount_points = {}
|
||||||
|
output = subprocess.getoutput("mount")
|
||||||
|
for r in output.split("\n"):
|
||||||
|
if not r.startswith("/dev/"):
|
||||||
|
continue
|
||||||
|
mount_info = r.split()
|
||||||
|
device = mount_info[0]
|
||||||
|
device = re.sub(r"\d+$", "", device)
|
||||||
|
mp = mount_info[2]
|
||||||
|
mount_points.setdefault(device, []).append(mp)
|
||||||
|
return mount_points
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,58 +1,68 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
import netbox_agent.dmidecode as dmidecode
|
||||||
from netbox_agent.config import netbox_instance as nb
|
from netbox_agent.config import netbox_instance as nb
|
||||||
|
|
||||||
PSU_DMI_TYPE = 39
|
PSU_DMI_TYPE = 39
|
||||||
|
|
||||||
|
|
||||||
class PowerSupply():
|
class PowerSupply:
|
||||||
def __init__(self, server=None):
|
def __init__(self, server=None):
|
||||||
self.server = server
|
self.server = server
|
||||||
self.netbox_server = self.server.get_netbox_server()
|
self.netbox_server = self.server.get_netbox_server()
|
||||||
if self.server.is_blade():
|
if self.server.is_blade():
|
||||||
self.device_id = self.netbox_server.parent_device.id if self.netbox_server else None
|
self.device_id = (
|
||||||
|
self.netbox_server.parent_device.id if self.netbox_server else None
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.device_id = self.netbox_server.id if self.netbox_server else None
|
self.device_id = self.netbox_server.id if self.netbox_server else None
|
||||||
|
|
||||||
def get_power_supply(self):
|
def get_power_supply(self):
|
||||||
power_supply = []
|
power_supply = []
|
||||||
for psu in self.server.dmi.get_by_type(PSU_DMI_TYPE):
|
for psu in dmidecode.get_by_type(self.server.dmi, PSU_DMI_TYPE):
|
||||||
if 'Present' not in psu['Status'] or psu['Status'] == 'Not Present':
|
if "Present" not in psu["Status"] or psu["Status"] == "Not Present":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
max_power = int(psu.get('Max Power Capacity').split()[0])
|
max_power = int(psu.get("Max Power Capacity").split()[0])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
max_power = None
|
max_power = None
|
||||||
desc = '{} - {}'.format(
|
desc = "{} - {}".format(
|
||||||
psu.get('Manufacturer', 'No Manufacturer').strip(),
|
psu.get("Manufacturer", "No Manufacturer").strip(),
|
||||||
psu.get('Name', 'No name').strip(),
|
psu.get("Name", "No name").strip(),
|
||||||
|
)
|
||||||
|
|
||||||
|
sn = psu.get("Serial Number", "").strip()
|
||||||
|
# Let's assume that if no serial and no power reported we skip it
|
||||||
|
if sn == "" and max_power is None:
|
||||||
|
continue
|
||||||
|
if sn == "":
|
||||||
|
sn = "N/A"
|
||||||
|
power_supply.append(
|
||||||
|
{
|
||||||
|
"name": sn,
|
||||||
|
"description": desc,
|
||||||
|
"allocated_draw": None,
|
||||||
|
"maximum_draw": max_power,
|
||||||
|
"device": self.device_id,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
power_supply.append({
|
|
||||||
'name': psu.get('Serial Number', 'No S/N').strip(),
|
|
||||||
'description': desc,
|
|
||||||
'allocated_draw': None,
|
|
||||||
'maximum_draw': max_power,
|
|
||||||
'device': self.device_id,
|
|
||||||
})
|
|
||||||
return power_supply
|
return power_supply
|
||||||
|
|
||||||
def get_netbox_power_supply(self):
|
def get_netbox_power_supply(self):
|
||||||
return nb.dcim.power_ports.filter(
|
return nb.dcim.power_ports.filter(device_id=self.device_id)
|
||||||
device_id=self.device_id
|
|
||||||
)
|
|
||||||
|
|
||||||
def create_or_update_power_supply(self):
|
def create_or_update_power_supply(self):
|
||||||
nb_psus = self.get_netbox_power_supply()
|
nb_psus = list(self.get_netbox_power_supply())
|
||||||
psus = self.get_power_supply()
|
psus = self.get_power_supply()
|
||||||
|
|
||||||
# Delete unknown PSU
|
# Delete unknown PSU
|
||||||
delete = False
|
delete = False
|
||||||
for nb_psu in nb_psus:
|
for nb_psu in nb_psus:
|
||||||
if nb_psu.name not in [x['name'] for x in psus]:
|
if nb_psu.name not in [x["name"] for x in psus]:
|
||||||
logging.info('Deleting unknown locally PSU {name}'.format(
|
logging.info(
|
||||||
name=nb_psu.name
|
"Deleting unknown locally PSU {name}".format(name=nb_psu.name)
|
||||||
))
|
)
|
||||||
nb_psu.delete()
|
nb_psu.delete()
|
||||||
delete = True
|
delete = True
|
||||||
|
|
||||||
|
@ -61,27 +71,23 @@ class PowerSupply():
|
||||||
|
|
||||||
# sync existing Netbox PSU with local infos
|
# sync existing Netbox PSU with local infos
|
||||||
for nb_psu in nb_psus:
|
for nb_psu in nb_psus:
|
||||||
local_psu = next(
|
local_psu = next(item for item in psus if item["name"] == nb_psu.name)
|
||||||
item for item in psus if item['name'] == nb_psu.name
|
|
||||||
)
|
|
||||||
update = False
|
update = False
|
||||||
if nb_psu.description != local_psu['description']:
|
if nb_psu.description != local_psu["description"]:
|
||||||
update = True
|
update = True
|
||||||
nb_psu.description = local_psu['description']
|
nb_psu.description = local_psu["description"]
|
||||||
if nb_psu.maximum_draw != local_psu['maximum_draw']:
|
if nb_psu.maximum_draw != local_psu["maximum_draw"]:
|
||||||
update = True
|
update = True
|
||||||
nb_psu.maximum_draw = local_psu['maximum_draw']
|
nb_psu.maximum_draw = local_psu["maximum_draw"]
|
||||||
if update:
|
if update:
|
||||||
nb_psu.save()
|
nb_psu.save()
|
||||||
|
|
||||||
for psu in psus:
|
for psu in psus:
|
||||||
if psu['name'] not in [x.name for x in nb_psus]:
|
if psu["name"] not in [x.name for x in nb_psus]:
|
||||||
logging.info('Creating PSU {name} ({description}), {maximum_draw}W'.format(
|
logging.info(
|
||||||
**psu
|
"Creating PSU {name} ({description}), {maximum_draw}W".format(**psu)
|
||||||
))
|
)
|
||||||
nb_psu = nb.dcim.power_ports.create(
|
nb_psu = nb.dcim.power_ports.create(**psu)
|
||||||
**psu
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -89,7 +95,7 @@ class PowerSupply():
|
||||||
try:
|
try:
|
||||||
psu_cons = self.server.get_power_consumption()
|
psu_cons = self.server.get_power_consumption()
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
logging.error('Cannot report power consumption for this vendor')
|
logging.error("Cannot report power consumption for this vendor")
|
||||||
return False
|
return False
|
||||||
nb_psus = self.get_netbox_power_supply()
|
nb_psus = self.get_netbox_power_supply()
|
||||||
|
|
||||||
|
@ -97,22 +103,27 @@ class PowerSupply():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# find power feeds for rack or dc
|
# find power feeds for rack or dc
|
||||||
voltage = None
|
|
||||||
pwr_feeds = None
|
pwr_feeds = None
|
||||||
if self.netbox_server.rack:
|
if self.netbox_server.rack:
|
||||||
pwr_feeds = nb.dcim.power_feeds.filter(
|
pwr_feeds = nb.dcim.power_feeds.filter(rack=self.netbox_server.rack.id)
|
||||||
rack=self.netbox_server.rack.id
|
|
||||||
)
|
if pwr_feeds:
|
||||||
if pwr_feeds is None or not len(pwr_feeds):
|
voltage = [p["voltage"] for p in pwr_feeds]
|
||||||
logging.info('Could not find power feeds for Rack, defaulting value to 230')
|
else:
|
||||||
voltage = 230
|
logging.info("Could not find power feeds for Rack, defaulting value to 230")
|
||||||
|
voltage = [230 for _ in nb_psus]
|
||||||
|
|
||||||
for i, nb_psu in enumerate(nb_psus):
|
for i, nb_psu in enumerate(nb_psus):
|
||||||
nb_psu.allocated_draw = float(psu_cons[i]) * voltage
|
nb_psu.allocated_draw = int(float(psu_cons[i]) * voltage[i])
|
||||||
|
if nb_psu.allocated_draw < 1:
|
||||||
|
logging.info("PSU is not connected or in standby mode")
|
||||||
|
continue
|
||||||
nb_psu.save()
|
nb_psu.save()
|
||||||
logging.info('Updated power consumption for PSU {}: {}W'.format(
|
logging.info(
|
||||||
nb_psu.name,
|
"Updated power consumption for PSU {}: {}W".format(
|
||||||
nb_psu.allocated_draw,
|
nb_psu.name,
|
||||||
))
|
nb_psu.allocated_draw,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class RaidController():
|
class RaidController:
|
||||||
|
|
||||||
def get_product_name(self):
|
def get_product_name(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -15,7 +15,10 @@ class RaidController():
|
||||||
def get_physical_disks(self):
|
def get_physical_disks(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def is_external(self):
|
||||||
|
return False
|
||||||
|
|
||||||
class Raid():
|
|
||||||
|
class Raid:
|
||||||
def get_controllers(self):
|
def get_controllers(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
|
@ -1,166 +1,240 @@
|
||||||
|
import logging
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from netbox_agent.raid.base import Raid, RaidController
|
|
||||||
from netbox_agent.misc import get_vendor
|
from netbox_agent.misc import get_vendor
|
||||||
|
from netbox_agent.raid.base import Raid, RaidController
|
||||||
|
|
||||||
REGEXP_CONTROLLER_HP = re.compile(r'Smart Array ([a-zA-Z0-9- ]+) in Slot ([0-9]+)')
|
REGEXP_CONTROLLER_HP = re.compile(r"Smart Array ([a-zA-Z0-9- ]+) in Slot ([0-9]+)")
|
||||||
|
|
||||||
|
|
||||||
def _get_indentation(string):
|
class HPRaidControllerError(Exception):
|
||||||
"""Return the number of spaces before the current line."""
|
pass
|
||||||
return len(string) - len(string.lstrip(' '))
|
|
||||||
|
|
||||||
|
|
||||||
def _get_key_value(string):
|
def ssacli(sub_command):
|
||||||
"""Return the (key, value) as a tuple from a string."""
|
command = ["ssacli"]
|
||||||
# Normally all properties look like this:
|
command.extend(sub_command.split())
|
||||||
# Unique Identifier: 600508B1001CE4ACF473EE9C826230FF
|
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
# Disk Name: /dev/sda
|
stdout, stderr = p.communicate()
|
||||||
# Mount Points: None
|
stdout = stdout.decode("utf-8")
|
||||||
key = ''
|
if p.returncode != 0:
|
||||||
value = ''
|
mesg = "Failed to execute command '{}':\n{}".format(" ".join(command), stdout)
|
||||||
try:
|
raise HPRaidControllerError(mesg)
|
||||||
key, value = string.split(':')
|
|
||||||
except ValueError:
|
|
||||||
# This handles the case when the property of a logical drive
|
|
||||||
# returned is as follows. Here we cannot split by ':' because
|
|
||||||
# the disk id has colon in it. So if this is about disk,
|
|
||||||
# then strip it accordingly.
|
|
||||||
# Mirror Group 0: physicaldrive 6I:1:5
|
|
||||||
string = string.lstrip(' ')
|
|
||||||
if string.startswith('physicaldrive'):
|
|
||||||
fields = string.split(' ')
|
|
||||||
key = fields[0]
|
|
||||||
value = fields[1]
|
|
||||||
else:
|
|
||||||
# TODO(rameshg87): Check if this ever occurs.
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
return key.lstrip(' ').rstrip(' '), value.lstrip(' ').rstrip(' ')
|
if "does not have any physical" in stdout:
|
||||||
|
return list()
|
||||||
|
else:
|
||||||
|
lines = stdout.split("\n")
|
||||||
|
lines = list(filter(None, lines))
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
def _get_dict(lines, start_index, indentation):
|
def _test_if_valid_line(line):
|
||||||
"""Recursive function for parsing hpssacli/ssacli output."""
|
ignore_patterns = [
|
||||||
|
"Note:",
|
||||||
|
"Error:",
|
||||||
|
"is not loaded",
|
||||||
|
"README",
|
||||||
|
" failure",
|
||||||
|
" cache",
|
||||||
|
]
|
||||||
|
for pattern in ignore_patterns:
|
||||||
|
if not line or pattern in line:
|
||||||
|
return None
|
||||||
|
return line
|
||||||
|
|
||||||
info = {}
|
|
||||||
current_item = None
|
|
||||||
|
|
||||||
i = start_index
|
def _parse_ctrl_output(lines):
|
||||||
while i < len(lines):
|
controllers = {}
|
||||||
current_line = lines[i]
|
current_ctrl = None
|
||||||
if current_line.startswith('Note:'):
|
|
||||||
i = i + 1
|
for line in lines:
|
||||||
|
line = line.strip()
|
||||||
|
line = _test_if_valid_line(line)
|
||||||
|
if line is None:
|
||||||
|
continue
|
||||||
|
ctrl = REGEXP_CONTROLLER_HP.search(line)
|
||||||
|
if ctrl is not None:
|
||||||
|
slot = ctrl.group(2)
|
||||||
|
current_ctrl = "{} - Slot {}".format(ctrl.group(1), slot)
|
||||||
|
controllers[current_ctrl] = {"Slot": slot}
|
||||||
|
if "Embedded" not in line:
|
||||||
|
controllers[current_ctrl]["External"] = True
|
||||||
|
continue
|
||||||
|
if ": " not in line:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
current_line_indentation = _get_indentation(current_line)
|
attr, val = line.split(": ", 1)
|
||||||
if current_line_indentation == indentation:
|
attr = attr.strip()
|
||||||
current_item = current_line.lstrip(' ')
|
val = val.strip()
|
||||||
|
controllers[current_ctrl][attr] = val
|
||||||
|
return controllers
|
||||||
|
|
||||||
info[current_item] = {}
|
|
||||||
i = i + 1
|
def _parse_pd_output(lines):
|
||||||
|
drives = {}
|
||||||
|
current_array = None
|
||||||
|
current_drv = None
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
line = line.strip()
|
||||||
|
line = _test_if_valid_line(line)
|
||||||
|
if line is None:
|
||||||
continue
|
continue
|
||||||
|
# Parses the Array the drives are in
|
||||||
|
if line.startswith("Array"):
|
||||||
|
current_array = line.split(None, 1)[1]
|
||||||
|
# Detects new physical drive
|
||||||
|
if line.startswith("physicaldrive"):
|
||||||
|
current_drv = line.split(None, 1)[1]
|
||||||
|
drives[current_drv] = {}
|
||||||
|
if current_array is not None:
|
||||||
|
drives[current_drv]["Array"] = current_array
|
||||||
|
continue
|
||||||
|
if ": " not in line:
|
||||||
|
continue
|
||||||
|
attr, val = line.split(": ", 1)
|
||||||
|
attr = attr.strip()
|
||||||
|
val = val.strip()
|
||||||
|
drives.setdefault(current_drv, {})[attr] = val
|
||||||
|
return drives
|
||||||
|
|
||||||
if i >= len(lines) - 1:
|
|
||||||
key, value = _get_key_value(current_line)
|
|
||||||
# If this is some unparsable information, then
|
|
||||||
# just skip it.
|
|
||||||
if key:
|
|
||||||
info[current_item][key] = value
|
|
||||||
return info, i
|
|
||||||
|
|
||||||
next_line = lines[i + 1]
|
def _parse_ld_output(lines):
|
||||||
next_line_indentation = _get_indentation(next_line)
|
drives = {}
|
||||||
|
current_array = None
|
||||||
|
current_drv = None
|
||||||
|
|
||||||
if current_line_indentation == next_line_indentation:
|
for line in lines:
|
||||||
key, value = _get_key_value(current_line)
|
line = line.strip()
|
||||||
if key:
|
line = _test_if_valid_line(line)
|
||||||
info[current_item][key] = value
|
if line is None:
|
||||||
i = i + 1
|
continue
|
||||||
elif next_line_indentation > current_line_indentation:
|
# Parses the Array the drives are in
|
||||||
ret_dict, j = _get_dict(lines, i, current_line_indentation)
|
if line.startswith("Array"):
|
||||||
info[current_item].update(ret_dict)
|
current_array = line.split(None, 1)[1]
|
||||||
i = j + 1
|
drives[current_array] = {}
|
||||||
elif next_line_indentation < current_line_indentation:
|
# Detects new physical drive
|
||||||
key, value = _get_key_value(current_line)
|
if line.startswith("Logical Drive"):
|
||||||
if key:
|
current_drv = line.split(": ", 1)[1]
|
||||||
info[current_item][key] = value
|
drives.setdefault(current_array, {})["LogicalDrive"] = current_drv
|
||||||
return info, i
|
continue
|
||||||
|
if ": " not in line:
|
||||||
return info, i
|
continue
|
||||||
|
attr, val = line.split(": ", 1)
|
||||||
|
drives.setdefault(current_array, {})[attr] = val
|
||||||
|
return drives
|
||||||
|
|
||||||
|
|
||||||
class HPRaidController(RaidController):
|
class HPRaidController(RaidController):
|
||||||
def __init__(self, controller_name, data):
|
def __init__(self, controller_name, data):
|
||||||
self.controller_name = controller_name
|
self.controller_name = controller_name
|
||||||
self.data = data
|
self.data = data
|
||||||
|
self.pdrives = self._get_physical_disks()
|
||||||
|
arrays = [d["Array"] for d in self.pdrives.values() if d.get("Array")]
|
||||||
|
if arrays:
|
||||||
|
self.ldrives = self._get_logical_drives()
|
||||||
|
self._get_virtual_drives_map()
|
||||||
|
|
||||||
def get_product_name(self):
|
def get_product_name(self):
|
||||||
return self.controller_name
|
return self.controller_name
|
||||||
|
|
||||||
def get_manufacturer(self):
|
def get_manufacturer(self):
|
||||||
return 'HP'
|
return "HP"
|
||||||
|
|
||||||
def get_serial_number(self):
|
def get_serial_number(self):
|
||||||
return self.data['Serial Number']
|
return self.data["Serial Number"]
|
||||||
|
|
||||||
def get_firmware_version(self):
|
def get_firmware_version(self):
|
||||||
return self.data['Firmware Version']
|
return self.data["Firmware Version"]
|
||||||
|
|
||||||
|
def is_external(self):
|
||||||
|
return self.data.get("External", False)
|
||||||
|
|
||||||
|
def _get_physical_disks(self):
|
||||||
|
lines = ssacli("ctrl slot={} pd all show detail".format(self.data["Slot"]))
|
||||||
|
pdrives = _parse_pd_output(lines)
|
||||||
|
ret = {}
|
||||||
|
|
||||||
|
for name, attrs in pdrives.items():
|
||||||
|
array = attrs.get("Array", "")
|
||||||
|
model = attrs.get("Model", "").strip()
|
||||||
|
vendor = None
|
||||||
|
if model.startswith("HP"):
|
||||||
|
vendor = "HP"
|
||||||
|
elif len(model.split()) > 1:
|
||||||
|
vendor = get_vendor(model.split()[1])
|
||||||
|
else:
|
||||||
|
vendor = get_vendor(model)
|
||||||
|
|
||||||
|
ret[name] = {
|
||||||
|
"Array": array,
|
||||||
|
"Model": model,
|
||||||
|
"Vendor": vendor,
|
||||||
|
"SN": attrs.get("Serial Number", "").strip(),
|
||||||
|
"Size": attrs.get("Size", "").strip(),
|
||||||
|
"Type": (
|
||||||
|
"SSD"
|
||||||
|
if attrs.get("Interface Type") == "Solid State SATA"
|
||||||
|
else "HDD"
|
||||||
|
),
|
||||||
|
"_src": self.__class__.__name__,
|
||||||
|
"custom_fields": {
|
||||||
|
"pd_identifier": name,
|
||||||
|
"mount_point": attrs.get("Mount Points", "").strip(),
|
||||||
|
"vd_device": attrs.get("Disk Name", "").strip(),
|
||||||
|
"vd_size": attrs.get("Size", "").strip(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def _get_logical_drives(self):
|
||||||
|
lines = ssacli("ctrl slot={} ld all show detail".format(self.data["Slot"]))
|
||||||
|
ldrives = _parse_ld_output(lines)
|
||||||
|
ret = {}
|
||||||
|
|
||||||
|
for array, attrs in ldrives.items():
|
||||||
|
ret[array] = {
|
||||||
|
"vd_array": array,
|
||||||
|
"vd_size": attrs.get("Size", "").strip(),
|
||||||
|
"vd_consistency": attrs.get("Status", "").strip(),
|
||||||
|
"vd_raid_type": "RAID {}".format(
|
||||||
|
attrs.get("Fault Tolerance", "N/A").strip()
|
||||||
|
),
|
||||||
|
"vd_device": attrs.get("LogicalDrive", "").strip(),
|
||||||
|
"mount_point": attrs.get("Mount Points", "").strip(),
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def _get_virtual_drives_map(self):
|
||||||
|
for name, attrs in self.pdrives.items():
|
||||||
|
array = attrs["Array"]
|
||||||
|
ld = self.ldrives.get(array)
|
||||||
|
if ld is None:
|
||||||
|
logging.error(
|
||||||
|
"Failed to find array information for physical drive {}."
|
||||||
|
" Ignoring.".format(name)
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
attrs["custom_fields"].update(ld)
|
||||||
|
|
||||||
def get_physical_disks(self):
|
def get_physical_disks(self):
|
||||||
ret = []
|
return list(self.pdrives.values())
|
||||||
output = subprocess.getoutput(
|
|
||||||
'ssacli ctrl slot={slot} pd all show detail'.format(slot=self.data['Slot'])
|
|
||||||
)
|
|
||||||
lines = output.split('\n')
|
|
||||||
lines = list(filter(None, lines))
|
|
||||||
j = -1
|
|
||||||
while j < len(lines):
|
|
||||||
info_dict, j = _get_dict(lines, j + 1, 0)
|
|
||||||
|
|
||||||
key = next(iter(info_dict))
|
|
||||||
for array, physical_disk in info_dict[key].items():
|
|
||||||
for _, pd_attr in physical_disk.items():
|
|
||||||
model = pd_attr.get('Model', '').strip()
|
|
||||||
vendor = None
|
|
||||||
if model.startswith('HP'):
|
|
||||||
vendor = 'HP'
|
|
||||||
elif len(model.split()) > 1:
|
|
||||||
vendor = get_vendor(model.split()[1])
|
|
||||||
else:
|
|
||||||
vendor = get_vendor(model)
|
|
||||||
|
|
||||||
ret.append({
|
|
||||||
'Model': model,
|
|
||||||
'Vendor': vendor,
|
|
||||||
'SN': pd_attr.get('Serial Number', '').strip(),
|
|
||||||
'Size': pd_attr.get('Size', '').strip(),
|
|
||||||
'Type': 'SSD' if pd_attr.get('Interface Type') == 'Solid State SATA'
|
|
||||||
else 'HDD',
|
|
||||||
'_src': self.__class__.__name__,
|
|
||||||
})
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
class HPRaid(Raid):
|
class HPRaid(Raid):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.output = subprocess.getoutput('ssacli ctrl all show detail')
|
self.output = subprocess.getoutput("ssacli ctrl all show detail")
|
||||||
self.controllers = []
|
self.controllers = []
|
||||||
self.convert_to_dict()
|
self.convert_to_dict()
|
||||||
|
|
||||||
def convert_to_dict(self):
|
def convert_to_dict(self):
|
||||||
lines = self.output.split('\n')
|
lines = self.output.split("\n")
|
||||||
lines = list(filter(None, lines))
|
lines = list(filter(None, lines))
|
||||||
j = -1
|
controllers = _parse_ctrl_output(lines)
|
||||||
while j < len(lines):
|
for controller, attrs in controllers.items():
|
||||||
info_dict, j = _get_dict(lines, j + 1, 0)
|
self.controllers.append(HPRaidController(controller, attrs))
|
||||||
if len(info_dict.keys()):
|
|
||||||
_product_name = list(info_dict.keys())[0]
|
|
||||||
product_name = REGEXP_CONTROLLER_HP.search(_product_name)
|
|
||||||
if product_name:
|
|
||||||
self.controllers.append(
|
|
||||||
HPRaidController(product_name.group(1), info_dict[_product_name])
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_controllers(self):
|
def get_controllers(self):
|
||||||
return self.controllers
|
return self.controllers
|
||||||
|
|
|
@ -1,25 +1,43 @@
|
||||||
|
import logging
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import xml.etree.ElementTree as ET # NOQA
|
|
||||||
|
|
||||||
from netbox_agent.misc import get_vendor
|
from netbox_agent.misc import get_mount_points, get_vendor
|
||||||
from netbox_agent.raid.base import Raid, RaidController
|
from netbox_agent.raid.base import Raid, RaidController
|
||||||
|
|
||||||
# Inspiration from https://github.com/asciiphil/perc-status/blob/master/perc-status
|
|
||||||
|
class OmreportControllerError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def get_field(obj, fieldname):
|
def omreport(sub_command):
|
||||||
f = obj.find(fieldname)
|
command = ["omreport"]
|
||||||
if f is None:
|
command.extend(sub_command.split())
|
||||||
return None
|
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
if f.attrib['type'] in ['u32', 'u64']:
|
p.wait()
|
||||||
if re.search('Mask$', fieldname):
|
stdout = p.stdout.read().decode("utf-8")
|
||||||
return int(f.text, 2)
|
if p.returncode != 0:
|
||||||
else:
|
mesg = "Failed to execute command '{}':\n{}".format(" ".join(command), stdout)
|
||||||
return int(f.text)
|
raise OmreportControllerError(mesg)
|
||||||
if f.attrib['type'] == 'astring':
|
|
||||||
return f.text
|
res = {}
|
||||||
return f.text
|
section_re = re.compile("^[A-Z]")
|
||||||
|
current_section = None
|
||||||
|
current_obj = None
|
||||||
|
|
||||||
|
for line in stdout.split("\n"):
|
||||||
|
if ": " in line:
|
||||||
|
attr, value = line.split(": ", 1)
|
||||||
|
attr = attr.strip()
|
||||||
|
value = value.strip()
|
||||||
|
if attr == "ID":
|
||||||
|
obj = {}
|
||||||
|
res.setdefault(current_section, []).append(obj)
|
||||||
|
current_obj = obj
|
||||||
|
current_obj[attr] = value
|
||||||
|
elif section_re.search(line) is not None:
|
||||||
|
current_section = line.strip()
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
class OmreportController(RaidController):
|
class OmreportController(RaidController):
|
||||||
|
@ -28,50 +46,82 @@ class OmreportController(RaidController):
|
||||||
self.controller_index = controller_index
|
self.controller_index = controller_index
|
||||||
|
|
||||||
def get_product_name(self):
|
def get_product_name(self):
|
||||||
return get_field(self.data, 'Name')
|
return self.data["Name"]
|
||||||
|
|
||||||
def get_manufacturer(self):
|
def get_manufacturer(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_serial_number(self):
|
def get_serial_number(self):
|
||||||
return get_field(self.data, 'DeviceSerialNumber')
|
return self.data.get("DeviceSerialNumber")
|
||||||
|
|
||||||
def get_firmware_version(self):
|
def get_firmware_version(self):
|
||||||
return get_field(self.data, 'Firmware Version')
|
return self.data.get("Firmware Version")
|
||||||
|
|
||||||
|
def _get_physical_disks(self):
|
||||||
|
pds = {}
|
||||||
|
res = omreport("storage pdisk controller={}".format(self.controller_index))
|
||||||
|
for pdisk in [d for d in list(res.values())[0]]:
|
||||||
|
disk_id = pdisk["ID"]
|
||||||
|
size = re.sub("B .*$", "B", pdisk["Capacity"])
|
||||||
|
pds[disk_id] = {
|
||||||
|
"Vendor": get_vendor(pdisk["Vendor ID"]),
|
||||||
|
"Model": pdisk["Product ID"],
|
||||||
|
"SN": pdisk["Serial No."],
|
||||||
|
"Size": size,
|
||||||
|
"Type": pdisk["Media"],
|
||||||
|
"_src": self.__class__.__name__,
|
||||||
|
}
|
||||||
|
return pds
|
||||||
|
|
||||||
|
def _get_virtual_drives_map(self):
|
||||||
|
pds = {}
|
||||||
|
res = omreport("storage vdisk controller={}".format(self.controller_index))
|
||||||
|
for vdisk in [d for d in list(res.values())[0]]:
|
||||||
|
vdisk_id = vdisk["ID"]
|
||||||
|
device = vdisk["Device Name"]
|
||||||
|
mount_points = get_mount_points()
|
||||||
|
mp = mount_points.get(device, "n/a")
|
||||||
|
size = re.sub("B .*$", "B", vdisk["Size"])
|
||||||
|
vd = {
|
||||||
|
"vd_array": vdisk_id,
|
||||||
|
"vd_size": size,
|
||||||
|
"vd_consistency": vdisk["State"],
|
||||||
|
"vd_raid_type": vdisk["Layout"],
|
||||||
|
"vd_device": vdisk["Device Name"],
|
||||||
|
"mount_point": ", ".join(sorted(mp)),
|
||||||
|
}
|
||||||
|
drives_res = omreport(
|
||||||
|
"storage pdisk controller={} vdisk={}".format(
|
||||||
|
self.controller_index, vdisk_id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for pdisk in [d for d in list(drives_res.values())[0]]:
|
||||||
|
pds[pdisk["ID"]] = vd
|
||||||
|
return pds
|
||||||
|
|
||||||
def get_physical_disks(self):
|
def get_physical_disks(self):
|
||||||
ret = []
|
pds = self._get_physical_disks()
|
||||||
output = subprocess.getoutput(
|
vds = self._get_virtual_drives_map()
|
||||||
'omreport storage controller controller={} -fmt xml'.format(self.controller_index)
|
for pd_identifier, vd in vds.items():
|
||||||
)
|
if pd_identifier not in pds:
|
||||||
root = ET.fromstring(output)
|
logging.error(
|
||||||
et_array_disks = root.find('ArrayDisks')
|
"Physical drive {} listed in virtual drive {} not "
|
||||||
if et_array_disks is not None:
|
"found in drives list".format(pd_identifier, vd["vd_array"])
|
||||||
for obj in et_array_disks.findall('DCStorageObject'):
|
)
|
||||||
ret.append({
|
continue
|
||||||
'Vendor': get_vendor(get_field(obj, 'Vendor')),
|
pds[pd_identifier].setdefault("custom_fields", {}).update(vd)
|
||||||
'Model': get_field(obj, 'ProductID'),
|
pds[pd_identifier]["custom_fields"]["pd_identifier"] = pd_identifier
|
||||||
'SN': get_field(obj, 'DeviceSerialNumber'),
|
return list(pds.values())
|
||||||
'Size': '{:.0f}GB'.format(
|
|
||||||
int(get_field(obj, 'Length')) / 1024 / 1024 / 1024
|
|
||||||
),
|
|
||||||
'Type': 'HDD' if int(get_field(obj, 'MediaType')) == 1 else 'SSD',
|
|
||||||
'_src': self.__class__.__name__,
|
|
||||||
})
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
class OmreportRaid(Raid):
|
class OmreportRaid(Raid):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
output = subprocess.getoutput('omreport storage controller -fmt xml')
|
|
||||||
controller_xml = ET.fromstring(output)
|
|
||||||
self.controllers = []
|
self.controllers = []
|
||||||
|
res = omreport("storage controller")
|
||||||
|
|
||||||
for obj in controller_xml.find('Controllers').findall('DCStorageObject'):
|
for controller in res["Controller"]:
|
||||||
ctrl_index = get_field(obj, 'ControllerNum')
|
ctrl_index = controller["ID"]
|
||||||
self.controllers.append(
|
self.controllers.append(OmreportController(ctrl_index, controller))
|
||||||
OmreportController(ctrl_index, obj)
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_controllers(self):
|
def get_controllers(self):
|
||||||
return self.controllers
|
return self.controllers
|
||||||
|
|
|
@ -1,73 +1,153 @@
|
||||||
import subprocess
|
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from netbox_agent.misc import get_vendor
|
from netbox_agent.config import config
|
||||||
|
from netbox_agent.misc import get_mount_points, get_vendor
|
||||||
from netbox_agent.raid.base import Raid, RaidController
|
from netbox_agent.raid.base import Raid, RaidController
|
||||||
|
|
||||||
|
|
||||||
|
class StorcliControllerError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def storecli(sub_command):
|
||||||
|
command = ["storcli"]
|
||||||
|
command.extend(sub_command.split())
|
||||||
|
command.append("J")
|
||||||
|
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
|
||||||
|
stdout, stderr = p.communicate()
|
||||||
|
if stderr:
|
||||||
|
mesg = "Failed to execute command '{}':\n{}".format(" ".join(command), stdout)
|
||||||
|
raise StorcliControllerError(mesg)
|
||||||
|
|
||||||
|
stdout = stdout.decode("utf-8")
|
||||||
|
data = json.loads(stdout)
|
||||||
|
|
||||||
|
controllers = dict(
|
||||||
|
[
|
||||||
|
(c["Command Status"]["Controller"], c["Response Data"])
|
||||||
|
for c in data["Controllers"]
|
||||||
|
if c["Command Status"]["Status"] == "Success"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if not controllers:
|
||||||
|
logging.error(
|
||||||
|
"Failed to execute command '{}'. "
|
||||||
|
"Ignoring data.".format(" ".join(command))
|
||||||
|
)
|
||||||
|
return {}
|
||||||
|
return controllers
|
||||||
|
|
||||||
|
|
||||||
class StorcliController(RaidController):
|
class StorcliController(RaidController):
|
||||||
def __init__(self, controller_index, data):
|
def __init__(self, controller_index, data):
|
||||||
self.data = data
|
self.data = data
|
||||||
self.controller_index = controller_index
|
self.controller_index = controller_index
|
||||||
|
|
||||||
def get_product_name(self):
|
def get_product_name(self):
|
||||||
return self.data['Product Name']
|
return self.data["Product Name"]
|
||||||
|
|
||||||
def get_manufacturer(self):
|
def get_manufacturer(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_serial_number(self):
|
def get_serial_number(self):
|
||||||
return self.data['Serial Number']
|
return self.data["Serial Number"]
|
||||||
|
|
||||||
def get_firmware_version(self):
|
def get_firmware_version(self):
|
||||||
return self.data['FW Package Build']
|
return self.data["FW Package Build"]
|
||||||
|
|
||||||
|
def _get_physical_disks(self):
|
||||||
|
pds = {}
|
||||||
|
cmd = "/c{}/eall/sall show all".format(self.controller_index)
|
||||||
|
controllers = storecli(cmd)
|
||||||
|
pd_info = controllers[self.controller_index]
|
||||||
|
pd_re = re.compile(r"^Drive (/c\d+/e\d+/s\d+)$")
|
||||||
|
|
||||||
|
for section, attrs in pd_info.items():
|
||||||
|
reg = pd_re.search(section)
|
||||||
|
if reg is None:
|
||||||
|
continue
|
||||||
|
pd_name = reg.group(1)
|
||||||
|
pd_attr = attrs[0]
|
||||||
|
pd_identifier = pd_attr["EID:Slt"]
|
||||||
|
size = pd_attr.get("Size", "").strip()
|
||||||
|
media_type = pd_attr.get("Med", "").strip()
|
||||||
|
pd_details = pd_info["{} - Detailed Information".format(section)]
|
||||||
|
pd_dev_attr = pd_details["{} Device attributes".format(section)]
|
||||||
|
model = pd_dev_attr.get("Model Number", "").strip()
|
||||||
|
pd = {
|
||||||
|
"Model": model,
|
||||||
|
"Vendor": get_vendor(model),
|
||||||
|
"SN": pd_dev_attr.get("SN", "").strip(),
|
||||||
|
"Size": size,
|
||||||
|
"Type": media_type,
|
||||||
|
"_src": self.__class__.__name__,
|
||||||
|
}
|
||||||
|
if config.process_virtual_drives:
|
||||||
|
pd.setdefault("custom_fields", {})["pd_identifier"] = pd_name
|
||||||
|
pds[pd_identifier] = pd
|
||||||
|
return pds
|
||||||
|
|
||||||
|
def _get_virtual_drives_map(self):
|
||||||
|
vds = {}
|
||||||
|
cmd = "/c{}/vall show all".format(self.controller_index)
|
||||||
|
controllers = storecli(cmd)
|
||||||
|
vd_info = controllers[self.controller_index]
|
||||||
|
mount_points = get_mount_points()
|
||||||
|
|
||||||
|
for vd_identifier, vd_attrs in vd_info.items():
|
||||||
|
if not vd_identifier.startswith("/c{}/v".format(self.controller_index)):
|
||||||
|
continue
|
||||||
|
volume = vd_identifier.split("/")[-1].lstrip("v")
|
||||||
|
vd_attr = vd_attrs[0]
|
||||||
|
vd_pd_identifier = "PDs for VD {}".format(volume)
|
||||||
|
vd_pds = vd_info[vd_pd_identifier]
|
||||||
|
vd_prop_identifier = "VD{} Properties".format(volume)
|
||||||
|
vd_properties = vd_info[vd_prop_identifier]
|
||||||
|
for pd in vd_pds:
|
||||||
|
pd_identifier = pd["EID:Slt"]
|
||||||
|
wwn = vd_properties["SCSI NAA Id"]
|
||||||
|
wwn_path = "/dev/disk/by-id/wwn-0x{}".format(wwn)
|
||||||
|
device = os.path.realpath(wwn_path)
|
||||||
|
mp = mount_points.get(device, "n/a")
|
||||||
|
vds[pd_identifier] = {
|
||||||
|
"vd_array": vd_identifier,
|
||||||
|
"vd_size": vd_attr["Size"],
|
||||||
|
"vd_consistency": vd_attr["Consist"],
|
||||||
|
"vd_raid_type": vd_attr["TYPE"],
|
||||||
|
"vd_device": device,
|
||||||
|
"mount_point": ", ".join(sorted(mp)),
|
||||||
|
}
|
||||||
|
return vds
|
||||||
|
|
||||||
def get_physical_disks(self):
|
def get_physical_disks(self):
|
||||||
ret = []
|
# Parses physical disks information
|
||||||
output = subprocess.getoutput(
|
pds = self._get_physical_disks()
|
||||||
'storcli /c{}/eall/sall show all J'.format(self.controller_index)
|
|
||||||
)
|
|
||||||
drive_infos = json.loads(output)['Controllers'][self.controller_index]['Response Data']
|
|
||||||
|
|
||||||
for physical_drive in self.data['PD LIST']:
|
# Parses virtual drives information and maps them to physical disks
|
||||||
enclosure = physical_drive.get('EID:Slt').split(':')[0]
|
vds = self._get_virtual_drives_map()
|
||||||
slot = physical_drive.get('EID:Slt').split(':')[1]
|
for pd_identifier, vd in vds.items():
|
||||||
size = physical_drive.get('Size').strip()
|
if pd_identifier not in pds:
|
||||||
media_type = physical_drive.get('Med').strip()
|
logging.error(
|
||||||
drive_identifier = 'Drive /c{}/e{}/s{}'.format(
|
"Physical drive {} listed in virtual drive {} not "
|
||||||
str(self.controller_index), str(enclosure), str(slot)
|
"found in drives list".format(pd_identifier, vd["vd_array"])
|
||||||
)
|
)
|
||||||
drive_attr = drive_infos['{} - Detailed Information'.format(drive_identifier)][
|
continue
|
||||||
'{} Device attributes'.format(drive_identifier)]
|
pds[pd_identifier].setdefault("custom_fields", {}).update(vd)
|
||||||
model = drive_attr.get('Model Number', '').strip()
|
|
||||||
ret.append({
|
return list(pds.values())
|
||||||
'Model': model,
|
|
||||||
'Vendor': get_vendor(model),
|
|
||||||
'SN': drive_attr.get('SN', '').strip(),
|
|
||||||
'Size': size,
|
|
||||||
'Type': media_type,
|
|
||||||
'_src': self.__class__.__name__,
|
|
||||||
})
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
class StorcliRaid(Raid):
|
class StorcliRaid(Raid):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.output = subprocess.getoutput('storcli /call show J')
|
|
||||||
self.data = json.loads(self.output)
|
|
||||||
self.controllers = []
|
self.controllers = []
|
||||||
|
controllers = storecli("/call show")
|
||||||
if len([
|
for controller_id, controller_data in controllers.items():
|
||||||
x for x in self.data['Controllers']
|
self.controllers.append(StorcliController(controller_id, controller_data))
|
||||||
if x['Command Status']['Status'] == 'Success'
|
|
||||||
]) > 0:
|
|
||||||
for controller in self.data['Controllers']:
|
|
||||||
self.controllers.append(
|
|
||||||
StorcliController(
|
|
||||||
controller['Command Status']['Controller'],
|
|
||||||
controller['Response Data']
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_controllers(self):
|
def get_controllers(self):
|
||||||
return self.controllers
|
return self.controllers
|
||||||
|
|
|
@ -1,60 +1,111 @@
|
||||||
import logging
|
import logging
|
||||||
from pprint import pprint
|
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
from netbox_agent.config import netbox_instance as nb, config
|
|
||||||
import netbox_agent.dmidecode as dmidecode
|
import netbox_agent.dmidecode as dmidecode
|
||||||
from netbox_agent.location import Datacenter, Rack
|
from netbox_agent.config import config
|
||||||
|
from netbox_agent.config import netbox_instance as nb
|
||||||
from netbox_agent.inventory import Inventory
|
from netbox_agent.inventory import Inventory
|
||||||
from netbox_agent.network import Network
|
from netbox_agent.location import Datacenter, Rack, Tenant
|
||||||
|
from netbox_agent.misc import (
|
||||||
|
create_netbox_tags,
|
||||||
|
get_device_platform,
|
||||||
|
get_device_role,
|
||||||
|
get_device_type,
|
||||||
|
)
|
||||||
|
from netbox_agent.network import ServerNetwork
|
||||||
from netbox_agent.power import PowerSupply
|
from netbox_agent.power import PowerSupply
|
||||||
|
|
||||||
|
|
||||||
class ServerBase():
|
class ServerBase:
|
||||||
def __init__(self, dmi=None):
|
def __init__(self, dmi=None):
|
||||||
if dmi:
|
if dmi:
|
||||||
self.dmi = dmi
|
self.dmi = dmi
|
||||||
else:
|
else:
|
||||||
self.dmi = dmidecode.parse()
|
self.dmi = dmidecode.parse()
|
||||||
|
|
||||||
self.baseboard = self.dmi.get_by_type('Baseboard')
|
self.baseboard = dmidecode.get_by_type(self.dmi, "Baseboard")
|
||||||
self.bios = self.dmi.get_by_type('BIOS')
|
self.bios = dmidecode.get_by_type(self.dmi, "BIOS")
|
||||||
self.chassis = self.dmi.get_by_type('Chassis')
|
self.chassis = dmidecode.get_by_type(self.dmi, "Chassis")
|
||||||
self.system = self.dmi.get_by_type('System')
|
self.system = dmidecode.get_by_type(self.dmi, "System")
|
||||||
|
self.device_platform = get_device_platform(config.device.platform)
|
||||||
|
|
||||||
self.network = None
|
self.network = None
|
||||||
|
|
||||||
|
self.tags = (
|
||||||
|
list(set([x.strip() for x in config.device.tags.split(",") if x.strip()]))
|
||||||
|
if config.device.tags
|
||||||
|
else []
|
||||||
|
)
|
||||||
|
self.nb_tags = list(create_netbox_tags(self.tags))
|
||||||
|
config_cf = set(
|
||||||
|
[f.strip() for f in config.device.custom_fields.split(",") if f.strip()]
|
||||||
|
)
|
||||||
|
self.custom_fields = {}
|
||||||
|
self.custom_fields.update(
|
||||||
|
dict(
|
||||||
|
[
|
||||||
|
(k.strip(), v.strip())
|
||||||
|
for k, v in [f.split("=", 1) for f in config_cf]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_tenant(self):
|
||||||
|
tenant = Tenant()
|
||||||
|
return tenant.get()
|
||||||
|
|
||||||
|
def get_netbox_tenant(self):
|
||||||
|
tenant = self.get_tenant()
|
||||||
|
if tenant is None:
|
||||||
|
return None
|
||||||
|
nb_tenant = nb.tenancy.tenants.get(slug=self.get_tenant())
|
||||||
|
return nb_tenant
|
||||||
|
|
||||||
def get_datacenter(self):
|
def get_datacenter(self):
|
||||||
dc = Datacenter()
|
dc = Datacenter()
|
||||||
return dc.get()
|
return dc.get()
|
||||||
|
|
||||||
def get_netbox_datacenter(self):
|
def get_netbox_datacenter(self):
|
||||||
datacenter = nb.dcim.sites.get(
|
dc = self.get_datacenter()
|
||||||
slug=self.get_datacenter()
|
if dc is None:
|
||||||
|
logging.error("Specifying a datacenter (Site) is mandatory in Netbox")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
nb_dc = nb.dcim.sites.get(
|
||||||
|
slug=dc,
|
||||||
)
|
)
|
||||||
return datacenter
|
if nb_dc is None:
|
||||||
|
logging.error("Site (slug: {}) has not been found".format(dc))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return nb_dc
|
||||||
|
|
||||||
def update_netbox_location(self, server):
|
def update_netbox_location(self, server):
|
||||||
dc = self.get_datacenter()
|
dc = self.get_datacenter()
|
||||||
rack = self.get_rack()
|
|
||||||
nb_rack = self.get_netbox_rack()
|
nb_rack = self.get_netbox_rack()
|
||||||
nb_dc = self.get_netbox_datacenter()
|
nb_dc = self.get_netbox_datacenter()
|
||||||
|
|
||||||
update = False
|
update = False
|
||||||
if dc and server.site and server.site.slug != nb_dc.slug:
|
if dc and server.site and server.site.slug != nb_dc.slug:
|
||||||
logging.info('Datacenter location has changed from {} to {}, updating'.format(
|
logging.info(
|
||||||
server.site.slug,
|
"Datacenter location has changed from {} to {}, updating".format(
|
||||||
nb_dc.slug,
|
server.site.slug,
|
||||||
))
|
nb_dc.slug,
|
||||||
|
)
|
||||||
|
)
|
||||||
update = True
|
update = True
|
||||||
server.site = nb_dc.id
|
server.site = nb_dc.id
|
||||||
|
|
||||||
if rack and server.rack and server.rack.id != nb_rack.id:
|
if server.rack and nb_rack and server.rack.id != nb_rack.id:
|
||||||
logging.info('Rack location has changed from {} to {}, updating'.format(
|
logging.info(
|
||||||
server.rack,
|
"Rack location has changed from {} to {}, updating".format(
|
||||||
nb_rack,
|
server.rack,
|
||||||
))
|
nb_rack,
|
||||||
|
)
|
||||||
|
)
|
||||||
update = True
|
update = True
|
||||||
server.rack = nb_rack
|
server.rack = nb_rack
|
||||||
if nb_rack is None:
|
if nb_rack is None:
|
||||||
|
@ -62,32 +113,59 @@ class ServerBase():
|
||||||
server.position = None
|
server.position = None
|
||||||
return update, server
|
return update, server
|
||||||
|
|
||||||
|
def update_netbox_expansion_location(self, server, expansion):
|
||||||
|
update = False
|
||||||
|
if expansion.tenant != server.tenant:
|
||||||
|
expansion.tenant = server.tenant
|
||||||
|
update = True
|
||||||
|
if expansion.site != server.site:
|
||||||
|
expansion.site = server.site
|
||||||
|
update = True
|
||||||
|
if expansion.rack != server.rack:
|
||||||
|
expansion.rack = server.rack
|
||||||
|
update = True
|
||||||
|
return update
|
||||||
|
|
||||||
def get_rack(self):
|
def get_rack(self):
|
||||||
rack = Rack()
|
rack = Rack()
|
||||||
return rack.get()
|
return rack.get()
|
||||||
|
|
||||||
def get_netbox_rack(self):
|
def get_netbox_rack(self):
|
||||||
rack = nb.dcim.racks.get(
|
rack = self.get_rack()
|
||||||
name=self.get_rack(),
|
datacenter = self.get_netbox_datacenter()
|
||||||
site_id=self.get_netbox_datacenter().id,
|
if not rack:
|
||||||
|
return None
|
||||||
|
if rack and not datacenter:
|
||||||
|
logging.error("Can't get rack if no datacenter is configured or found")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return nb.dcim.racks.get(
|
||||||
|
name=rack,
|
||||||
|
site_id=datacenter.id,
|
||||||
)
|
)
|
||||||
return rack
|
|
||||||
|
|
||||||
def get_product_name(self):
|
def get_product_name(self):
|
||||||
"""
|
"""
|
||||||
Return the Chassis Name from dmidecode info
|
Return the Chassis Name from dmidecode info
|
||||||
"""
|
"""
|
||||||
return self.system[0]['Product Name'].strip()
|
return self.system[0]["Product Name"].strip()
|
||||||
|
|
||||||
def get_service_tag(self):
|
def get_service_tag(self):
|
||||||
"""
|
"""
|
||||||
Return the Service Tag from dmidecode info
|
Return the Service Tag from dmidecode info
|
||||||
"""
|
"""
|
||||||
return self.system[0]['Serial Number'].strip()
|
return self.system[0]["Serial Number"].strip()
|
||||||
|
|
||||||
|
def get_expansion_service_tag(self):
|
||||||
|
"""
|
||||||
|
Return the virtual Service Tag from dmidecode info host
|
||||||
|
with 'expansion'
|
||||||
|
"""
|
||||||
|
return self.system[0]["Serial Number"].strip() + " expansion"
|
||||||
|
|
||||||
def get_hostname(self):
|
def get_hostname(self):
|
||||||
if config.hostname_cmd is None:
|
if config.hostname_cmd is None:
|
||||||
return '{}'.format(socket.gethostname())
|
return "{}".format(socket.gethostname())
|
||||||
return subprocess.getoutput(config.hostname_cmd)
|
return subprocess.getoutput(config.hostname_cmd)
|
||||||
|
|
||||||
def is_blade(self):
|
def is_blade(self):
|
||||||
|
@ -117,236 +195,352 @@ class ServerBase():
|
||||||
def get_power_consumption(self):
|
def get_power_consumption(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def _netbox_create_blade_chassis(self, datacenter, rack):
|
def get_expansion_product(self):
|
||||||
device_type = nb.dcim.device_types.get(
|
raise NotImplementedError
|
||||||
model=self.get_chassis(),
|
|
||||||
)
|
def _netbox_create_chassis(self, datacenter, tenant, rack):
|
||||||
if not device_type:
|
device_type = get_device_type(self.get_chassis())
|
||||||
error_msg = 'Chassis "{}" doesn\'t exist'.format(self.get_chassis())
|
device_role = get_device_role(config.device.chassis_role)
|
||||||
logging.error(error_msg)
|
|
||||||
raise Exception(error_msg)
|
|
||||||
device_role = nb.dcim.device_roles.get(
|
|
||||||
name='Server Chassis',
|
|
||||||
)
|
|
||||||
serial = self.get_chassis_service_tag()
|
serial = self.get_chassis_service_tag()
|
||||||
logging.info('Creating chassis blade (serial: {serial})'.format(
|
logging.info("Creating chassis blade (serial: {serial})".format(serial=serial))
|
||||||
serial=serial))
|
|
||||||
new_chassis = nb.dcim.devices.create(
|
new_chassis = nb.dcim.devices.create(
|
||||||
name=self.get_chassis_name(),
|
name=self.get_chassis_name(),
|
||||||
device_type=device_type.id,
|
device_type=device_type.id,
|
||||||
serial=serial,
|
serial=serial,
|
||||||
device_role=device_role.id,
|
role=device_role.id,
|
||||||
site=datacenter.id if datacenter else None,
|
site=datacenter.id if datacenter else None,
|
||||||
|
tenant=tenant.id if tenant else None,
|
||||||
rack=rack.id if rack else None,
|
rack=rack.id if rack else None,
|
||||||
|
tags=[{"name": x} for x in self.tags],
|
||||||
|
custom_fields=self.custom_fields,
|
||||||
)
|
)
|
||||||
return new_chassis
|
return new_chassis
|
||||||
|
|
||||||
def _netbox_create_blade(self, chassis, datacenter, rack):
|
def _netbox_create_blade(self, chassis, datacenter, tenant, rack):
|
||||||
device_role = nb.dcim.device_roles.get(
|
device_role = get_device_role(config.device.blade_role)
|
||||||
name='Blade',
|
device_type = get_device_type(self.get_product_name())
|
||||||
)
|
|
||||||
device_type = nb.dcim.device_types.get(
|
|
||||||
model=self.get_product_name(),
|
|
||||||
)
|
|
||||||
serial = self.get_service_tag()
|
serial = self.get_service_tag()
|
||||||
hostname = self.get_hostname()
|
hostname = self.get_hostname()
|
||||||
logging.info(
|
logging.info(
|
||||||
'Creating blade (serial: {serial}) {hostname} on chassis {chassis_serial}'.format(
|
"Creating blade (serial: {serial}) {hostname} on chassis {chassis_serial}".format(
|
||||||
serial=serial, hostname=hostname, chassis_serial=chassis.serial
|
serial=serial, hostname=hostname, chassis_serial=chassis.serial
|
||||||
))
|
)
|
||||||
|
)
|
||||||
new_blade = nb.dcim.devices.create(
|
new_blade = nb.dcim.devices.create(
|
||||||
name=hostname,
|
name=hostname,
|
||||||
serial=serial,
|
serial=serial,
|
||||||
device_role=device_role.id,
|
role=device_role.id,
|
||||||
device_type=device_type.id,
|
device_type=device_type.id,
|
||||||
parent_device=chassis.id,
|
parent_device=chassis.id,
|
||||||
site=datacenter.id if datacenter else None,
|
site=datacenter.id if datacenter else None,
|
||||||
|
tenant=tenant.id if tenant else None,
|
||||||
rack=rack.id if rack else None,
|
rack=rack.id if rack else None,
|
||||||
|
tags=[{"name": x} for x in self.tags],
|
||||||
|
custom_fields=self.custom_fields,
|
||||||
)
|
)
|
||||||
return new_blade
|
return new_blade
|
||||||
|
|
||||||
def _netbox_set_blade_slot(self, chassis, server):
|
def _netbox_create_blade_expansion(self, chassis, datacenter, tenant, rack):
|
||||||
slot = self.get_blade_slot()
|
device_role = get_device_role(config.device.blade_role)
|
||||||
# Find the slot and update it with our blade
|
device_type = get_device_type(self.get_expansion_product())
|
||||||
device_bays = nb.dcim.device_bays.filter(
|
serial = self.get_expansion_service_tag()
|
||||||
device_id=chassis.id,
|
hostname = self.get_hostname() + " expansion"
|
||||||
name=slot,
|
logging.info(
|
||||||
|
"Creating expansion (serial: {serial}) {hostname} on chassis {chassis_serial}".format(
|
||||||
|
serial=serial, hostname=hostname, chassis_serial=chassis.serial
|
||||||
|
)
|
||||||
)
|
)
|
||||||
if len(device_bays) > 0:
|
new_blade = nb.dcim.devices.create(
|
||||||
logging.info(
|
name=hostname,
|
||||||
'Setting device ({serial}) new slot on {slot} '
|
serial=serial,
|
||||||
'(Chassis {chassis_serial})..'.format(
|
role=device_role.id,
|
||||||
serial=server.serial, slot=slot, chassis_serial=chassis.serial
|
device_type=device_type.id,
|
||||||
))
|
parent_device=chassis.id,
|
||||||
device_bay = device_bays[0]
|
site=datacenter.id if datacenter else None,
|
||||||
device_bay.installed_device = server
|
tenant=tenant.id if tenant else None,
|
||||||
device_bay.save()
|
rack=rack.id if rack else None,
|
||||||
else:
|
tags=[{"name": x} for x in self.tags],
|
||||||
logging.error('Could not find slot {slot} for chassis'.format(
|
)
|
||||||
slot=slot
|
return new_blade
|
||||||
))
|
|
||||||
|
|
||||||
def _netbox_create_server(self, datacenter, rack):
|
def _netbox_deduplicate_server(self):
|
||||||
device_role = nb.dcim.device_roles.get(
|
serial = self.get_service_tag()
|
||||||
name='Server',
|
hostname = self.get_hostname()
|
||||||
)
|
server = nb.dcim.devices.get(name=hostname)
|
||||||
device_type = nb.dcim.device_types.get(
|
if server and server.serial != serial:
|
||||||
model=self.get_product_name(),
|
server.delete()
|
||||||
)
|
|
||||||
|
def _netbox_create_server(self, datacenter, tenant, rack):
|
||||||
|
device_role = get_device_role(config.device.server_role)
|
||||||
|
device_type = get_device_type(self.get_product_name())
|
||||||
if not device_type:
|
if not device_type:
|
||||||
raise Exception('Chassis "{}" doesn\'t exist'.format(self.get_chassis()))
|
raise Exception('Chassis "{}" doesn\'t exist'.format(self.get_chassis()))
|
||||||
serial = self.get_service_tag()
|
serial = self.get_service_tag()
|
||||||
hostname = self.get_hostname()
|
hostname = self.get_hostname()
|
||||||
logging.info('Creating server (serial: {serial}) {hostname}'.format(
|
logging.info(
|
||||||
serial=serial, hostname=hostname))
|
"Creating server (serial: {serial}) {hostname}".format(
|
||||||
|
serial=serial, hostname=hostname
|
||||||
|
)
|
||||||
|
)
|
||||||
new_server = nb.dcim.devices.create(
|
new_server = nb.dcim.devices.create(
|
||||||
name=hostname,
|
name=hostname,
|
||||||
serial=serial,
|
serial=serial,
|
||||||
device_role=device_role.id,
|
role=device_role.id,
|
||||||
device_type=device_type.id,
|
device_type=device_type.id,
|
||||||
|
platform=self.device_platform.id,
|
||||||
site=datacenter.id if datacenter else None,
|
site=datacenter.id if datacenter else None,
|
||||||
|
tenant=tenant.id if tenant else None,
|
||||||
rack=rack.id if rack else None,
|
rack=rack.id if rack else None,
|
||||||
|
tags=[{"name": x} for x in self.tags],
|
||||||
)
|
)
|
||||||
return new_server
|
return new_server
|
||||||
|
|
||||||
def get_netbox_server(self):
|
def get_netbox_server(self, expansion=False):
|
||||||
return nb.dcim.devices.get(serial=self.get_service_tag())
|
if expansion is False:
|
||||||
|
return nb.dcim.devices.get(serial=self.get_service_tag())
|
||||||
|
else:
|
||||||
|
return nb.dcim.devices.get(serial=self.get_expansion_service_tag())
|
||||||
|
|
||||||
def netbox_create(self, config):
|
def _netbox_set_or_update_blade_slot(self, server, chassis, datacenter):
|
||||||
logging.debug('Creating Server..')
|
# before everything check if right chassis
|
||||||
|
actual_device_bay = (
|
||||||
|
server.parent_device.device_bay if server.parent_device else None
|
||||||
|
)
|
||||||
|
actual_chassis = actual_device_bay.device if actual_device_bay else None
|
||||||
|
slot = self.get_blade_slot()
|
||||||
|
if (
|
||||||
|
actual_chassis
|
||||||
|
and actual_chassis.serial == chassis.serial
|
||||||
|
and actual_device_bay.name == slot
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
real_device_bays = nb.dcim.device_bays.filter(
|
||||||
|
device_id=chassis.id,
|
||||||
|
name=slot,
|
||||||
|
)
|
||||||
|
real_device_bays = nb.dcim.device_bays.filter(
|
||||||
|
device_id=chassis.id,
|
||||||
|
name=slot,
|
||||||
|
)
|
||||||
|
if real_device_bays:
|
||||||
|
logging.info(
|
||||||
|
"Setting device ({serial}) new slot on {slot} "
|
||||||
|
"(Chassis {chassis_serial})..".format(
|
||||||
|
serial=server.serial, slot=slot, chassis_serial=chassis.serial
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# reset actual device bay if set
|
||||||
|
if actual_device_bay:
|
||||||
|
# Forces the evaluation of the installed_device attribute to
|
||||||
|
# workaround a bug probably due to lazy loading optimization
|
||||||
|
# that prevents the value change detection
|
||||||
|
actual_device_bay.installed_device
|
||||||
|
actual_device_bay.installed_device = None
|
||||||
|
actual_device_bay.save()
|
||||||
|
# setup new device bay
|
||||||
|
real_device_bay = next(real_device_bays)
|
||||||
|
real_device_bay.installed_device = server
|
||||||
|
real_device_bay.save()
|
||||||
|
else:
|
||||||
|
logging.error("Could not find slot {slot} for chassis".format(slot=slot))
|
||||||
|
|
||||||
|
def _netbox_set_or_update_blade_expansion_slot(
|
||||||
|
self, expansion, chassis, datacenter
|
||||||
|
):
|
||||||
|
# before everything check if right chassis
|
||||||
|
actual_device_bay = (
|
||||||
|
expansion.parent_device.device_bay if expansion.parent_device else None
|
||||||
|
)
|
||||||
|
actual_chassis = actual_device_bay.device if actual_device_bay else None
|
||||||
|
slot = self.get_blade_expansion_slot()
|
||||||
|
if (
|
||||||
|
actual_chassis
|
||||||
|
and actual_chassis.serial == chassis.serial
|
||||||
|
and actual_device_bay.name == slot
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
real_device_bays = nb.dcim.device_bays.filter(
|
||||||
|
device_id=chassis.id,
|
||||||
|
name=slot,
|
||||||
|
)
|
||||||
|
if not real_device_bays:
|
||||||
|
logging.error(
|
||||||
|
"Could not find slot {slot} expansion for chassis".format(slot=slot)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
logging.info(
|
||||||
|
"Setting device expansion ({serial}) new slot on {slot} "
|
||||||
|
"(Chassis {chassis_serial})..".format(
|
||||||
|
serial=expansion.serial, slot=slot, chassis_serial=chassis.serial
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# reset actual device bay if set
|
||||||
|
if actual_device_bay:
|
||||||
|
# Forces the evaluation of the installed_device attribute to
|
||||||
|
# workaround a bug probably due to lazy loading optimization
|
||||||
|
# that prevents the value change detection
|
||||||
|
actual_device_bay.installed_device
|
||||||
|
actual_device_bay.installed_device = None
|
||||||
|
actual_device_bay.save()
|
||||||
|
# setup new device bay
|
||||||
|
real_device_bay = next(real_device_bays)
|
||||||
|
real_device_bay.installed_device = expansion
|
||||||
|
real_device_bay.save()
|
||||||
|
|
||||||
|
def netbox_create_or_update(self, config):
|
||||||
|
"""
|
||||||
|
Netbox method to create or update info about our server/blade
|
||||||
|
|
||||||
|
Handle:
|
||||||
|
* new chassis for a blade
|
||||||
|
* new slot for a blade
|
||||||
|
* hostname update
|
||||||
|
* Network infos
|
||||||
|
* Inventory management
|
||||||
|
* PSU management
|
||||||
|
"""
|
||||||
datacenter = self.get_netbox_datacenter()
|
datacenter = self.get_netbox_datacenter()
|
||||||
rack = self.get_netbox_rack()
|
rack = self.get_netbox_rack()
|
||||||
if self.is_blade():
|
tenant = self.get_netbox_tenant()
|
||||||
# let's find the blade
|
|
||||||
serial = self.get_service_tag()
|
|
||||||
blade = nb.dcim.devices.get(serial=serial)
|
|
||||||
chassis = nb.dcim.devices.get(serial=self.get_chassis_service_tag())
|
|
||||||
# if it doesn't exist, create it
|
|
||||||
if not blade:
|
|
||||||
# check if the chassis exist before
|
|
||||||
# if it doesn't exist, create it
|
|
||||||
chassis = nb.dcim.devices.get(
|
|
||||||
serial=self.get_chassis_service_tag()
|
|
||||||
)
|
|
||||||
if not chassis:
|
|
||||||
chassis = self._netbox_create_blade_chassis(datacenter, rack)
|
|
||||||
|
|
||||||
blade = self._netbox_create_blade(chassis, datacenter, rack)
|
if config.purge_old_devices:
|
||||||
|
self._netbox_deduplicate_server()
|
||||||
|
|
||||||
|
if self.is_blade():
|
||||||
|
chassis = nb.dcim.devices.get(serial=self.get_chassis_service_tag())
|
||||||
|
# Chassis does not exist
|
||||||
|
if not chassis:
|
||||||
|
chassis = self._netbox_create_chassis(datacenter, tenant, rack)
|
||||||
|
|
||||||
|
server = nb.dcim.devices.get(serial=self.get_service_tag())
|
||||||
|
if not server:
|
||||||
|
server = self._netbox_create_blade(chassis, datacenter, tenant, rack)
|
||||||
|
|
||||||
# Set slot for blade
|
# Set slot for blade
|
||||||
self._netbox_set_blade_slot(chassis, blade)
|
self._netbox_set_or_update_blade_slot(server, chassis, datacenter)
|
||||||
else:
|
else:
|
||||||
server = nb.dcim.devices.get(serial=self.get_service_tag())
|
server = nb.dcim.devices.get(serial=self.get_service_tag())
|
||||||
if not server:
|
if not server:
|
||||||
self._netbox_create_server(datacenter, rack)
|
server = self._netbox_create_server(datacenter, tenant, rack)
|
||||||
|
|
||||||
self.network = Network(server=self)
|
logging.debug("Updating Server...")
|
||||||
self.network.create_netbox_network_cards()
|
# check network cards
|
||||||
|
if config.register or config.update_all or config.update_network:
|
||||||
self.power = PowerSupply(server=self)
|
self.network = ServerNetwork(server=self)
|
||||||
self.power.create_or_update_power_supply()
|
self.network.create_or_update_netbox_network_cards()
|
||||||
|
update_inventory = config.inventory and (
|
||||||
if config.inventory:
|
config.register or config.update_all or config.update_inventory
|
||||||
self.inventory = Inventory(server=self)
|
|
||||||
self.inventory.create()
|
|
||||||
logging.debug('Server created!')
|
|
||||||
|
|
||||||
def _netbox_update_chassis_for_blade(self, server, datacenter):
|
|
||||||
chassis = server.parent_device.device_bay.device
|
|
||||||
device_bay = nb.dcim.device_bays.get(
|
|
||||||
server.parent_device.device_bay.id
|
|
||||||
)
|
)
|
||||||
netbox_chassis_serial = server.parent_device.device_bay.device.serial
|
# update inventory if feature is enabled
|
||||||
move_device_bay = False
|
self.inventory = Inventory(server=self)
|
||||||
|
if update_inventory:
|
||||||
|
self.inventory.create_or_update()
|
||||||
|
# update psu
|
||||||
|
if config.register or config.update_all or config.update_psu:
|
||||||
|
self.power = PowerSupply(server=self)
|
||||||
|
self.power.create_or_update_power_supply()
|
||||||
|
self.power.report_power_consumption()
|
||||||
|
|
||||||
# check chassis serial with dmidecode
|
expansion = nb.dcim.devices.get(serial=self.get_expansion_service_tag())
|
||||||
if netbox_chassis_serial != self.get_chassis_service_tag():
|
if self.own_expansion_slot() and config.expansion_as_device:
|
||||||
move_device_bay = True
|
logging.debug("Update Server expansion...")
|
||||||
# try to find the new netbox chassis
|
if not expansion:
|
||||||
chassis = nb.dcim.devices.get(
|
expansion = self._netbox_create_blade_expansion(
|
||||||
serial=self.get_chassis_service_tag()
|
chassis, datacenter, tenant, rack
|
||||||
)
|
|
||||||
if not chassis:
|
|
||||||
chassis = self._netbox_create_blade_chassis(datacenter)
|
|
||||||
if move_device_bay or device_bay.name != self.get_blade_slot():
|
|
||||||
logging.info('Device ({serial}) seems to have moved, reseting old slot..'.format(
|
|
||||||
serial=server.serial))
|
|
||||||
device_bay.installed_device = None
|
|
||||||
device_bay.save()
|
|
||||||
|
|
||||||
# Set slot for blade
|
|
||||||
self._netbox_set_blade_slot(chassis, server)
|
|
||||||
|
|
||||||
def netbox_update(self, config):
|
|
||||||
"""
|
|
||||||
Netbox method to update info about our server/blade
|
|
||||||
|
|
||||||
Handle:
|
|
||||||
* new chasis for a blade
|
|
||||||
* new slot for a bblade
|
|
||||||
* hostname update
|
|
||||||
* new network infos
|
|
||||||
"""
|
|
||||||
logging.debug('Updating Server...')
|
|
||||||
|
|
||||||
server = nb.dcim.devices.get(serial=self.get_service_tag())
|
|
||||||
if not server:
|
|
||||||
raise Exception("The server (Serial: {}) isn't yet registered in Netbox, register"
|
|
||||||
'it before updating it'.format(self.get_service_tag()))
|
|
||||||
update = 0
|
|
||||||
if self.is_blade():
|
|
||||||
datacenter = self.get_netbox_datacenter()
|
|
||||||
# if it's already linked to a chassis
|
|
||||||
if server.parent_device:
|
|
||||||
self._netbox_update_chassis_for_blade(server, datacenter)
|
|
||||||
else:
|
|
||||||
logging.info('Blade is not in a chassis, fixing...')
|
|
||||||
chassis = nb.dcim.devices.get(
|
|
||||||
serial=self.get_chassis_service_tag()
|
|
||||||
)
|
)
|
||||||
if not chassis:
|
|
||||||
chassis = self._netbox_create_blade_chassis(datacenter)
|
|
||||||
# Set slot for blade
|
|
||||||
self._netbox_set_blade_slot(chassis, server)
|
|
||||||
|
|
||||||
|
# set slot for blade expansion
|
||||||
|
self._netbox_set_or_update_blade_expansion_slot(
|
||||||
|
expansion, chassis, datacenter
|
||||||
|
)
|
||||||
|
if update_inventory:
|
||||||
|
# Updates expansion inventory
|
||||||
|
inventory = Inventory(server=self, update_expansion=True)
|
||||||
|
inventory.create_or_update()
|
||||||
|
elif self.own_expansion_slot() and expansion:
|
||||||
|
expansion.delete()
|
||||||
|
expansion = None
|
||||||
|
|
||||||
|
update = 0
|
||||||
# for every other specs
|
# for every other specs
|
||||||
# check hostname
|
# check hostname
|
||||||
if server.name != self.get_hostname():
|
if server.name != self.get_hostname():
|
||||||
update += 1
|
|
||||||
server.name = self.get_hostname()
|
server.name = self.get_hostname()
|
||||||
|
update += 1
|
||||||
|
|
||||||
|
server_tags = sorted(set([x.name for x in server.tags]))
|
||||||
|
tags = sorted(set(self.tags))
|
||||||
|
if server_tags != tags:
|
||||||
|
new_tags_ids = [x.id for x in self.nb_tags]
|
||||||
|
if not config.preserve_tags:
|
||||||
|
server.tags = new_tags_ids
|
||||||
|
else:
|
||||||
|
server_tags_ids = [x.id for x in server.tags]
|
||||||
|
server.tags = sorted(set(new_tags_ids + server_tags_ids))
|
||||||
|
update += 1
|
||||||
|
|
||||||
|
if server.custom_fields != self.custom_fields:
|
||||||
|
server.custom_fields = self.custom_fields
|
||||||
|
update += 1
|
||||||
|
|
||||||
if config.update_all or config.update_location:
|
if config.update_all or config.update_location:
|
||||||
ret, server = self.update_netbox_location(server)
|
ret, server = self.update_netbox_location(server)
|
||||||
update += ret
|
update += ret
|
||||||
|
|
||||||
# check network cards
|
if server.platform != self.device_platform:
|
||||||
if config.update_all or config.update_network:
|
server.platform = self.device_platform
|
||||||
self.network = Network(server=self)
|
update += 1
|
||||||
self.network.update_netbox_network_cards()
|
|
||||||
# update inventory
|
|
||||||
if config.update_all or config.update_inventory:
|
|
||||||
self.inventory = Inventory(server=self)
|
|
||||||
self.inventory.update()
|
|
||||||
# update psu
|
|
||||||
if config.update_all or config.update_psu:
|
|
||||||
self.power = PowerSupply(server=self)
|
|
||||||
self.power.create_or_update_power_supply()
|
|
||||||
self.power.report_power_consumption()
|
|
||||||
if update:
|
if update:
|
||||||
server.save()
|
server.save()
|
||||||
logging.debug('Finished updating Server!')
|
|
||||||
|
if expansion:
|
||||||
|
update = 0
|
||||||
|
expansion_name = server.name + " expansion"
|
||||||
|
if expansion.name != expansion_name:
|
||||||
|
expansion.name = expansion_name
|
||||||
|
update += 1
|
||||||
|
if self.update_netbox_expansion_location(server, expansion):
|
||||||
|
update += 1
|
||||||
|
if update:
|
||||||
|
expansion.save()
|
||||||
|
logging.debug("Finished updating Server!")
|
||||||
|
|
||||||
def print_debug(self):
|
def print_debug(self):
|
||||||
self.network = Network(server=self)
|
self.network = ServerNetwork(server=self)
|
||||||
print('Datacenter:', self.get_datacenter())
|
print("Datacenter:", self.get_datacenter())
|
||||||
print('Netbox Datacenter:', self.get_netbox_datacenter())
|
print("Netbox Datacenter:", self.get_netbox_datacenter())
|
||||||
print('Rack:', self.get_rack())
|
print("Rack:", self.get_rack())
|
||||||
print('Netbox Rack:', self.get_netbox_rack())
|
print("Netbox Rack:", self.get_netbox_rack())
|
||||||
print('Is blade:', self.is_blade())
|
print("Is blade:", self.is_blade())
|
||||||
print('Product Name:', self.get_product_name())
|
print("Got expansion:", self.own_expansion_slot())
|
||||||
print('Chassis:', self.get_chassis())
|
print("Product Name:", self.get_product_name())
|
||||||
print('Chassis service tag:', self.get_chassis_service_tag())
|
print("Platform:", self.device_platform)
|
||||||
print('Service tag:', self.get_service_tag())
|
print("Chassis:", self.get_chassis())
|
||||||
print('NIC:',)
|
print("Chassis service tag:", self.get_chassis_service_tag())
|
||||||
|
print("Service tag:", self.get_service_tag())
|
||||||
|
print(
|
||||||
|
"NIC:",
|
||||||
|
)
|
||||||
pprint(self.network.get_network_cards())
|
pprint(self.network.get_network_cards())
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def own_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Indicates if the device hosts an expansion card
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
|
def own_gpu_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Indicates if the device hosts a GPU expansion card
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
|
def own_drive_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Indicates if the device hosts a drive expansion bay
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
49
netbox_agent/vendors/dell.py
vendored
49
netbox_agent/vendors/dell.py
vendored
|
@ -1,17 +1,17 @@
|
||||||
import logging
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from netbox_agent.server import ServerBase
|
|
||||||
from netbox_agent.misc import is_tool
|
from netbox_agent.misc import is_tool
|
||||||
|
from netbox_agent.server import ServerBase
|
||||||
|
|
||||||
|
|
||||||
class DellHost(ServerBase):
|
class DellHost(ServerBase):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(DellHost, self).__init__(*args, **kwargs)
|
super(DellHost, self).__init__(*args, **kwargs)
|
||||||
self.manufacturer = 'Dell'
|
self.manufacturer = "Dell"
|
||||||
|
|
||||||
def is_blade(self):
|
def is_blade(self):
|
||||||
return self.get_product_name().startswith('PowerEdge M')
|
return self.get_product_name().startswith("PowerEdge M")
|
||||||
|
|
||||||
def get_blade_slot(self):
|
def get_blade_slot(self):
|
||||||
"""
|
"""
|
||||||
|
@ -20,50 +20,69 @@ class DellHost(ServerBase):
|
||||||
` Location In Chassis: Slot 03`
|
` Location In Chassis: Slot 03`
|
||||||
"""
|
"""
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return self.dmi.get_by_type('Baseboard')[0].get('Location In Chassis').strip()
|
return self.baseboard[0].get("Location In Chassis").strip()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_chassis_name(self):
|
def get_chassis_name(self):
|
||||||
if not self.is_blade():
|
if not self.is_blade():
|
||||||
return None
|
return None
|
||||||
return 'Chassis {}'.format(self.get_service_tag())
|
return "Chassis {}".format(self.get_service_tag())
|
||||||
|
|
||||||
def get_chassis(self):
|
def get_chassis(self):
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return self.dmi.get_by_type('Chassis')[0]['Version'].strip()
|
return self.chassis[0]["Version"].strip()
|
||||||
return self.get_product_name()
|
return self.get_product_name()
|
||||||
|
|
||||||
def get_chassis_service_tag(self):
|
def get_chassis_service_tag(self):
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return self.dmi.get_by_type('Chassis')[0]['Serial Number'].strip()
|
return self.chassis[0]["Serial Number"].strip()
|
||||||
return self.get_service_tag()
|
return self.get_service_tag()
|
||||||
|
|
||||||
def get_power_consumption(self):
|
def get_power_consumption(self):
|
||||||
'''
|
"""
|
||||||
Parse omreport output like this
|
Parse omreport output like this
|
||||||
|
|
||||||
Amperage
|
Amperage
|
||||||
PS1 Current 1 : 1.8 A
|
PS1 Current 1 : 1.8 A
|
||||||
PS2 Current 2 : 1.4 A
|
PS2 Current 2 : 1.4 A
|
||||||
'''
|
"""
|
||||||
value = []
|
value = []
|
||||||
|
|
||||||
if not is_tool('omreport'):
|
if not is_tool("omreport"):
|
||||||
logging.error('omreport does not seem to be installed, please debug')
|
logging.error("omreport does not seem to be installed, please debug")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
data = subprocess.getoutput('omreport chassis pwrmonitoring')
|
data = subprocess.getoutput("omreport chassis pwrmonitoring")
|
||||||
amperage = False
|
amperage = False
|
||||||
for line in data.splitlines():
|
for line in data.splitlines():
|
||||||
if line.startswith('Amperage'):
|
if line.startswith("Amperage"):
|
||||||
amperage = True
|
amperage = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if amperage:
|
if amperage:
|
||||||
if line.startswith('PS'):
|
if line.startswith("PS"):
|
||||||
amp_value = line.split(':')[1].split()[0]
|
amp_value = line.split(":")[1].split()[0]
|
||||||
value.append(amp_value)
|
value.append(amp_value)
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def get_expansion_product(self):
|
||||||
|
"""
|
||||||
|
Get the extension slot that is on a pair slot number
|
||||||
|
next to the compute slot that is on an odd slot number
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def is_expansion_slot(self, server):
|
||||||
|
"""
|
||||||
|
Return True if its an extension slot
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_blade_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Expansion slot are always the compute bay number + 1
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
25
netbox_agent/vendors/generic.py
vendored
Normal file
25
netbox_agent/vendors/generic.py
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import netbox_agent.dmidecode as dmidecode
|
||||||
|
from netbox_agent.server import ServerBase
|
||||||
|
|
||||||
|
|
||||||
|
class GenericHost(ServerBase):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(GenericHost, self).__init__(*args, **kwargs)
|
||||||
|
self.manufacturer = dmidecode.get_by_type(self.dmi, "Baseboard")[0].get(
|
||||||
|
"Manufacturer"
|
||||||
|
)
|
||||||
|
|
||||||
|
def is_blade(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_blade_slot(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_chassis_name(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_chassis(self):
|
||||||
|
return self.get_product_name()
|
||||||
|
|
||||||
|
def get_chassis_service_tag(self):
|
||||||
|
return self.get_service_tag()
|
106
netbox_agent/vendors/hp.py
vendored
106
netbox_agent/vendors/hp.py
vendored
|
@ -1,15 +1,22 @@
|
||||||
|
import netbox_agent.dmidecode as dmidecode
|
||||||
|
from netbox_agent.inventory import Inventory
|
||||||
from netbox_agent.server import ServerBase
|
from netbox_agent.server import ServerBase
|
||||||
|
|
||||||
|
|
||||||
class HPHost(ServerBase):
|
class HPHost(ServerBase):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(HPHost, self).__init__(*args, **kwargs)
|
super(HPHost, self).__init__(*args, **kwargs)
|
||||||
|
self.manufacturer = "HP"
|
||||||
|
self.product = self.get_product_name()
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
self.hp_rack_locator = self._find_rack_locator()
|
self.hp_rack_locator = self._find_rack_locator()
|
||||||
self.manufacturer = 'HP'
|
|
||||||
|
|
||||||
def is_blade(self):
|
def is_blade(self):
|
||||||
return self.get_product_name().startswith('ProLiant BL')
|
blade = self.product.startswith("ProLiant BL")
|
||||||
|
blade |= self.product.startswith("ProLiant m") and self.product.endswith(
|
||||||
|
"Server Cartridge"
|
||||||
|
)
|
||||||
|
return blade
|
||||||
|
|
||||||
def _find_rack_locator(self):
|
def _find_rack_locator(self):
|
||||||
"""
|
"""
|
||||||
|
@ -19,35 +26,102 @@ class HPHost(ServerBase):
|
||||||
"""
|
"""
|
||||||
# FIXME: make a dmidecode function get_by_dminame() ?
|
# FIXME: make a dmidecode function get_by_dminame() ?
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
locator = self.dmi.get_by_type(204)
|
locator = dmidecode.get_by_type(self.dmi, 204)
|
||||||
if self.get_product_name() == 'ProLiant BL460c Gen10':
|
if self.product.startswith("ProLiant BL460c Gen10"):
|
||||||
locator = locator[0]['Strings']
|
locator = locator[0]["Strings"]
|
||||||
return {
|
return {
|
||||||
'Enclosure Model': locator[2].strip(),
|
"Enclosure Model": locator[2].strip(),
|
||||||
'Enclosure Name': locator[0].strip(),
|
"Enclosure Name": locator[0].strip(),
|
||||||
'Server Bay': locator[3].strip(),
|
"Server Bay": locator[3].strip(),
|
||||||
'Enclosure Serial': locator[4].strip(),
|
"Enclosure Serial": locator[4].strip(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# HP ProLiant m750, m710x, m510 Server Cartridge
|
||||||
|
if self.product.startswith("ProLiant m") and self.product.endswith(
|
||||||
|
"Server Cartridge"
|
||||||
|
):
|
||||||
|
locator = dmidecode.get_by_type(self.dmi, 2)
|
||||||
|
chassis = dmidecode.get_by_type(self.dmi, 3)
|
||||||
|
return {
|
||||||
|
"Enclosure Model": "Moonshot 1500 Chassis",
|
||||||
|
"Enclosure Name": "Unknown",
|
||||||
|
"Server Bay": locator[0]["Location In Chassis"].strip(),
|
||||||
|
"Enclosure Serial": chassis[0]["Serial Number"].strip(),
|
||||||
|
}
|
||||||
|
|
||||||
return locator[0]
|
return locator[0]
|
||||||
|
|
||||||
def get_blade_slot(self):
|
def get_blade_slot(self):
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return 'Bay {}'.format(
|
return "Bay {}".format(str(self.hp_rack_locator["Server Bay"].strip()))
|
||||||
int(self.hp_rack_locator['Server Bay'].strip())
|
|
||||||
)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_chassis(self):
|
def get_chassis(self):
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return self.hp_rack_locator['Enclosure Model'].strip()
|
return self.hp_rack_locator["Enclosure Model"].strip()
|
||||||
return self.get_product_name()
|
return self.get_product_name()
|
||||||
|
|
||||||
def get_chassis_name(self):
|
def get_chassis_name(self):
|
||||||
if not self.is_blade():
|
if not self.is_blade():
|
||||||
return None
|
return None
|
||||||
return self.hp_rack_locator['Enclosure Name'].strip()
|
return self.hp_rack_locator["Enclosure Name"].strip()
|
||||||
|
|
||||||
def get_chassis_service_tag(self):
|
def get_chassis_service_tag(self):
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return self.hp_rack_locator['Enclosure Serial'].strip()
|
return self.hp_rack_locator["Enclosure Serial"].strip()
|
||||||
return self.get_service_tag()
|
return self.get_service_tag()
|
||||||
|
|
||||||
|
def get_blade_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Expansion slot are always the compute bay number + 1
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
self.is_blade()
|
||||||
|
and self.own_gpu_expansion_slot()
|
||||||
|
or self.own_disk_expansion_slot()
|
||||||
|
or True
|
||||||
|
):
|
||||||
|
return "Bay {}".format(
|
||||||
|
str(int(self.hp_rack_locator["Server Bay"].strip()) + 1)
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_expansion_product(self):
|
||||||
|
"""
|
||||||
|
Get the extension slot that is on a pair slot number
|
||||||
|
next to the compute slot that is on an odd slot number
|
||||||
|
I only know on model of slot GPU extension card that.
|
||||||
|
"""
|
||||||
|
if self.own_gpu_expansion_slot():
|
||||||
|
return "ProLiant BL460c Graphics Expansion Blade"
|
||||||
|
elif self.own_disk_expansion_slot():
|
||||||
|
return "ProLiant BL460c Disk Expansion Blade"
|
||||||
|
return None
|
||||||
|
|
||||||
|
def own_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Indicates if the device hosts an expension card
|
||||||
|
"""
|
||||||
|
return self.own_gpu_expansion_slot() or self.own_disk_expansion_slot()
|
||||||
|
|
||||||
|
def own_gpu_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Indicates if the device hosts a GPU expansion card based
|
||||||
|
on the product name
|
||||||
|
"""
|
||||||
|
return self.get_product_name().endswith("Graphics Exp")
|
||||||
|
|
||||||
|
def own_disk_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Indicates if the device hosts a drive expansion card based
|
||||||
|
on raid card attributes.
|
||||||
|
"""
|
||||||
|
# Uses already parsed inventory if available
|
||||||
|
# parses it otherwise
|
||||||
|
inventory = getattr(self, "inventory", None)
|
||||||
|
if inventory is None:
|
||||||
|
inventory = Inventory(self)
|
||||||
|
for raid_card in inventory.get_raid_cards():
|
||||||
|
if self.is_blade() and raid_card.is_external():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
14
netbox_agent/vendors/qct.py
vendored
14
netbox_agent/vendors/qct.py
vendored
|
@ -4,29 +4,29 @@ from netbox_agent.server import ServerBase
|
||||||
class QCTHost(ServerBase):
|
class QCTHost(ServerBase):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(QCTHost, self).__init__(*args, **kwargs)
|
super(QCTHost, self).__init__(*args, **kwargs)
|
||||||
self.manufacturer = 'QCT'
|
self.manufacturer = "QCT"
|
||||||
|
|
||||||
def is_blade(self):
|
def is_blade(self):
|
||||||
return 'Location In Chassis' in self.dmi.get_by_type('Baseboard')[0].keys()
|
return "Location In Chassis" in self.baseboard[0].keys()
|
||||||
|
|
||||||
def get_blade_slot(self):
|
def get_blade_slot(self):
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return 'Slot {}'.format(
|
return "Slot {}".format(
|
||||||
self.dmi.get_by_type('Baseboard')[0].get('Location In Chassis').strip()
|
self.baseboard[0].get("Location In Chassis").strip()
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_chassis_name(self):
|
def get_chassis_name(self):
|
||||||
if not self.is_blade():
|
if not self.is_blade():
|
||||||
return None
|
return None
|
||||||
return 'Chassis {}'.format(self.get_service_tag())
|
return "Chassis {}".format(self.get_service_tag())
|
||||||
|
|
||||||
def get_chassis(self):
|
def get_chassis(self):
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return self.dmi.get_by_type('Chassis')[0]['Version'].strip()
|
return self.chassis[0]["Version"].strip()
|
||||||
return self.get_product_name()
|
return self.get_product_name()
|
||||||
|
|
||||||
def get_chassis_service_tag(self):
|
def get_chassis_service_tag(self):
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return self.dmi.get_by_type('Chassis')[0]['Serial Number'].strip()
|
return self.chassis[0]["Serial Number"].strip()
|
||||||
return self.get_service_tag()
|
return self.get_service_tag()
|
||||||
|
|
66
netbox_agent/vendors/supermicro.py
vendored
66
netbox_agent/vendors/supermicro.py
vendored
|
@ -1,29 +1,39 @@
|
||||||
|
|
||||||
from netbox_agent.location import Slot
|
from netbox_agent.location import Slot
|
||||||
from netbox_agent.server import ServerBase
|
from netbox_agent.server import ServerBase
|
||||||
|
|
||||||
"""
|
|
||||||
Supermicro DMI can be messed up. They depend on the vendor
|
|
||||||
to set the correct values. The endusers cannot
|
|
||||||
change them without buying a license from Supermicro.
|
|
||||||
|
|
||||||
There are 3 serial numbers in the system
|
|
||||||
|
|
||||||
1) System - this is used for the chassis information.
|
|
||||||
2) Baseboard - this is used for the blade.
|
|
||||||
3) Chassis - this is ignored.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class SupermicroHost(ServerBase):
|
class SupermicroHost(ServerBase):
|
||||||
|
"""
|
||||||
|
Supermicro DMI can be messed up. They depend on the vendor
|
||||||
|
to set the correct values. The endusers cannot
|
||||||
|
change them without buying a license from Supermicro.
|
||||||
|
|
||||||
|
There are 3 serial numbers in the system
|
||||||
|
|
||||||
|
1) System - this is used for the chassis information.
|
||||||
|
2) Baseboard - this is used for the blade.
|
||||||
|
3) Chassis - this is ignored.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(SupermicroHost, self).__init__(*args, **kwargs)
|
super(SupermicroHost, self).__init__(*args, **kwargs)
|
||||||
self.manufacturer = 'Supermicro'
|
self.manufacturer = "Supermicro"
|
||||||
|
|
||||||
def is_blade(self):
|
def is_blade(self):
|
||||||
blade = self.system[0]['Product Name'].startswith('SBI')
|
product_name = self.system[0]["Product Name"].strip()
|
||||||
blade |= self.system[0]['Product Name'].startswith('SYS')
|
# Blades
|
||||||
|
blade = product_name.startswith("SBI")
|
||||||
|
blade |= product_name.startswith("SBA")
|
||||||
|
# Twin
|
||||||
|
blade |= "TR-" in product_name
|
||||||
|
# TwinPro
|
||||||
|
blade |= "TP-" in product_name
|
||||||
|
# BigTwin
|
||||||
|
blade |= "BT-" in product_name
|
||||||
|
# Microcloud
|
||||||
|
blade |= product_name.startswith("SYS-5039")
|
||||||
|
blade |= product_name.startswith("SYS-5038")
|
||||||
return blade
|
return blade
|
||||||
|
|
||||||
def get_blade_slot(self):
|
def get_blade_slot(self):
|
||||||
|
@ -36,24 +46,34 @@ class SupermicroHost(ServerBase):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_service_tag(self):
|
def get_service_tag(self):
|
||||||
return self.baseboard[0]['Serial Number'].strip()
|
if self.is_blade():
|
||||||
|
return self.baseboard[0]["Serial Number"].strip()
|
||||||
|
return self.system[0]["Serial Number"].strip()
|
||||||
|
|
||||||
def get_product_name(self):
|
def get_product_name(self):
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return self.baseboard[0]['Product Name'].strip()
|
return self.baseboard[0]["Product Name"].strip()
|
||||||
return self.system[0]['Product Name'].strip()
|
return self.system[0]["Product Name"].strip()
|
||||||
|
|
||||||
def get_chassis(self):
|
def get_chassis(self):
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return self.system[0]['Product Name'].strip()
|
return self.system[0]["Product Name"].strip()
|
||||||
return self.get_product_name()
|
return self.get_product_name()
|
||||||
|
|
||||||
def get_chassis_service_tag(self):
|
def get_chassis_service_tag(self):
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return self.system[0]['Serial Number'].strip()
|
return self.system[0]["Serial Number"].strip()
|
||||||
return self.get_service_tag()
|
return self.get_service_tag()
|
||||||
|
|
||||||
def get_chassis_name(self):
|
def get_chassis_name(self):
|
||||||
if not self.is_blade():
|
if not self.is_blade():
|
||||||
return None
|
return None
|
||||||
return 'Chassis {}'.format(self.get_chassis_service_tag())
|
return "Chassis {}".format(self.get_chassis_service_tag())
|
||||||
|
|
||||||
|
def get_expansion_product(self):
|
||||||
|
"""
|
||||||
|
Get the extension slot that is on a pair slot number
|
||||||
|
next to the compute slot that is on an odd slot number
|
||||||
|
I only know on model of slot GPU extension card that.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
151
netbox_agent/virtualmachine.py
Normal file
151
netbox_agent/virtualmachine.py
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
import os
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
import netbox_agent.dmidecode as dmidecode
|
||||||
|
from netbox_agent.config import config
|
||||||
|
from netbox_agent.config import netbox_instance as nb
|
||||||
|
from netbox_agent.location import Tenant
|
||||||
|
from netbox_agent.logging import logging # NOQA
|
||||||
|
from netbox_agent.misc import create_netbox_tags, get_device_platform, get_hostname
|
||||||
|
from netbox_agent.network import VirtualNetwork
|
||||||
|
|
||||||
|
|
||||||
|
def is_vm(dmi):
|
||||||
|
bios = dmidecode.get_by_type(dmi, "BIOS")[0]
|
||||||
|
system = dmidecode.get_by_type(dmi, "System")[0]
|
||||||
|
|
||||||
|
return (
|
||||||
|
"Hyper-V" in bios["Version"]
|
||||||
|
or "Xen" in bios["Version"]
|
||||||
|
or "Google Compute Engine" in system["Product Name"]
|
||||||
|
) or (
|
||||||
|
(
|
||||||
|
"Amazon EC2" in system["Manufacturer"]
|
||||||
|
and not system["Product Name"].endswith(".metal")
|
||||||
|
)
|
||||||
|
or "RHEV Hypervisor" in system["Product Name"]
|
||||||
|
or "QEMU" in system["Manufacturer"]
|
||||||
|
or "VirtualBox" in bios["Version"]
|
||||||
|
or "VMware" in system["Manufacturer"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class VirtualMachine(object):
|
||||||
|
def __init__(self, dmi=None):
|
||||||
|
if dmi:
|
||||||
|
self.dmi = dmi
|
||||||
|
else:
|
||||||
|
self.dmi = dmidecode.parse()
|
||||||
|
self.network = None
|
||||||
|
self.device_platform = get_device_platform(config.device.platform)
|
||||||
|
|
||||||
|
self.tags = (
|
||||||
|
list(set(config.device.tags.split(","))) if config.device.tags else []
|
||||||
|
)
|
||||||
|
self.nb_tags = create_netbox_tags(self.tags)
|
||||||
|
|
||||||
|
def get_memory(self):
|
||||||
|
mem_bytes = os.sysconf("SC_PAGE_SIZE") * os.sysconf(
|
||||||
|
"SC_PHYS_PAGES"
|
||||||
|
) # e.g. 4015976448
|
||||||
|
mem_gib = mem_bytes / (1024.0**2) # e.g. 3.74
|
||||||
|
return int(mem_gib)
|
||||||
|
|
||||||
|
def get_vcpus(self):
|
||||||
|
return os.cpu_count()
|
||||||
|
|
||||||
|
def get_netbox_vm(self):
|
||||||
|
hostname = get_hostname(config)
|
||||||
|
vm = nb.virtualization.virtual_machines.get(name=hostname)
|
||||||
|
return vm
|
||||||
|
|
||||||
|
def get_netbox_cluster(self, name):
|
||||||
|
cluster = nb.virtualization.clusters.get(
|
||||||
|
name=name,
|
||||||
|
)
|
||||||
|
return cluster
|
||||||
|
|
||||||
|
def get_netbox_datacenter(self, name):
|
||||||
|
cluster = self.get_netbox_cluster()
|
||||||
|
if cluster.datacenter:
|
||||||
|
return cluster.datacenter
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_tenant(self):
|
||||||
|
tenant = Tenant()
|
||||||
|
return tenant.get()
|
||||||
|
|
||||||
|
def get_netbox_tenant(self):
|
||||||
|
tenant = self.get_tenant()
|
||||||
|
if tenant is None:
|
||||||
|
return None
|
||||||
|
nb_tenant = nb.tenancy.tenants.get(slug=self.get_tenant())
|
||||||
|
return nb_tenant
|
||||||
|
|
||||||
|
def netbox_create_or_update(self, config):
|
||||||
|
logging.debug("It's a virtual machine")
|
||||||
|
created = False
|
||||||
|
updated = 0
|
||||||
|
|
||||||
|
hostname = get_hostname(config)
|
||||||
|
vm = self.get_netbox_vm()
|
||||||
|
|
||||||
|
vcpus = self.get_vcpus()
|
||||||
|
memory = self.get_memory()
|
||||||
|
tenant = self.get_netbox_tenant()
|
||||||
|
if not vm:
|
||||||
|
logging.debug("Creating Virtual machine..")
|
||||||
|
cluster = self.get_netbox_cluster(config.virtual.cluster_name)
|
||||||
|
|
||||||
|
vm = nb.virtualization.virtual_machines.create(
|
||||||
|
name=hostname,
|
||||||
|
cluster=cluster.id,
|
||||||
|
platform=self.device_platform.id,
|
||||||
|
vcpus=vcpus,
|
||||||
|
memory=memory,
|
||||||
|
tenant=tenant.id if tenant else None,
|
||||||
|
tags=[{"name": x} for x in self.tags],
|
||||||
|
)
|
||||||
|
created = True
|
||||||
|
|
||||||
|
self.network = VirtualNetwork(server=self)
|
||||||
|
self.network.create_or_update_netbox_network_cards()
|
||||||
|
|
||||||
|
if not created:
|
||||||
|
if vm.vcpus != vcpus:
|
||||||
|
vm.vcpus = vcpus
|
||||||
|
updated += 1
|
||||||
|
if vm.memory != memory:
|
||||||
|
vm.memory = memory
|
||||||
|
updated += 1
|
||||||
|
|
||||||
|
vm_tags = sorted(set([x.name for x in vm.tags]))
|
||||||
|
tags = sorted(set(self.tags))
|
||||||
|
if vm_tags != tags:
|
||||||
|
new_tags_ids = [x.id for x in self.nb_tags]
|
||||||
|
if not config.preserve_tags:
|
||||||
|
vm.tags = new_tags_ids
|
||||||
|
else:
|
||||||
|
vm_tags_ids = [x.id for x in vm.tags]
|
||||||
|
vm.tags = sorted(set(new_tags_ids + vm_tags_ids))
|
||||||
|
updated += 1
|
||||||
|
|
||||||
|
if vm.platform != self.device_platform:
|
||||||
|
vm.platform = self.device_platform
|
||||||
|
updated += 1
|
||||||
|
|
||||||
|
if updated:
|
||||||
|
vm.save()
|
||||||
|
|
||||||
|
def print_debug(self):
|
||||||
|
self.network = VirtualNetwork(server=self)
|
||||||
|
print("Cluster:", self.get_netbox_cluster(config.virtual.cluster_name))
|
||||||
|
print("Platform:", self.device_platform)
|
||||||
|
print("VM:", self.get_netbox_vm())
|
||||||
|
print("vCPU:", self.get_vcpus())
|
||||||
|
print("Memory:", f"{self.get_memory()} MB")
|
||||||
|
print(
|
||||||
|
"NIC:",
|
||||||
|
)
|
||||||
|
pprint(self.network.get_network_cards())
|
||||||
|
pass
|
46
nix/netifaces2.nix
Normal file
46
nix/netifaces2.nix
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
buildPythonPackage,
|
||||||
|
fetchFromGitHub,
|
||||||
|
cargo,
|
||||||
|
rustPlatform,
|
||||||
|
rustc,
|
||||||
|
typing-extensions,
|
||||||
|
}:
|
||||||
|
|
||||||
|
buildPythonPackage rec {
|
||||||
|
pname = "netifaces-2";
|
||||||
|
version = "0.0.22";
|
||||||
|
pyproject = true;
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "SamuelYvon";
|
||||||
|
repo = "netifaces-2";
|
||||||
|
rev = "V${version}";
|
||||||
|
hash = "sha256-XO3HWq8FOVzvpbK8mIBOup6hFMnhDpqOK/5bPziPZQ8=";
|
||||||
|
};
|
||||||
|
|
||||||
|
cargoDeps = rustPlatform.fetchCargoTarball {
|
||||||
|
inherit src;
|
||||||
|
name = "${pname}-${version}";
|
||||||
|
hash = "sha256-uoUa6DSBuIV3RrE7svT1TVLxPHdx8BFu/C6mbpRmor0=";
|
||||||
|
};
|
||||||
|
|
||||||
|
build-system = [
|
||||||
|
cargo
|
||||||
|
rustPlatform.cargoSetupHook
|
||||||
|
rustPlatform.maturinBuildHook
|
||||||
|
rustc
|
||||||
|
];
|
||||||
|
|
||||||
|
dependencies = [ typing-extensions ];
|
||||||
|
|
||||||
|
pythonImportsCheck = [ "netifaces" ];
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "Netifaces reborn";
|
||||||
|
homepage = "https://github.com/SamuelYvon/netifaces-2.git";
|
||||||
|
license = lib.licenses.mit;
|
||||||
|
maintainers = with lib.maintainers; [ ];
|
||||||
|
};
|
||||||
|
}
|
80
npins/default.nix
Normal file
80
npins/default.nix
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
# Generated by npins. Do not modify; will be overwritten regularly
|
||||||
|
let
|
||||||
|
data = builtins.fromJSON (builtins.readFile ./sources.json);
|
||||||
|
version = data.version;
|
||||||
|
|
||||||
|
mkSource =
|
||||||
|
spec:
|
||||||
|
assert spec ? type;
|
||||||
|
let
|
||||||
|
path =
|
||||||
|
if spec.type == "Git" then
|
||||||
|
mkGitSource spec
|
||||||
|
else if spec.type == "GitRelease" then
|
||||||
|
mkGitSource spec
|
||||||
|
else if spec.type == "PyPi" then
|
||||||
|
mkPyPiSource spec
|
||||||
|
else if spec.type == "Channel" then
|
||||||
|
mkChannelSource spec
|
||||||
|
else
|
||||||
|
builtins.throw "Unknown source type ${spec.type}";
|
||||||
|
in
|
||||||
|
spec // { outPath = path; };
|
||||||
|
|
||||||
|
mkGitSource =
|
||||||
|
{
|
||||||
|
repository,
|
||||||
|
revision,
|
||||||
|
url ? null,
|
||||||
|
hash,
|
||||||
|
branch ? null,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
assert repository ? type;
|
||||||
|
# At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository
|
||||||
|
# In the latter case, there we will always be an url to the tarball
|
||||||
|
if url != null then
|
||||||
|
(builtins.fetchTarball {
|
||||||
|
inherit url;
|
||||||
|
sha256 = hash; # FIXME: check nix version & use SRI hashes
|
||||||
|
})
|
||||||
|
else
|
||||||
|
assert repository.type == "Git";
|
||||||
|
let
|
||||||
|
urlToName =
|
||||||
|
url: rev:
|
||||||
|
let
|
||||||
|
matched = builtins.match "^.*/([^/]*)(\\.git)?$" repository.url;
|
||||||
|
|
||||||
|
short = builtins.substring 0 7 rev;
|
||||||
|
|
||||||
|
appendShort = if (builtins.match "[a-f0-9]*" rev) != null then "-${short}" else "";
|
||||||
|
in
|
||||||
|
"${if matched == null then "source" else builtins.head matched}${appendShort}";
|
||||||
|
name = urlToName repository.url revision;
|
||||||
|
in
|
||||||
|
builtins.fetchGit {
|
||||||
|
url = repository.url;
|
||||||
|
rev = revision;
|
||||||
|
inherit name;
|
||||||
|
# hash = hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
mkPyPiSource =
|
||||||
|
{ url, hash, ... }:
|
||||||
|
builtins.fetchurl {
|
||||||
|
inherit url;
|
||||||
|
sha256 = hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
mkChannelSource =
|
||||||
|
{ url, hash, ... }:
|
||||||
|
builtins.fetchTarball {
|
||||||
|
inherit url;
|
||||||
|
sha256 = hash;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
if version == 3 then
|
||||||
|
builtins.mapAttrs (_: mkSource) data.pins
|
||||||
|
else
|
||||||
|
throw "Unsupported format version ${toString version} in sources.json. Try running `npins upgrade`"
|
23
npins/sources.json
Normal file
23
npins/sources.json
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"pins": {
|
||||||
|
"git-hooks": {
|
||||||
|
"type": "Git",
|
||||||
|
"repository": {
|
||||||
|
"type": "GitHub",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "git-hooks.nix"
|
||||||
|
},
|
||||||
|
"branch": "master",
|
||||||
|
"revision": "3c3e88f0f544d6bb54329832616af7eb971b6be6",
|
||||||
|
"url": "https://github.com/cachix/git-hooks.nix/archive/3c3e88f0f544d6bb54329832616af7eb971b6be6.tar.gz",
|
||||||
|
"hash": "04pwjz423iq2nkazkys905gvsm5j39722ngavrnx42b8msr5k555"
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"type": "Channel",
|
||||||
|
"name": "nixpkgs-unstable",
|
||||||
|
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-24.11pre694416.ccc0c2126893/nixexprs.tar.xz",
|
||||||
|
"hash": "0cn1z4wzps8nfqxzr6l5mbn81adcqy2cy2ic70z13fhzicmxfsbx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": 3
|
||||||
|
}
|
2
pyproject.toml
Normal file
2
pyproject.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[tool.isort]
|
||||||
|
profile = "black"
|
|
@ -1,5 +1,8 @@
|
||||||
pynetbox==4.0.7
|
pynetbox==7.3.4
|
||||||
netaddr==0.7.19
|
netaddr==1.3.0
|
||||||
netifaces==0.10.9
|
netifaces2==0.0.22
|
||||||
pyyaml==5.1.2
|
pyyaml==6.0.1
|
||||||
jsonargparse==2.6.0
|
jsonargparse==4.32.0
|
||||||
|
python-slugify==8.0.4
|
||||||
|
packaging==23.2
|
||||||
|
distro==1.9.0
|
||||||
|
|
27
rpmenv.json
Normal file
27
rpmenv.json
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"extensions": {
|
||||||
|
"enabled": ["python_venv", "blocks"]
|
||||||
|
},
|
||||||
|
"core": {
|
||||||
|
"group": "Application/System",
|
||||||
|
"license": "Apache2",
|
||||||
|
"name": "netbox-agent",
|
||||||
|
"summary": "NetBox agent for server",
|
||||||
|
"url": "https://github.com/Solvik/netbox-agent",
|
||||||
|
"version": "0.7.0",
|
||||||
|
"requires": ["lshw"]
|
||||||
|
},
|
||||||
|
"python_venv": {
|
||||||
|
"python": "python3.6",
|
||||||
|
"requirements": ["requirements.txt"],
|
||||||
|
"name": "netbox-agent",
|
||||||
|
"path": "/opt/"
|
||||||
|
},
|
||||||
|
"blocks": {
|
||||||
|
"post": ["ln -sf /opt/netbox-agent/bin/netbox_agent /usr/bin/netbox_agent"],
|
||||||
|
"desc": [
|
||||||
|
"This project aims to create hardware automatically into Netbox based on standard tools (dmidecode, lldpd, parsing /sys/, etc).",
|
||||||
|
"The goal is to generate an existing infrastructure on Netbox and have the ability to update it regularly by executing the agent."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
16
setup.cfg
Normal file
16
setup.cfg
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[tool:pytest]
|
||||||
|
testpaths = tests
|
||||||
|
python_files = *.py
|
||||||
|
addopts = -vv --showlocals --cov-report term-missing --cov netbox_agent --no-cov-on-fail
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
ignore = E125,E129,W503,W504
|
||||||
|
exclude = .venv/,.git/,.tox/,netbox-docker/
|
||||||
|
max-line-length = 99
|
||||||
|
|
||||||
|
[isort]
|
||||||
|
line_length = 99
|
||||||
|
indent=' '
|
||||||
|
multi_line_output = 0
|
||||||
|
skip = .venv/,.git/,tests/conftest.py,ipython_config.py
|
||||||
|
known_first_party = netbox_agent,tests
|
51
setup.py
51
setup.py
|
@ -1,33 +1,38 @@
|
||||||
from setuptools import setup, find_packages
|
import os
|
||||||
|
|
||||||
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
|
|
||||||
|
def get_requirements():
|
||||||
|
reqs_path = os.path.join(os.path.dirname(__file__), "requirements.txt")
|
||||||
|
with open(reqs_path, "r") as f:
|
||||||
|
reqs = [r.strip() for r in f if r.strip()]
|
||||||
|
return reqs
|
||||||
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='netbox_agent',
|
name="netbox_agent",
|
||||||
version='0.3.1',
|
version="0.7.1",
|
||||||
description='NetBox agent for server',
|
description="NetBox agent for server",
|
||||||
long_description=open('README.md', encoding="utf-8").read(),
|
long_description=open("README.md", encoding="utf-8").read(),
|
||||||
url='https://github.com/solvik/netbox_agent',
|
long_description_content_type="text/markdown",
|
||||||
author='Solvik Blum',
|
url="https://github.com/solvik/netbox_agent",
|
||||||
author_email='solvik@solvik.fr',
|
author="Solvik Blum",
|
||||||
license='Apache2',
|
author_email="solvik@solvik.fr",
|
||||||
|
license="Apache2",
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]),
|
packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]),
|
||||||
use_scm_version=True,
|
use_scm_version=True,
|
||||||
install_requires=[
|
install_requires=get_requirements(),
|
||||||
'pynetbox==4.0.7',
|
|
||||||
'netaddr==0.7.19',
|
|
||||||
'netifaces==0.10.9',
|
|
||||||
'pyyaml==5.1.2',
|
|
||||||
'jsonargparse==2.6.0',
|
|
||||||
],
|
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
keywords=['netbox'],
|
keywords=["netbox"],
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Intended Audience :: Developers',
|
"Intended Audience :: Developers",
|
||||||
'Development Status :: 5 - Production/Stable',
|
"Development Status :: 5 - Production/Stable",
|
||||||
'Programming Language :: Python :: 3',
|
"Programming Language :: Python :: 3",
|
||||||
'Programming Language :: Python :: 3.6',
|
"Programming Language :: Python :: 3.6",
|
||||||
],
|
],
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': ['netbox_agent=netbox_agent.cli:main'],
|
"console_scripts": ["netbox_agent=netbox_agent.cli:main"],
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
1
shell.nix
Normal file
1
shell.nix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(import ./. { }).devShell
|
22
tests.sh
Executable file
22
tests.sh
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
set -x
|
||||||
|
|
||||||
|
git clone https://github.com/netbox-community/netbox-docker.git
|
||||||
|
cd netbox-docker
|
||||||
|
docker-compose pull
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://$(docker-compose port nginx 8080))" != "200" ]]
|
||||||
|
do
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
|
||||||
|
export NETBOX_AGENT__NETBOX__URL="http://$(docker-compose port nginx 8080)"
|
||||||
|
export NETBOX_AGENT__NETBOX__TOKEN=0123456789abcdef0123456789abcdef01234567
|
||||||
|
|
||||||
|
cd -
|
||||||
|
pytest
|
||||||
|
|
||||||
|
cd netbox-docker
|
||||||
|
docker-compose down
|
||||||
|
cd -
|
||||||
|
set +x
|
35
tests/conftest.py
Normal file
35
tests/conftest.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
def get_fixture_paths(path):
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
return [path]
|
||||||
|
fixture_paths = []
|
||||||
|
for p in os.listdir(path):
|
||||||
|
p = os.path.join(path, p)
|
||||||
|
if os.path.isfile(p):
|
||||||
|
fixture_paths.append(p)
|
||||||
|
return fixture_paths
|
||||||
|
|
||||||
|
|
||||||
|
def parametrize_with_fixtures(
|
||||||
|
path, base_path="tests/fixtures", argname="fixture", only_filenames=None
|
||||||
|
):
|
||||||
|
path = os.path.join(base_path, path)
|
||||||
|
fixture_paths = get_fixture_paths(path)
|
||||||
|
argvalues = []
|
||||||
|
for path in fixture_paths:
|
||||||
|
with open(path, "r") as f:
|
||||||
|
content = "".join(f.readlines())
|
||||||
|
filename = os.path.basename(path)
|
||||||
|
if only_filenames and filename not in only_filenames:
|
||||||
|
continue
|
||||||
|
param = pytest.param(content, id=filename)
|
||||||
|
argvalues.append(param)
|
||||||
|
|
||||||
|
def _decorator(test_function):
|
||||||
|
return pytest.mark.parametrize(argname, argvalues)(test_function)
|
||||||
|
|
||||||
|
return _decorator
|
868
tests/fixtures/dmidecode/Dell_DSS7500
vendored
Normal file
868
tests/fixtures/dmidecode/Dell_DSS7500
vendored
Normal file
|
@ -0,0 +1,868 @@
|
||||||
|
# dmidecode 2.12
|
||||||
|
SMBIOS 2.8 present.
|
||||||
|
57 structures occupying 3093 bytes.
|
||||||
|
Table at 0x7AF09000.
|
||||||
|
|
||||||
|
Handle 0xDA00, DMI type 218, 11 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
DA 0B 00 DA B2 00 17 20 0E 10 03
|
||||||
|
|
||||||
|
Handle 0x0000, DMI type 0, 24 bytes
|
||||||
|
BIOS Information
|
||||||
|
Vendor: Dell Inc.
|
||||||
|
Version: 2.3.4
|
||||||
|
Release Date: 11/10/2016
|
||||||
|
Address: 0xF0000
|
||||||
|
Runtime Size: 64 kB
|
||||||
|
ROM Size: 16384 kB
|
||||||
|
Characteristics:
|
||||||
|
ISA is supported
|
||||||
|
PCI is supported
|
||||||
|
PNP is supported
|
||||||
|
BIOS is upgradeable
|
||||||
|
BIOS shadowing is allowed
|
||||||
|
Boot from CD is supported
|
||||||
|
Selectable boot is supported
|
||||||
|
EDD is supported
|
||||||
|
Japanese floppy for Toshiba 1.2 MB is supported (int 13h)
|
||||||
|
5.25"/360 kB floppy services are supported (int 13h)
|
||||||
|
5.25"/1.2 MB floppy services are supported (int 13h)
|
||||||
|
3.5"/720 kB floppy services are supported (int 13h)
|
||||||
|
8042 keyboard services are supported (int 9h)
|
||||||
|
Serial services are supported (int 14h)
|
||||||
|
CGA/mono video services are supported (int 10h)
|
||||||
|
ACPI is supported
|
||||||
|
USB legacy is supported
|
||||||
|
BIOS boot specification is supported
|
||||||
|
Function key-initiated network boot is supported
|
||||||
|
Targeted content distribution is supported
|
||||||
|
UEFI is supported
|
||||||
|
BIOS Revision: 2.3
|
||||||
|
|
||||||
|
Handle 0x0100, DMI type 1, 27 bytes
|
||||||
|
System Information
|
||||||
|
Manufacturer: Dell Inc.
|
||||||
|
Product Name: DSS7500
|
||||||
|
Version: Not Specified
|
||||||
|
Serial Number: 4242-SERVICE_TAG
|
||||||
|
UUID: 4C4C4544-0048-5110-804A-C6C04F594A32
|
||||||
|
Wake-up Type: Power Switch
|
||||||
|
SKU Number: SKU=NotProvided;ModelName=DSS7500
|
||||||
|
Family: Not Specified
|
||||||
|
|
||||||
|
Handle 0x0200, DMI type 2, 8 bytes
|
||||||
|
Base Board Information
|
||||||
|
Manufacturer: Dell Inc.
|
||||||
|
Product Name: 0X89R8
|
||||||
|
Version: A04
|
||||||
|
Serial Number: 4242
|
||||||
|
|
||||||
|
Handle 0x0300, DMI type 3, 22 bytes
|
||||||
|
Chassis Information
|
||||||
|
Manufacturer: Dell Inc.
|
||||||
|
Type: Rack Mount Chassis
|
||||||
|
Lock: Present
|
||||||
|
Version: Not Specified
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Boot-up State: Safe
|
||||||
|
Power Supply State: Safe
|
||||||
|
Thermal State: Safe
|
||||||
|
Security Status: Unknown
|
||||||
|
OEM Information: 0x00000000
|
||||||
|
Height: 4 U
|
||||||
|
Number Of Power Cords: Unspecified
|
||||||
|
Contained Elements: 0
|
||||||
|
SKU Number: Not Specified
|
||||||
|
|
||||||
|
Handle 0x0400, DMI type 4, 42 bytes
|
||||||
|
Processor Information
|
||||||
|
Socket Designation: CPU1
|
||||||
|
Type: Central Processor
|
||||||
|
Family: Xeon
|
||||||
|
Manufacturer: Intel
|
||||||
|
ID: F1 06 04 00 FF FB EB BF
|
||||||
|
Signature: Type 0, Family 6, Model 79, Stepping 1
|
||||||
|
Flags:
|
||||||
|
FPU (Floating-point unit on-chip)
|
||||||
|
VME (Virtual mode extension)
|
||||||
|
DE (Debugging extension)
|
||||||
|
PSE (Page size extension)
|
||||||
|
TSC (Time stamp counter)
|
||||||
|
MSR (Model specific registers)
|
||||||
|
PAE (Physical address extension)
|
||||||
|
MCE (Machine check exception)
|
||||||
|
CX8 (CMPXCHG8 instruction supported)
|
||||||
|
APIC (On-chip APIC hardware supported)
|
||||||
|
SEP (Fast system call)
|
||||||
|
MTRR (Memory type range registers)
|
||||||
|
PGE (Page global enable)
|
||||||
|
MCA (Machine check architecture)
|
||||||
|
CMOV (Conditional move instruction supported)
|
||||||
|
PAT (Page attribute table)
|
||||||
|
PSE-36 (36-bit page size extension)
|
||||||
|
CLFSH (CLFLUSH instruction supported)
|
||||||
|
DS (Debug store)
|
||||||
|
ACPI (ACPI supported)
|
||||||
|
MMX (MMX technology supported)
|
||||||
|
FXSR (FXSAVE and FXSTOR instructions supported)
|
||||||
|
SSE (Streaming SIMD extensions)
|
||||||
|
SSE2 (Streaming SIMD extensions 2)
|
||||||
|
SS (Self-snoop)
|
||||||
|
HTT (Multi-threading)
|
||||||
|
TM (Thermal monitor supported)
|
||||||
|
PBE (Pending break enabled)
|
||||||
|
Version: Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz
|
||||||
|
Voltage: 1.3 V
|
||||||
|
External Clock: 8000 MHz
|
||||||
|
Max Speed: 4000 MHz
|
||||||
|
Current Speed: 2200 MHz
|
||||||
|
Status: Populated, Enabled
|
||||||
|
Upgrade: <OUT OF SPEC>
|
||||||
|
L1 Cache Handle: 0x0700
|
||||||
|
L2 Cache Handle: 0x0701
|
||||||
|
L3 Cache Handle: 0x0702
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Part Number: Not Specified
|
||||||
|
Core Count: 10
|
||||||
|
Core Enabled: 10
|
||||||
|
Thread Count: 10
|
||||||
|
Characteristics:
|
||||||
|
64-bit capable
|
||||||
|
Multi-Core
|
||||||
|
Hardware Thread
|
||||||
|
Execute Protection
|
||||||
|
Enhanced Virtualization
|
||||||
|
Power/Performance Control
|
||||||
|
|
||||||
|
Handle 0x0401, DMI type 4, 42 bytes
|
||||||
|
Processor Information
|
||||||
|
Socket Designation: CPU2
|
||||||
|
Type: Central Processor
|
||||||
|
Family: Xeon
|
||||||
|
Manufacturer: Intel
|
||||||
|
ID: F1 06 04 00 FF FB EB BF
|
||||||
|
Signature: Type 0, Family 6, Model 79, Stepping 1
|
||||||
|
Flags:
|
||||||
|
FPU (Floating-point unit on-chip)
|
||||||
|
VME (Virtual mode extension)
|
||||||
|
DE (Debugging extension)
|
||||||
|
PSE (Page size extension)
|
||||||
|
TSC (Time stamp counter)
|
||||||
|
MSR (Model specific registers)
|
||||||
|
PAE (Physical address extension)
|
||||||
|
MCE (Machine check exception)
|
||||||
|
CX8 (CMPXCHG8 instruction supported)
|
||||||
|
APIC (On-chip APIC hardware supported)
|
||||||
|
SEP (Fast system call)
|
||||||
|
MTRR (Memory type range registers)
|
||||||
|
PGE (Page global enable)
|
||||||
|
MCA (Machine check architecture)
|
||||||
|
CMOV (Conditional move instruction supported)
|
||||||
|
PAT (Page attribute table)
|
||||||
|
PSE-36 (36-bit page size extension)
|
||||||
|
CLFSH (CLFLUSH instruction supported)
|
||||||
|
DS (Debug store)
|
||||||
|
ACPI (ACPI supported)
|
||||||
|
MMX (MMX technology supported)
|
||||||
|
FXSR (FXSAVE and FXSTOR instructions supported)
|
||||||
|
SSE (Streaming SIMD extensions)
|
||||||
|
SSE2 (Streaming SIMD extensions 2)
|
||||||
|
SS (Self-snoop)
|
||||||
|
HTT (Multi-threading)
|
||||||
|
TM (Thermal monitor supported)
|
||||||
|
PBE (Pending break enabled)
|
||||||
|
Version: Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz
|
||||||
|
Voltage: 1.3 V
|
||||||
|
External Clock: 8000 MHz
|
||||||
|
Max Speed: 4000 MHz
|
||||||
|
Current Speed: 2200 MHz
|
||||||
|
Status: Populated, Enabled
|
||||||
|
Upgrade: <OUT OF SPEC>
|
||||||
|
L1 Cache Handle: 0x0703
|
||||||
|
L2 Cache Handle: 0x0704
|
||||||
|
L3 Cache Handle: 0x0705
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Part Number: Not Specified
|
||||||
|
Core Count: 10
|
||||||
|
Core Enabled: 10
|
||||||
|
Thread Count: 10
|
||||||
|
Characteristics:
|
||||||
|
64-bit capable
|
||||||
|
Multi-Core
|
||||||
|
Hardware Thread
|
||||||
|
Execute Protection
|
||||||
|
Enhanced Virtualization
|
||||||
|
Power/Performance Control
|
||||||
|
|
||||||
|
Handle 0x0700, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: Not Specified
|
||||||
|
Configuration: Enabled, Not Socketed, Level 1
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 640 kB
|
||||||
|
Maximum Size: 640 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Unknown
|
||||||
|
Installed SRAM Type: Unknown
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Parity
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0701, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: Not Specified
|
||||||
|
Configuration: Enabled, Not Socketed, Level 2
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 2560 kB
|
||||||
|
Maximum Size: 2560 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Unknown
|
||||||
|
Installed SRAM Type: Unknown
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0702, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: Not Specified
|
||||||
|
Configuration: Enabled, Not Socketed, Level 3
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 25600 kB
|
||||||
|
Maximum Size: 25600 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Unknown
|
||||||
|
Installed SRAM Type: Unknown
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 20-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0703, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: Not Specified
|
||||||
|
Configuration: Enabled, Not Socketed, Level 1
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 640 kB
|
||||||
|
Maximum Size: 640 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Unknown
|
||||||
|
Installed SRAM Type: Unknown
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Parity
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0704, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: Not Specified
|
||||||
|
Configuration: Enabled, Not Socketed, Level 2
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 2560 kB
|
||||||
|
Maximum Size: 2560 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Unknown
|
||||||
|
Installed SRAM Type: Unknown
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0705, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: Not Specified
|
||||||
|
Configuration: Enabled, Not Socketed, Level 3
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 25600 kB
|
||||||
|
Maximum Size: 25600 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Unknown
|
||||||
|
Installed SRAM Type: Unknown
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 20-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0800, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: Not Specified
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: Back USB port 2
|
||||||
|
External Connector Type: Access Bus (USB)
|
||||||
|
Port Type: USB
|
||||||
|
|
||||||
|
Handle 0x0801, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: Internal USB port 1
|
||||||
|
Internal Connector Type: Access Bus (USB)
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: USB
|
||||||
|
|
||||||
|
Handle 0x0802, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: Not Specified
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: Front USB port 2
|
||||||
|
External Connector Type: Access Bus (USB)
|
||||||
|
Port Type: USB
|
||||||
|
|
||||||
|
Handle 0x0803, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: Not Specified
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: Back USB port 1
|
||||||
|
External Connector Type: Access Bus (USB)
|
||||||
|
Port Type: USB
|
||||||
|
|
||||||
|
Handle 0x0804, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: Not Specified
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: Front USB port 1
|
||||||
|
External Connector Type: Access Bus (USB)
|
||||||
|
Port Type: USB
|
||||||
|
|
||||||
|
Handle 0x0805, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: Not Specified
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: Video port 1
|
||||||
|
External Connector Type: DB-15 female
|
||||||
|
Port Type: Video Port
|
||||||
|
|
||||||
|
Handle 0x0806, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: Not Specified
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: Serial port 1
|
||||||
|
External Connector Type: DB-9 male
|
||||||
|
Port Type: Serial Port 16550A Compatible
|
||||||
|
|
||||||
|
Handle 0x0900, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCIe Slot 1
|
||||||
|
Type: x8 PCI Express 3
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Long
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
|
||||||
|
Handle 0x0901, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCIe Slot 2
|
||||||
|
Type: x8 PCI Express 3 x16
|
||||||
|
Current Usage: In Use
|
||||||
|
Length: Long
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:04:00.0
|
||||||
|
|
||||||
|
Handle 0x0902, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCIe Slot 3
|
||||||
|
Type: x8 PCI Express 3
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Long
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
|
||||||
|
Handle 0x0903, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCIe Slot 4
|
||||||
|
Type: x8 PCI Express 3
|
||||||
|
Current Usage: In Use
|
||||||
|
Length: Long
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:06:00.0
|
||||||
|
|
||||||
|
Handle 0x0B00, DMI type 11, 5 bytes
|
||||||
|
OEM Strings
|
||||||
|
String 1: Dell System
|
||||||
|
String 2: 5[0000]
|
||||||
|
String 3: 1[06B6]
|
||||||
|
String 4: 7[0721]
|
||||||
|
String 5: 8[Dell Inc.]
|
||||||
|
String 6: 9[DSS7500]
|
||||||
|
String 7: 10[2.3.4]
|
||||||
|
String 8: 11[01.00.00]
|
||||||
|
String 9: 12[www.dell.com]
|
||||||
|
String 10: 14[1]
|
||||||
|
String 11: 17[8F27911A0C407F63]
|
||||||
|
String 12: 17[8F28041BFDD8E7E6]
|
||||||
|
String 13: 18[0]
|
||||||
|
String 14: 19[1]
|
||||||
|
String 15: 19[1]
|
||||||
|
|
||||||
|
Handle 0x0C00, DMI type 12, 5 bytes
|
||||||
|
System Configuration Options
|
||||||
|
Option 1: NVRAM_CLR: Clear user settable NVRAM areas and set defaults
|
||||||
|
Option 2: PWRD_EN: Close to enable password
|
||||||
|
|
||||||
|
Handle 0x0D00, DMI type 13, 22 bytes
|
||||||
|
BIOS Language Information
|
||||||
|
Language Description Format: Long
|
||||||
|
Installable Languages: 1
|
||||||
|
en|US|iso8859-1
|
||||||
|
Currently Installed Language: en|US|iso8859-1
|
||||||
|
|
||||||
|
Handle 0x1000, DMI type 16, 23 bytes
|
||||||
|
Physical Memory Array
|
||||||
|
Location: System Board Or Motherboard
|
||||||
|
Use: System Memory
|
||||||
|
Error Correction Type: Multi-bit ECC
|
||||||
|
Maximum Capacity: 1536 GB
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Number Of Devices: 12
|
||||||
|
|
||||||
|
Handle 0x1100, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x1000
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 1
|
||||||
|
Locator: A1
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: <OUT OF SPEC>
|
||||||
|
Type Detail: Synchronous Registered (Buffered)
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: 002C00B3002C
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: 00171230
|
||||||
|
Part Number: 18ASF2G72PDZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum voltage: 1.200 V
|
||||||
|
Maximum voltage: 1.200 V
|
||||||
|
Configured voltage: 1.200 V
|
||||||
|
|
||||||
|
Handle 0x1101, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x1000
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 1
|
||||||
|
Locator: A2
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: <OUT OF SPEC>
|
||||||
|
Type Detail: Synchronous Registered (Buffered)
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: 002C00B3002C
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: 00171230
|
||||||
|
Part Number: 18ASF2G72PDZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum voltage: 1.200 V
|
||||||
|
Maximum voltage: 1.200 V
|
||||||
|
Configured voltage: 1.200 V
|
||||||
|
|
||||||
|
Handle 0x1102, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x1000
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 1
|
||||||
|
Locator: A3
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: <OUT OF SPEC>
|
||||||
|
Type Detail: Synchronous Registered (Buffered)
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: 002C00B3002C
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: 00171230
|
||||||
|
Part Number: 18ASF2G72PDZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum voltage: 1.200 V
|
||||||
|
Maximum voltage: 1.200 V
|
||||||
|
Configured voltage: 1.200 V
|
||||||
|
|
||||||
|
Handle 0x1103, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x1000
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 1
|
||||||
|
Locator: A4
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: <OUT OF SPEC>
|
||||||
|
Type Detail: Synchronous Registered (Buffered)
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: 002C00B3002C
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: 00171230
|
||||||
|
Part Number: 18ASF2G72PDZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum voltage: 1.200 V
|
||||||
|
Maximum voltage: 1.200 V
|
||||||
|
Configured voltage: 1.200 V
|
||||||
|
|
||||||
|
Handle 0x1104, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x1000
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 2
|
||||||
|
Locator: A5
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: <OUT OF SPEC>
|
||||||
|
Type Detail: Synchronous Registered (Buffered)
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: 002C00B3002C
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: 00171230
|
||||||
|
Part Number: 18ASF2G72PDZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum voltage: 1.200 V
|
||||||
|
Maximum voltage: 1.200 V
|
||||||
|
Configured voltage: 1.200 V
|
||||||
|
|
||||||
|
Handle 0x1105, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x1000
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 2
|
||||||
|
Locator: A6
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: <OUT OF SPEC>
|
||||||
|
Type Detail: Synchronous Registered (Buffered)
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: 002C00B3002C
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: 00171230
|
||||||
|
Part Number: 18ASF2G72PDZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum voltage: 1.200 V
|
||||||
|
Maximum voltage: 1.200 V
|
||||||
|
Configured voltage: 1.200 V
|
||||||
|
|
||||||
|
Handle 0x1106, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x1000
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 2
|
||||||
|
Locator: A7
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: <OUT OF SPEC>
|
||||||
|
Type Detail: Synchronous Registered (Buffered)
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: 002C00B3002C
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: 00171230
|
||||||
|
Part Number: 18ASF2G72PDZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum voltage: 1.200 V
|
||||||
|
Maximum voltage: 1.200 V
|
||||||
|
Configured voltage: 1.200 V
|
||||||
|
|
||||||
|
Handle 0x1107, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x1000
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 2
|
||||||
|
Locator: A8
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: <OUT OF SPEC>
|
||||||
|
Type Detail: Synchronous Registered (Buffered)
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: 002C00B3002C
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: 00171230
|
||||||
|
Part Number: 18ASF2G72PDZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum voltage: 1.200 V
|
||||||
|
Maximum voltage: 1.200 V
|
||||||
|
Configured voltage: 1.200 V
|
||||||
|
|
||||||
|
Handle 0x1108, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x1000
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 3
|
||||||
|
Locator: B1
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: <OUT OF SPEC>
|
||||||
|
Type Detail: Synchronous Registered (Buffered)
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: 002C00B3002C
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: 00171230
|
||||||
|
Part Number: 18ASF2G72PDZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum voltage: 1.200 V
|
||||||
|
Maximum voltage: 1.200 V
|
||||||
|
Configured voltage: 1.200 V
|
||||||
|
|
||||||
|
Handle 0x1109, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x1000
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 3
|
||||||
|
Locator: B2
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: <OUT OF SPEC>
|
||||||
|
Type Detail: Synchronous Registered (Buffered)
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: 002C00B3002C
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: 00171230
|
||||||
|
Part Number: 18ASF2G72PDZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum voltage: 1.200 V
|
||||||
|
Maximum voltage: 1.200 V
|
||||||
|
Configured voltage: 1.200 V
|
||||||
|
|
||||||
|
Handle 0x110A, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x1000
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 3
|
||||||
|
Locator: B3
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: <OUT OF SPEC>
|
||||||
|
Type Detail: Synchronous Registered (Buffered)
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: 002C00B3002C
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: 00171230
|
||||||
|
Part Number: 18ASF2G72PDZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum voltage: 1.200 V
|
||||||
|
Maximum voltage: 1.200 V
|
||||||
|
Configured voltage: 1.200 V
|
||||||
|
|
||||||
|
Handle 0x110B, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x1000
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 3
|
||||||
|
Locator: B4
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: <OUT OF SPEC>
|
||||||
|
Type Detail: Synchronous Registered (Buffered)
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: 002C00B3002C
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: 00171230
|
||||||
|
Part Number: 18ASF2G72PDZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum voltage: 1.200 V
|
||||||
|
Maximum voltage: 1.200 V
|
||||||
|
Configured voltage: 1.200 V
|
||||||
|
|
||||||
|
Handle 0x1300, DMI type 19, 31 bytes
|
||||||
|
Memory Array Mapped Address
|
||||||
|
Starting Address: 0x00000000000
|
||||||
|
Ending Address: 0x0007FFFFFFF
|
||||||
|
Range Size: 2 GB
|
||||||
|
Physical Array Handle: 0x1000
|
||||||
|
Partition Width: 2
|
||||||
|
|
||||||
|
Handle 0x1301, DMI type 19, 31 bytes
|
||||||
|
Memory Array Mapped Address
|
||||||
|
Starting Address: 0x00100000000
|
||||||
|
Ending Address: 0x0307FFFFFFF
|
||||||
|
Range Size: 190 GB
|
||||||
|
Physical Array Handle: 0x1000
|
||||||
|
Partition Width: 2
|
||||||
|
|
||||||
|
Handle 0x2000, DMI type 32, 11 bytes
|
||||||
|
System Boot Information
|
||||||
|
Status: No errors detected
|
||||||
|
|
||||||
|
Handle 0x2600, DMI type 38, 18 bytes
|
||||||
|
IPMI Device Information
|
||||||
|
Interface Type: KCS (Keyboard Control Style)
|
||||||
|
Specification Version: 2.0
|
||||||
|
I2C Slave Address: 0x10
|
||||||
|
NV Storage Device: Not Present
|
||||||
|
Base Address: 0x0000000000000CA8 (I/O)
|
||||||
|
Register Spacing: 32-bit Boundaries
|
||||||
|
Interrupt Polarity: Active High
|
||||||
|
Interrupt Trigger Mode: Edge
|
||||||
|
Interrupt Number: a
|
||||||
|
|
||||||
|
Handle 0x2700, DMI type 39, 22 bytes
|
||||||
|
System Power Supply
|
||||||
|
Location: Not Specified
|
||||||
|
Name: PWR SPLY,1600W,RDNT,DELTA
|
||||||
|
Manufacturer: DELL
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Model Part Number: 0685W7A00
|
||||||
|
Revision: Not Specified
|
||||||
|
Max Power Capacity: 1600 W
|
||||||
|
Status: Present, Unknown
|
||||||
|
Type: Unknown
|
||||||
|
Input Voltage Range Switching: Unknown
|
||||||
|
Plugged: Yes
|
||||||
|
Hot Replaceable: Yes
|
||||||
|
|
||||||
|
Handle 0x2701, DMI type 39, 22 bytes
|
||||||
|
System Power Supply
|
||||||
|
Location: Not Specified
|
||||||
|
Name: PWR SPLY,1600W,RDNT,DELTA
|
||||||
|
Manufacturer: DELL
|
||||||
|
Serial Number: 4242
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Model Part Number: 0685W7A00
|
||||||
|
Revision: Not Specified
|
||||||
|
Max Power Capacity: 1600 W
|
||||||
|
Status: Present, Unknown
|
||||||
|
Type: Unknown
|
||||||
|
Input Voltage Range Switching: Unknown
|
||||||
|
Plugged: Yes
|
||||||
|
Hot Replaceable: Yes
|
||||||
|
|
||||||
|
Handle 0x2900, DMI type 41, 11 bytes
|
||||||
|
Onboard Device
|
||||||
|
Reference Designation: Embedded Video
|
||||||
|
Type: Video
|
||||||
|
Status: Enabled
|
||||||
|
Type Instance: 1
|
||||||
|
Bus Address: 0000:0b:00.0
|
||||||
|
|
||||||
|
Handle 0x2901, DMI type 41, 11 bytes
|
||||||
|
Onboard Device
|
||||||
|
Reference Designation: Embedded EHCI USB Controller 1
|
||||||
|
Type: Other
|
||||||
|
Status: Enabled
|
||||||
|
Type Instance: 1
|
||||||
|
Bus Address: 0000:00:1d.0
|
||||||
|
|
||||||
|
Handle 0x2902, DMI type 41, 11 bytes
|
||||||
|
Onboard Device
|
||||||
|
Reference Designation: Embedded EHCI USB Controller 2
|
||||||
|
Type: Other
|
||||||
|
Status: Enabled
|
||||||
|
Type Instance: 2
|
||||||
|
Bus Address: 0000:00:1a.0
|
||||||
|
|
||||||
|
Handle 0xB100, DMI type 177, 12 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
B1 0C 00 B1 00 02 00 00 00 00 00 00
|
||||||
|
|
||||||
|
Handle 0xD000, DMI type 208, 16 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
D0 10 00 D0 02 00 FE 00 B6 06 00 00 00 01 00 00
|
||||||
|
|
||||||
|
Handle 0xD200, DMI type 210, 12 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
D2 0C 00 D2 F8 02 03 03 06 80 04 05
|
||||||
|
|
||||||
|
Handle 0xD800, DMI type 216, 9 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
D8 09 00 D8 01 02 00 F0 03
|
||||||
|
Strings:
|
||||||
|
Matrox
|
||||||
|
{* Content TBD *}
|
||||||
|
|
||||||
|
Handle 0xDE00, DMI type 222, 16 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
DE 10 00 DE 00 40 FF FF 00 00 00 00 00 01 00 00
|
||||||
|
|
||||||
|
Handle 0xE100, DMI type 225, 13 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E1 0D 00 E1 01 01 00 04 00 02 01 04 00
|
||||||
|
Strings:
|
||||||
|
CPU.Socket.1
|
||||||
|
CPU.Socket.2
|
||||||
|
|
||||||
|
Handle 0xE101, DMI type 225, 53 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E1 35 01 E1 01 01 00 11 00 02 01 11 00 03 02 11
|
||||||
|
00 04 03 11 00 05 04 11 00 06 05 11 00 07 06 11
|
||||||
|
00 08 07 11 00 09 08 11 00 0A 09 11 00 0B 0A 11
|
||||||
|
00 0C 0B 11 00
|
||||||
|
Strings:
|
||||||
|
DIMM.Socket.A1
|
||||||
|
DIMM.Socket.A2
|
||||||
|
DIMM.Socket.A3
|
||||||
|
DIMM.Socket.A4
|
||||||
|
DIMM.Socket.A5
|
||||||
|
DIMM.Socket.A6
|
||||||
|
DIMM.Socket.A7
|
||||||
|
DIMM.Socket.A8
|
||||||
|
DIMM.Socket.B1
|
||||||
|
DIMM.Socket.B2
|
||||||
|
DIMM.Socket.B3
|
||||||
|
DIMM.Socket.B4
|
||||||
|
|
||||||
|
Handle 0xFEFF, DMI type 127, 4 bytes
|
||||||
|
End Of Table
|
1146
tests/fixtures/dmidecode/Dell_PowerEdge_M630
vendored
Normal file
1146
tests/fixtures/dmidecode/Dell_PowerEdge_M630
vendored
Normal file
File diff suppressed because it is too large
Load diff
1766
tests/fixtures/dmidecode/HP_BL460c_Gen10
vendored
Normal file
1766
tests/fixtures/dmidecode/HP_BL460c_Gen10
vendored
Normal file
File diff suppressed because it is too large
Load diff
1709
tests/fixtures/dmidecode/HP_BL460c_Gen9
vendored
Normal file
1709
tests/fixtures/dmidecode/HP_BL460c_Gen9
vendored
Normal file
File diff suppressed because it is too large
Load diff
1751
tests/fixtures/dmidecode/HP_DL380p_Gen8
vendored
Normal file
1751
tests/fixtures/dmidecode/HP_DL380p_Gen8
vendored
Normal file
File diff suppressed because it is too large
Load diff
1798
tests/fixtures/dmidecode/HP_ProLiant_BL460c_Gen10_Graphics_Exp
vendored
Normal file
1798
tests/fixtures/dmidecode/HP_ProLiant_BL460c_Gen10_Graphics_Exp
vendored
Normal file
File diff suppressed because it is too large
Load diff
921
tests/fixtures/dmidecode/HP_ProLiant_m710x
vendored
Normal file
921
tests/fixtures/dmidecode/HP_ProLiant_m710x
vendored
Normal file
|
@ -0,0 +1,921 @@
|
||||||
|
# dmidecode 3.1
|
||||||
|
Getting SMBIOS data from sysfs.
|
||||||
|
SMBIOS 2.8 present.
|
||||||
|
93 structures occupying 4311 bytes.
|
||||||
|
Table at 0x766AD000.
|
||||||
|
|
||||||
|
Handle 0x0000, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: L1-Cache
|
||||||
|
Configuration: Enabled, Not Socketed, Level 1
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 256 kB
|
||||||
|
Maximum Size: 256 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Synchronous
|
||||||
|
Installed SRAM Type: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0001, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: L2-Cache
|
||||||
|
Configuration: Enabled, Not Socketed, Level 2
|
||||||
|
Operational Mode: Varies With Memory Address
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 1024 kB
|
||||||
|
Maximum Size: 1024 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Synchronous
|
||||||
|
Installed SRAM Type: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 4-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0002, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: L3-Cache
|
||||||
|
Configuration: Enabled, Not Socketed, Level 3
|
||||||
|
Operational Mode: Varies With Memory Address
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 8192 kB
|
||||||
|
Maximum Size: 8192 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Synchronous
|
||||||
|
Installed SRAM Type: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 16-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0003, DMI type 4, 48 bytes
|
||||||
|
Processor Information
|
||||||
|
Socket Designation: Proc 1
|
||||||
|
Type: Central Processor
|
||||||
|
Family: Xeon
|
||||||
|
Manufacturer: Intel(R) Corporation
|
||||||
|
ID: E3 06 05 00 FF FB EB BF
|
||||||
|
Signature: Type 0, Family 6, Model 94, Stepping 3
|
||||||
|
Flags:
|
||||||
|
FPU (Floating-point unit on-chip)
|
||||||
|
VME (Virtual mode extension)
|
||||||
|
DE (Debugging extension)
|
||||||
|
PSE (Page size extension)
|
||||||
|
TSC (Time stamp counter)
|
||||||
|
MSR (Model specific registers)
|
||||||
|
PAE (Physical address extension)
|
||||||
|
MCE (Machine check exception)
|
||||||
|
CX8 (CMPXCHG8 instruction supported)
|
||||||
|
APIC (On-chip APIC hardware supported)
|
||||||
|
SEP (Fast system call)
|
||||||
|
MTRR (Memory type range registers)
|
||||||
|
PGE (Page global enable)
|
||||||
|
MCA (Machine check architecture)
|
||||||
|
CMOV (Conditional move instruction supported)
|
||||||
|
PAT (Page attribute table)
|
||||||
|
PSE-36 (36-bit page size extension)
|
||||||
|
CLFSH (CLFLUSH instruction supported)
|
||||||
|
DS (Debug store)
|
||||||
|
ACPI (ACPI supported)
|
||||||
|
MMX (MMX technology supported)
|
||||||
|
FXSR (FXSAVE and FXSTOR instructions supported)
|
||||||
|
SSE (Streaming SIMD extensions)
|
||||||
|
SSE2 (Streaming SIMD extensions 2)
|
||||||
|
SS (Self-snoop)
|
||||||
|
HTT (Multi-threading)
|
||||||
|
TM (Thermal monitor supported)
|
||||||
|
PBE (Pending break enabled)
|
||||||
|
Version: Intel(R) Xeon(R) CPU E3-1585L v5 @ 3.00GHz
|
||||||
|
Voltage: 1.0 V
|
||||||
|
External Clock: 100 MHz
|
||||||
|
Max Speed: 3700 MHz
|
||||||
|
Current Speed: 3000 MHz
|
||||||
|
Status: Populated, Enabled
|
||||||
|
Upgrade: Other
|
||||||
|
L1 Cache Handle: 0x0000
|
||||||
|
L2 Cache Handle: 0x0001
|
||||||
|
L3 Cache Handle: 0x0002
|
||||||
|
Serial Number: To Be Filled By O.E.M.
|
||||||
|
Asset Tag: To Be Filled By O.E.M.
|
||||||
|
Part Number: To Be Filled By O.E.M.
|
||||||
|
Core Count: 4
|
||||||
|
Core Enabled: 4
|
||||||
|
Thread Count: 8
|
||||||
|
Characteristics:
|
||||||
|
64-bit capable
|
||||||
|
Multi-Core
|
||||||
|
Hardware Thread
|
||||||
|
Execute Protection
|
||||||
|
Enhanced Virtualization
|
||||||
|
Power/Performance Control
|
||||||
|
|
||||||
|
Handle 0x0004, DMI type 0, 24 bytes
|
||||||
|
BIOS Information
|
||||||
|
Vendor: HP
|
||||||
|
Version: H07
|
||||||
|
Release Date: 05/23/2016
|
||||||
|
Address: 0xF0000
|
||||||
|
Runtime Size: 64 kB
|
||||||
|
ROM Size: 16 MB
|
||||||
|
Characteristics:
|
||||||
|
PCI is supported
|
||||||
|
PNP is supported
|
||||||
|
BIOS is upgradeable
|
||||||
|
BIOS shadowing is allowed
|
||||||
|
ESCD support is available
|
||||||
|
Boot from CD is supported
|
||||||
|
Selectable boot is supported
|
||||||
|
EDD is supported
|
||||||
|
5.25"/360 kB floppy services are supported (int 13h)
|
||||||
|
5.25"/1.2 MB floppy services are supported (int 13h)
|
||||||
|
3.5"/720 kB floppy services are supported (int 13h)
|
||||||
|
Print screen service is supported (int 5h)
|
||||||
|
8042 keyboard services are supported (int 9h)
|
||||||
|
Serial services are supported (int 14h)
|
||||||
|
Printer services are supported (int 17h)
|
||||||
|
CGA/mono video services are supported (int 10h)
|
||||||
|
ACPI is supported
|
||||||
|
USB legacy is supported
|
||||||
|
BIOS boot specification is supported
|
||||||
|
Function key-initiated network boot is supported
|
||||||
|
Targeted content distribution is supported
|
||||||
|
UEFI is supported
|
||||||
|
BIOS Revision: 1.0
|
||||||
|
Firmware Revision: 2.40
|
||||||
|
|
||||||
|
Handle 0x0005, DMI type 1, 27 bytes
|
||||||
|
System Information
|
||||||
|
Manufacturer: HP
|
||||||
|
Product Name: ProLiant m710x Server Cartridge
|
||||||
|
Version: Not Specified
|
||||||
|
Serial Number: CN66480BLA
|
||||||
|
UUID: CF6D6DE0-A5AB-512C-BCD4-5CF40EC490C1
|
||||||
|
Wake-up Type: Power Switch
|
||||||
|
SKU Number: 833105-B21
|
||||||
|
Family: ProLiant
|
||||||
|
|
||||||
|
Handle 0x0006, DMI type 16, 23 bytes
|
||||||
|
Physical Memory Array
|
||||||
|
Location: System Board Or Motherboard
|
||||||
|
Use: System Memory
|
||||||
|
Error Correction Type: Multi-bit ECC
|
||||||
|
Maximum Capacity: 64 GB
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Number Of Devices: 4
|
||||||
|
|
||||||
|
Handle 0x0007, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0006
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: PROC 1 DIMM 1
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: 2400 MT/s
|
||||||
|
Manufacturer: HP
|
||||||
|
Serial Number: Not Specified
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Part Number: 853289-091
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MT/s
|
||||||
|
Minimum Voltage: 1.2 V
|
||||||
|
Maximum Voltage: 1.2 V
|
||||||
|
Configured Voltage: 1.2 V
|
||||||
|
|
||||||
|
Handle 0x0008, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0006
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 1
|
||||||
|
Locator: PROC 1 DIMM 2
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: 2400 MT/s
|
||||||
|
Manufacturer: HP
|
||||||
|
Serial Number: Not Specified
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Part Number: 853289-091
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MT/s
|
||||||
|
Minimum Voltage: 1.2 V
|
||||||
|
Maximum Voltage: 1.2 V
|
||||||
|
Configured Voltage: 1.2 V
|
||||||
|
|
||||||
|
Handle 0x0009, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0006
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 2
|
||||||
|
Locator: PROC 1 DIMM 3
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: 2400 MT/s
|
||||||
|
Manufacturer: HP
|
||||||
|
Serial Number: Not Specified
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Part Number: 853289-091
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MT/s
|
||||||
|
Minimum Voltage: 1.2 V
|
||||||
|
Maximum Voltage: 1.2 V
|
||||||
|
Configured Voltage: 1.2 V
|
||||||
|
|
||||||
|
Handle 0x000A, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0006
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: 3
|
||||||
|
Locator: PROC 1 DIMM 4
|
||||||
|
Bank Locator: Not Specified
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: 2400 MT/s
|
||||||
|
Manufacturer: HP
|
||||||
|
Serial Number: Not Specified
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Part Number: 853289-091
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MT/s
|
||||||
|
Minimum Voltage: 1.2 V
|
||||||
|
Maximum Voltage: 1.2 V
|
||||||
|
Configured Voltage: 1.2 V
|
||||||
|
|
||||||
|
Handle 0x000B, DMI type 19, 31 bytes
|
||||||
|
Memory Array Mapped Address
|
||||||
|
Starting Address: 0x00000000000
|
||||||
|
Ending Address: 0x0007E7FFFFF
|
||||||
|
Range Size: 2024 MB
|
||||||
|
Physical Array Handle: 0x0006
|
||||||
|
Partition Width: 1
|
||||||
|
|
||||||
|
Handle 0x000C, DMI type 19, 31 bytes
|
||||||
|
Memory Array Mapped Address
|
||||||
|
Starting Address: 0x0000000100000000k
|
||||||
|
Ending Address: 0x00000010817FFFFFk
|
||||||
|
Range Size: 63512 MB
|
||||||
|
Physical Array Handle: 0x0006
|
||||||
|
Partition Width: 1
|
||||||
|
|
||||||
|
Handle 0x000D, DMI type 211, 7 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
D3 07 0D 00 03 00 00
|
||||||
|
|
||||||
|
Handle 0x000E, DMI type 2, 17 bytes
|
||||||
|
Base Board Information
|
||||||
|
Manufacturer: HP
|
||||||
|
Product Name: ProLiant m710x Server Cartridge
|
||||||
|
Version: Not Specified
|
||||||
|
Serial Number: CN66480ANY
|
||||||
|
Asset Tag:
|
||||||
|
Features:
|
||||||
|
Board is a hosting board
|
||||||
|
Board is removable
|
||||||
|
Board is replaceable
|
||||||
|
Location In Chassis: c2n1
|
||||||
|
Chassis Handle: 0x0000
|
||||||
|
Type: Motherboard
|
||||||
|
Contained Object Handles: 0
|
||||||
|
|
||||||
|
Handle 0x000F, DMI type 3, 21 bytes
|
||||||
|
Chassis Information
|
||||||
|
Manufacturer: HP
|
||||||
|
Type: Multi-system
|
||||||
|
Lock: Not Present
|
||||||
|
Version: Not Specified
|
||||||
|
Serial Number: CZ3702MD5K
|
||||||
|
Asset Tag:
|
||||||
|
Boot-up State: Safe
|
||||||
|
Power Supply State: Safe
|
||||||
|
Thermal State: Safe
|
||||||
|
Security Status: Unknown
|
||||||
|
OEM Information: 0x00000000
|
||||||
|
Height: 5 U
|
||||||
|
Number Of Power Cords: Unspecified
|
||||||
|
Contained Elements: 0
|
||||||
|
|
||||||
|
Handle 0x0010, DMI type 11, 5 bytes
|
||||||
|
OEM Strings
|
||||||
|
String 1: PSF:
|
||||||
|
String 2: Product ID: 833105-B21
|
||||||
|
String 3: CPN: HP Moonshot 1500 Chassis
|
||||||
|
String 4: OEM String:
|
||||||
|
|
||||||
|
Handle 0x0011, DMI type 38, 18 bytes
|
||||||
|
IPMI Device Information
|
||||||
|
Interface Type: KCS (Keyboard Control Style)
|
||||||
|
Specification Version: 2.0
|
||||||
|
I2C Slave Address: 0x10
|
||||||
|
NV Storage Device: Not Present
|
||||||
|
Base Address: 0x0000000000000CA2 (I/O)
|
||||||
|
Register Spacing: Successive Byte Boundaries
|
||||||
|
|
||||||
|
Handle 0x0012, DMI type 193, 9 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
C1 09 12 00 00 01 00 02 03
|
||||||
|
Strings:
|
||||||
|
0/0000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Handle 0x0013, DMI type 194, 5 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
C2 05 13 00 10
|
||||||
|
|
||||||
|
Handle 0x0014, DMI type 195, 7 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
C3 07 14 00 01 12 01
|
||||||
|
Strings:
|
||||||
|
$0E110855
|
||||||
|
|
||||||
|
Handle 0x0015, DMI type 197, 16 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
C5 10 15 00 03 00 00 01 FF 01 2D 00 00 00 00 00
|
||||||
|
|
||||||
|
Handle 0x0016, DMI type 198, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
C6 0E 16 00 17 00 00 00 00 00 01 0A FF FF
|
||||||
|
|
||||||
|
Handle 0x0017, DMI type 199, 28 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
C7 1C 17 00 2C 00 00 00 15 20 01 07 E2 06 05 00
|
||||||
|
88 00 00 00 16 20 16 03 E3 06 05 00
|
||||||
|
|
||||||
|
Handle 0x0018, DMI type 201, 16 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
C9 10 18 00 10 02 00 00 40 0D 01 00 0E 00 00 80
|
||||||
|
|
||||||
|
Handle 0x0019, DMI type 215, 6 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
D7 06 19 00 00 05
|
||||||
|
|
||||||
|
Handle 0x001A, DMI type 216, 23 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
D8 17 1A 00 01 00 01 02 07 01 00 05 17 E0 07 00
|
||||||
|
00 00 00 00 00 00 00
|
||||||
|
Strings:
|
||||||
|
System ROM
|
||||||
|
v1.00 (05/23/2016)
|
||||||
|
|
||||||
|
Handle 0x001B, DMI type 216, 23 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
D8 17 1B 00 04 00 01 02 04 00 00 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 00
|
||||||
|
Strings:
|
||||||
|
Power Management Controller Firmware
|
||||||
|
0.0
|
||||||
|
|
||||||
|
Handle 0x001C, DMI type 216, 23 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
D8 17 1C 00 05 00 01 02 02 60 00 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 00
|
||||||
|
Strings:
|
||||||
|
Power Management Controller FW Bootloader
|
||||||
|
6.0
|
||||||
|
|
||||||
|
Handle 0x001D, DMI type 216, 23 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
D8 17 1D 00 08 00 01 00 01 09 09 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 00
|
||||||
|
Strings:
|
||||||
|
System Programmable Logic Device
|
||||||
|
|
||||||
|
Handle 0x001E, DMI type 216, 23 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
D8 17 1E 00 09 00 01 00 03 04 00 00 00 03 00 96
|
||||||
|
00 0A 00 00 00 01 00
|
||||||
|
Strings:
|
||||||
|
Server Platform Services (SPS) Firmware
|
||||||
|
|
||||||
|
Handle 0x001F, DMI type 219, 32 bytes
|
||||||
|
HP ProLiant Information
|
||||||
|
Power Features: 0x000000df
|
||||||
|
Omega Features: 0x00000000
|
||||||
|
Misc. Features: 0x00009001
|
||||||
|
iCRU: Yes
|
||||||
|
UEFI: No
|
||||||
|
|
||||||
|
Handle 0x0020, DMI type 223, 11 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
DF 0B 20 00 66 46 70 00 00 00 00
|
||||||
|
|
||||||
|
Handle 0x0021, DMI type 224, 10 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E0 0A 21 00 00 00 02 03 FE FF
|
||||||
|
|
||||||
|
Handle 0x0022, DMI type 226, 21 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E2 15 22 00 38 33 33 31 30 35 43 4E 36 36 34 38
|
||||||
|
30 41 4E 59 01
|
||||||
|
Strings:
|
||||||
|
CN66480ANY
|
||||||
|
|
||||||
|
Handle 0x0023, DMI type 227, 22 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E3 16 23 00 03 00 07 00 00 A0 01 00 FF FF FF FF
|
||||||
|
00 00 00 00 00 00
|
||||||
|
|
||||||
|
Handle 0x0024, DMI type 227, 22 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E3 16 24 00 03 00 08 00 00 A2 01 00 FF FF FF FF
|
||||||
|
00 00 00 00 00 00
|
||||||
|
|
||||||
|
Handle 0x0025, DMI type 227, 22 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E3 16 25 00 03 00 09 00 00 A4 01 00 FF FF FF FF
|
||||||
|
01 00 00 00 00 00
|
||||||
|
|
||||||
|
Handle 0x0026, DMI type 227, 22 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E3 16 26 00 03 00 0A 00 00 A6 01 00 FF FF FF FF
|
||||||
|
01 00 00 00 00 00
|
||||||
|
|
||||||
|
Handle 0x0027, DMI type 228, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E4 0E 27 00 00 00 00 00 00 00 00 FF 00 00
|
||||||
|
|
||||||
|
Handle 0x0028, DMI type 228, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E4 0E 28 00 01 00 00 00 00 00 00 FF 00 00
|
||||||
|
|
||||||
|
Handle 0x0029, DMI type 228, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E4 0E 29 00 02 00 00 00 00 00 00 FF 00 00
|
||||||
|
|
||||||
|
Handle 0x002A, DMI type 228, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E4 0E 2A 00 03 00 00 00 00 00 00 FF 00 00
|
||||||
|
|
||||||
|
Handle 0x002B, DMI type 228, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E4 0E 2B 00 04 00 00 00 00 00 00 FF 00 00
|
||||||
|
|
||||||
|
Handle 0x002C, DMI type 228, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E4 0E 2C 00 05 00 00 00 00 00 00 FF 00 00
|
||||||
|
|
||||||
|
Handle 0x002D, DMI type 228, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E4 0E 2D 00 06 00 00 00 00 00 00 FF 00 00
|
||||||
|
|
||||||
|
Handle 0x002E, DMI type 228, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E4 0E 2E 00 07 00 00 00 00 00 00 FF 00 00
|
||||||
|
|
||||||
|
Handle 0x002F, DMI type 228, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E4 0E 2F 00 08 06 00 00 00 00 00 FF 01 00
|
||||||
|
|
||||||
|
Handle 0x0030, DMI type 229, 100 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E5 64 30 00 24 4F 43 53 00 B0 F1 77 00 00 00 00
|
||||||
|
00 40 00 00 24 4F 43 42 00 50 F0 77 00 00 00 00
|
||||||
|
00 60 01 00 24 48 44 44 00 30 F0 77 00 00 00 00
|
||||||
|
00 20 00 00 24 57 48 45 00 20 EF 77 00 00 00 00
|
||||||
|
00 10 00 00 24 53 4D 56 98 2E F2 77 00 00 00 00
|
||||||
|
08 00 00 00 24 5A 58 54 00 10 EF 77 00 00 00 00
|
||||||
|
3B 00 00 00
|
||||||
|
|
||||||
|
Handle 0x0031, DMI type 232, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E8 0E 31 00 07 00 11 00 00 00 B0 04 B0 04
|
||||||
|
|
||||||
|
Handle 0x0032, DMI type 232, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E8 0E 32 00 08 00 11 00 00 00 B0 04 B0 04
|
||||||
|
|
||||||
|
Handle 0x0033, DMI type 232, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E8 0E 33 00 09 00 11 00 00 00 B0 04 B0 04
|
||||||
|
|
||||||
|
Handle 0x0034, DMI type 232, 14 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
E8 0E 34 00 0A 00 11 00 00 00 B0 04 B0 04
|
||||||
|
|
||||||
|
Handle 0x0035, DMI type 237, 9 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
ED 09 35 00 07 00 01 02 03
|
||||||
|
Strings:
|
||||||
|
Hynix
|
||||||
|
HMA82GS7AFR8N-UH
|
||||||
|
31F9E4B8
|
||||||
|
|
||||||
|
Handle 0x0036, DMI type 237, 9 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
ED 09 36 00 08 00 01 02 03
|
||||||
|
Strings:
|
||||||
|
Hynix
|
||||||
|
HMA82GS7AFR8N-UH
|
||||||
|
31F9E4B6
|
||||||
|
|
||||||
|
Handle 0x0037, DMI type 237, 9 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
ED 09 37 00 09 00 01 02 03
|
||||||
|
Strings:
|
||||||
|
Hynix
|
||||||
|
HMA82GS7AFR8N-UH
|
||||||
|
31F9E96B
|
||||||
|
|
||||||
|
Handle 0x0038, DMI type 237, 9 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
ED 09 38 00 0A 00 01 02 03
|
||||||
|
Strings:
|
||||||
|
Hynix
|
||||||
|
HMA82GS7AFR8N-UH
|
||||||
|
31F9E4B9
|
||||||
|
|
||||||
|
Handle 0x0039, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI-E Slot 2
|
||||||
|
Type: x4 PCI Express 2
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Other
|
||||||
|
ID: 2
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:02:00.0
|
||||||
|
|
||||||
|
Handle 0x003A, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI-E Slot 1
|
||||||
|
Type: x1 PCI Express 2
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Other
|
||||||
|
ID: 1
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:05:00.0
|
||||||
|
|
||||||
|
Handle 0x003B, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI-E Slot 5
|
||||||
|
Type: x2 PCI Express 2
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Other
|
||||||
|
ID: 5
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:08:00.0
|
||||||
|
|
||||||
|
Handle 0x003C, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI-E Slot 0
|
||||||
|
Type: x1 PCI Express 3 x4
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Unknown
|
||||||
|
ID: 0
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:fe:00.0
|
||||||
|
|
||||||
|
Handle 0x003D, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI-E Slot 0
|
||||||
|
Type: x1 PCI Express 3 x4
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Unknown
|
||||||
|
ID: 0
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:fe:00.0
|
||||||
|
|
||||||
|
Handle 0x003E, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI-E Slot 4
|
||||||
|
Type: x4 PCI Express 2
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Unknown
|
||||||
|
ID: 4
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:0b:00.0
|
||||||
|
|
||||||
|
Handle 0x003F, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI-E Slot 3
|
||||||
|
Type: x4 PCI Express 2
|
||||||
|
Current Usage: In Use
|
||||||
|
Length: Other
|
||||||
|
ID: 3
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:0e:00.0
|
||||||
|
|
||||||
|
Handle 0x0040, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI-E Slot 1
|
||||||
|
Type: x4 PCI Express 3 x4
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Unknown
|
||||||
|
ID: 1
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:fe:00.0
|
||||||
|
|
||||||
|
Handle 0x0041, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI-E Slot 1
|
||||||
|
Type: x4 PCI Express 3 x4
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Unknown
|
||||||
|
ID: 1
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:fe:00.0
|
||||||
|
|
||||||
|
Handle 0x0042, DMI type 233, 41 bytes
|
||||||
|
HP BIOS PXE NIC PCI and MAC Information
|
||||||
|
NIC 1: PCI device 11:00.0, MAC address 00:FD:45:50:6C:01
|
||||||
|
|
||||||
|
Handle 0x0043, DMI type 233, 41 bytes
|
||||||
|
HP BIOS PXE NIC PCI and MAC Information
|
||||||
|
NIC 2: PCI device 11:00.0, MAC address 00:FD:45:50:6C:02
|
||||||
|
|
||||||
|
Handle 0x0044, DMI type 32, 11 bytes
|
||||||
|
System Boot Information
|
||||||
|
Status: No errors detected
|
||||||
|
|
||||||
|
Handle 0x0045, DMI type 196, 15 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
C4 0F 45 00 00 00 00 00 00 00 02 01 00 01 02
|
||||||
|
|
||||||
|
Handle 0x0046, DMI type 41, 11 bytes
|
||||||
|
Onboard Device
|
||||||
|
Reference Designation: Embedded LOM 1 Port 1
|
||||||
|
Type: Ethernet
|
||||||
|
Status: Enabled
|
||||||
|
Type Instance: 1
|
||||||
|
Bus Address: 0000:11:00.0
|
||||||
|
|
||||||
|
Handle 0x0047, DMI type 41, 11 bytes
|
||||||
|
Onboard Device
|
||||||
|
Reference Designation: Embedded LOM 1 Port 2
|
||||||
|
Type: Ethernet
|
||||||
|
Status: Enabled
|
||||||
|
Type Instance: 2
|
||||||
|
Bus Address: 0000:11:00.0
|
||||||
|
|
||||||
|
Handle 0x0048, DMI type 41, 11 bytes
|
||||||
|
Onboard Device
|
||||||
|
Reference Designation: Embedded SATA Controller #1
|
||||||
|
Type: SATA Controller
|
||||||
|
Status: Enabled
|
||||||
|
Type Instance: 1
|
||||||
|
Bus Address: 0000:00:17.0
|
||||||
|
|
||||||
|
Handle 0x0049, DMI type 202, 13 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CA 0D 49 00 07 00 FF 01 01 01 00 00 00
|
||||||
|
|
||||||
|
Handle 0x004A, DMI type 202, 13 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CA 0D 4A 00 08 00 FF 02 01 02 00 00 00
|
||||||
|
|
||||||
|
Handle 0x004B, DMI type 202, 13 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CA 0D 4B 00 09 00 FF 03 01 03 00 00 00
|
||||||
|
|
||||||
|
Handle 0x004C, DMI type 202, 13 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CA 0D 4C 00 0A 00 FF 04 01 04 00 00 00
|
||||||
|
|
||||||
|
Handle 0x004D, DMI type 203, 34 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CB 22 4D 00 39 00 FE FF FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FE FF 00 00 09 0A 02 01 FF FF 01 02 03 04
|
||||||
|
FE FF
|
||||||
|
Strings:
|
||||||
|
PciRoot(0x0)/Pci(0x1D,0x0)/Pci(0x0,0x0)
|
||||||
|
PCI.Slot.2.1
|
||||||
|
Empty slot 2
|
||||||
|
Slot 2
|
||||||
|
|
||||||
|
Handle 0x004E, DMI type 203, 34 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CB 22 4E 00 3A 00 FE FF FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FE FF 00 00 09 0A 01 01 FF FF 01 02 03 04
|
||||||
|
FE FF
|
||||||
|
Strings:
|
||||||
|
PciRoot(0x0)/Pci(0x1D,0x5)/Pci(0x0,0x0)
|
||||||
|
PCI.Slot.1.1
|
||||||
|
Empty slot 1
|
||||||
|
Slot 1
|
||||||
|
|
||||||
|
Handle 0x004F, DMI type 203, 34 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CB 22 4F 00 3B 00 FE FF FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FE FF 00 00 09 0A 05 01 FF FF 01 02 03 04
|
||||||
|
FE FF
|
||||||
|
Strings:
|
||||||
|
PciRoot(0x0)/Pci(0x1C,0x0)/Pci(0x0,0x0)
|
||||||
|
PCI.Slot.5.1
|
||||||
|
Empty slot 5
|
||||||
|
Slot 5
|
||||||
|
|
||||||
|
Handle 0x0050, DMI type 203, 34 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CB 22 50 00 3C 00 FE FF FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FE FF 00 00 09 0A 01 01 FF FF 01 02 03 04
|
||||||
|
FE FF
|
||||||
|
Strings:
|
||||||
|
PciRoot(0x0)/Pci(0x1C,0x2)/Pci(0x0,0x0)
|
||||||
|
PCI.Slot.1.1
|
||||||
|
Unknown
|
||||||
|
Slot 0
|
||||||
|
|
||||||
|
Handle 0x0051, DMI type 203, 34 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CB 22 51 00 3D 00 FE FF FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FE FF 00 00 09 0A 01 01 FF FF 01 02 03 04
|
||||||
|
FE FF
|
||||||
|
Strings:
|
||||||
|
PciRoot(0x0)/Pci(0x1C,0x2)/Pci(0x0,0x0)
|
||||||
|
PCI.Slot.1.1
|
||||||
|
Unknown
|
||||||
|
Slot 0
|
||||||
|
|
||||||
|
Handle 0x0052, DMI type 203, 34 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CB 22 52 00 3E 00 FE FF FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FE FF 00 00 09 0A 04 01 FF FF 01 02 03 04
|
||||||
|
FE FF
|
||||||
|
Strings:
|
||||||
|
PciRoot(0x0)/Pci(0x1C,0x4)/Pci(0x0,0x0)
|
||||||
|
PCI.Slot.4.1
|
||||||
|
Empty slot 4
|
||||||
|
Slot 4
|
||||||
|
|
||||||
|
Handle 0x0053, DMI type 203, 34 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CB 22 53 00 3F 00 FE FF 79 11 0F 01 79 11 01 00
|
||||||
|
01 08 FE FF 00 00 10 0A 03 01 FF FF 01 02 03 04
|
||||||
|
FE FF
|
||||||
|
Strings:
|
||||||
|
PciRoot(0x0)/Pci(0x1B,0x0)/Pci(0x0,0x0)
|
||||||
|
NVMe.Slot.3.1
|
||||||
|
NVM Express Controller
|
||||||
|
Slot 3
|
||||||
|
|
||||||
|
Handle 0x0054, DMI type 203, 34 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CB 22 54 00 40 00 FE FF FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FE FF 00 00 09 0A 01 01 FF FF 01 02 03 04
|
||||||
|
FE FF
|
||||||
|
Strings:
|
||||||
|
PciRoot(0x0)/Pci(0x1C,0x2)/Pci(0x0,0x0)
|
||||||
|
PCI.Slot.1.1
|
||||||
|
Empty slot 1
|
||||||
|
Slot 0
|
||||||
|
|
||||||
|
Handle 0x0055, DMI type 203, 34 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CB 22 55 00 41 00 FE FF FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FE FF 00 00 09 0A 01 01 FF FF 01 02 03 04
|
||||||
|
FE FF
|
||||||
|
Strings:
|
||||||
|
PciRoot(0x0)/Pci(0x1C,0x2)/Pci(0x0,0x0)
|
||||||
|
PCI.Slot.1.1
|
||||||
|
Empty slot 1
|
||||||
|
Slot 0
|
||||||
|
|
||||||
|
Handle 0x0056, DMI type 203, 34 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CB 22 56 00 46 00 FE FF B3 15 07 10 90 15 04 22
|
||||||
|
02 00 FE FF 00 00 04 01 01 01 FF FF 01 02 03 04
|
||||||
|
FE FF
|
||||||
|
Strings:
|
||||||
|
PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Ctrl(0x1)
|
||||||
|
NIC.LOM.1.1
|
||||||
|
Port 1 - Mellanox Network Adapter
|
||||||
|
Embedded LOM 1
|
||||||
|
|
||||||
|
Handle 0x0057, DMI type 203, 34 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CB 22 57 00 47 00 FE FF B3 15 07 10 90 15 04 22
|
||||||
|
02 00 FE FF 00 00 04 01 01 02 FF FF 01 02 03 04
|
||||||
|
FE FF
|
||||||
|
Strings:
|
||||||
|
PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Ctrl(0x2)
|
||||||
|
NIC.LOM.1.2
|
||||||
|
Port 2 - Mellanox Network Adapter
|
||||||
|
Embedded LOM 1
|
||||||
|
|
||||||
|
Handle 0x0058, DMI type 203, 34 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
CB 22 58 00 48 00 FE FF 86 80 02 A1 3C 10 65 81
|
||||||
|
01 06 FE FF 00 00 06 08 01 01 FF FF 01 02 03 04
|
||||||
|
FE FF
|
||||||
|
Strings:
|
||||||
|
PciRoot(0x0)/Pci(0x17,0x0)
|
||||||
|
SATA.Emb.1.1
|
||||||
|
Embedded SATA Controller #1
|
||||||
|
Embedded SATA Controller #1
|
||||||
|
|
||||||
|
Handle 0x0059, DMI type 234, 16 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
EA 10 59 00 FE FF C0 00 01 A0 00 00 00 00 00 00
|
||||||
|
|
||||||
|
Handle 0x005A, DMI type 234, 12 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
EA 0C 5A 00 27 00 60 03 01 01 00 00
|
||||||
|
|
||||||
|
Handle 0x005B, DMI type 240, 39 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
F0 27 5B 00 56 00 18 1E 24 00 01 08 48 0D 00 00
|
||||||
|
00 00 00 0F 00 00 00 00 00 00 00 0B 00 00 00 00
|
||||||
|
00 00 00 02 00 00 00
|
||||||
|
Strings:
|
||||||
|
02.36.70.00
|
||||||
|
|
||||||
|
Handle 0xFEFF, DMI type 127, 4 bytes
|
||||||
|
End Of Table
|
1364
tests/fixtures/dmidecode/HP_SL4540_Gen8
vendored
Normal file
1364
tests/fixtures/dmidecode/HP_SL4540_Gen8
vendored
Normal file
File diff suppressed because it is too large
Load diff
526
tests/fixtures/dmidecode/QCT_X10E-9N
vendored
Normal file
526
tests/fixtures/dmidecode/QCT_X10E-9N
vendored
Normal file
|
@ -0,0 +1,526 @@
|
||||||
|
# dmidecode 3.0
|
||||||
|
Getting SMBIOS data from sysfs.
|
||||||
|
SMBIOS 3.0 present.
|
||||||
|
37 structures occupying 2615 bytes.
|
||||||
|
Table at 0x8F9C5000.
|
||||||
|
|
||||||
|
Handle 0x0000, DMI type 0, 24 bytes
|
||||||
|
BIOS Information
|
||||||
|
Vendor: American Megatrends Inc.
|
||||||
|
Version: S3E_3B09.02
|
||||||
|
Release Date: 02/23/2018
|
||||||
|
Address: 0xF0000
|
||||||
|
Runtime Size: 64 kB
|
||||||
|
ROM Size: 8192 kB
|
||||||
|
Characteristics:
|
||||||
|
PCI is supported
|
||||||
|
BIOS is upgradeable
|
||||||
|
BIOS shadowing is allowed
|
||||||
|
Boot from CD is supported
|
||||||
|
Selectable boot is supported
|
||||||
|
BIOS ROM is socketed
|
||||||
|
EDD is supported
|
||||||
|
Print screen service is supported (int 5h)
|
||||||
|
Serial services are supported (int 14h)
|
||||||
|
Printer services are supported (int 17h)
|
||||||
|
ACPI is supported
|
||||||
|
USB legacy is supported
|
||||||
|
BIOS boot specification is supported
|
||||||
|
Targeted content distribution is supported
|
||||||
|
UEFI is supported
|
||||||
|
BIOS Revision: 5.11
|
||||||
|
Firmware Revision: 3.20
|
||||||
|
|
||||||
|
Handle 0x0001, DMI type 1, 27 bytes
|
||||||
|
System Information
|
||||||
|
Manufacturer: Quanta Cloud Technology Inc.
|
||||||
|
Product Name: QuantaMicro X10E-9N
|
||||||
|
Version: N/A
|
||||||
|
Serial Number: QTFCQ57140285
|
||||||
|
UUID: E1A3D1C8-0809-E711-B48A-A81E84729878
|
||||||
|
Wake-up Type: Power Switch
|
||||||
|
SKU Number: S3E
|
||||||
|
Family: Default string
|
||||||
|
|
||||||
|
Handle 0x0002, DMI type 2, 15 bytes
|
||||||
|
Base Board Information
|
||||||
|
Manufacturer: Quanta Cloud Technology Inc.
|
||||||
|
Product Name: S3E-MB
|
||||||
|
Version: 31S3EMB0010
|
||||||
|
Serial Number: CQ571000415
|
||||||
|
Asset Tag: N/A
|
||||||
|
Features:
|
||||||
|
Board is a hosting board
|
||||||
|
Board is replaceable
|
||||||
|
Location In Chassis: 4
|
||||||
|
Chassis Handle: 0x0003
|
||||||
|
Type: Motherboard
|
||||||
|
Contained Object Handles: 0
|
||||||
|
|
||||||
|
Handle 0x0003, DMI type 3, 22 bytes
|
||||||
|
Chassis Information
|
||||||
|
Manufacturer: Quanta Cloud Technology Inc.
|
||||||
|
Type: Rack Mount Chassis
|
||||||
|
Lock: Not Present
|
||||||
|
Version: 32S3ECAST00
|
||||||
|
Serial Number: QTFCQ571402FD
|
||||||
|
Asset Tag: N/A
|
||||||
|
Boot-up State: Safe
|
||||||
|
Power Supply State: Safe
|
||||||
|
Thermal State: Safe
|
||||||
|
Security Status: None
|
||||||
|
OEM Information: 0x00000000
|
||||||
|
Height: 3 U
|
||||||
|
Number Of Power Cords: 2
|
||||||
|
Contained Elements: 0
|
||||||
|
SKU Number: Default string
|
||||||
|
|
||||||
|
Handle 0x0021, DMI type 11, 5 bytes
|
||||||
|
OEM Strings
|
||||||
|
String 1: Default string
|
||||||
|
String 2: Default string
|
||||||
|
String 3: Default string
|
||||||
|
String 4: Default string
|
||||||
|
String 5: Default string
|
||||||
|
|
||||||
|
Handle 0x0025, DMI type 38, 18 bytes
|
||||||
|
IPMI Device Information
|
||||||
|
Interface Type: KCS (Keyboard Control Style)
|
||||||
|
Specification Version: 2.0
|
||||||
|
I2C Slave Address: 0x10
|
||||||
|
NV Storage Device: Not Present
|
||||||
|
Base Address: 0x0000000000000CA2 (I/O)
|
||||||
|
Register Spacing: Successive Byte Boundaries
|
||||||
|
|
||||||
|
Handle 0x0034, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: L1 Cache
|
||||||
|
Configuration: Enabled, Not Socketed, Level 1
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 256 kB
|
||||||
|
Maximum Size: 256 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Synchronous
|
||||||
|
Installed SRAM Type: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Parity
|
||||||
|
System Type: Other
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0035, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: L2 Cache
|
||||||
|
Configuration: Enabled, Not Socketed, Level 2
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 1024 kB
|
||||||
|
Maximum Size: 1024 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Synchronous
|
||||||
|
Installed SRAM Type: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 4-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0036, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: L3 Cache
|
||||||
|
Configuration: Enabled, Not Socketed, Level 3
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 8192 kB
|
||||||
|
Maximum Size: 8192 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Synchronous
|
||||||
|
Installed SRAM Type: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Multi-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 16-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0037, DMI type 4, 48 bytes
|
||||||
|
Processor Information
|
||||||
|
Socket Designation: CPU
|
||||||
|
Type: Central Processor
|
||||||
|
Family: Xeon
|
||||||
|
Manufacturer: Intel(R) Corporation
|
||||||
|
ID: E9 06 09 00 FF FB EB BF
|
||||||
|
Signature: Type 0, Family 6, Model 158, Stepping 9
|
||||||
|
Flags:
|
||||||
|
FPU (Floating-point unit on-chip)
|
||||||
|
VME (Virtual mode extension)
|
||||||
|
DE (Debugging extension)
|
||||||
|
PSE (Page size extension)
|
||||||
|
TSC (Time stamp counter)
|
||||||
|
MSR (Model specific registers)
|
||||||
|
PAE (Physical address extension)
|
||||||
|
MCE (Machine check exception)
|
||||||
|
CX8 (CMPXCHG8 instruction supported)
|
||||||
|
APIC (On-chip APIC hardware supported)
|
||||||
|
SEP (Fast system call)
|
||||||
|
MTRR (Memory type range registers)
|
||||||
|
PGE (Page global enable)
|
||||||
|
MCA (Machine check architecture)
|
||||||
|
CMOV (Conditional move instruction supported)
|
||||||
|
PAT (Page attribute table)
|
||||||
|
PSE-36 (36-bit page size extension)
|
||||||
|
CLFSH (CLFLUSH instruction supported)
|
||||||
|
DS (Debug store)
|
||||||
|
ACPI (ACPI supported)
|
||||||
|
MMX (MMX technology supported)
|
||||||
|
FXSR (FXSAVE and FXSTOR instructions supported)
|
||||||
|
SSE (Streaming SIMD extensions)
|
||||||
|
SSE2 (Streaming SIMD extensions 2)
|
||||||
|
SS (Self-snoop)
|
||||||
|
HTT (Multi-threading)
|
||||||
|
TM (Thermal monitor supported)
|
||||||
|
PBE (Pending break enabled)
|
||||||
|
Version: Intel(R) Xeon(R) CPU E3-1240 v6 @ 3.70GHz
|
||||||
|
Voltage: 1.0 V
|
||||||
|
External Clock: 100 MHz
|
||||||
|
Max Speed: 4100 MHz
|
||||||
|
Current Speed: 3700 MHz
|
||||||
|
Status: Populated, Enabled
|
||||||
|
Upgrade: Other
|
||||||
|
L1 Cache Handle: 0x0034
|
||||||
|
L2 Cache Handle: 0x0035
|
||||||
|
L3 Cache Handle: 0x0036
|
||||||
|
Serial Number: To Be Filled By O.E.M.
|
||||||
|
Asset Tag: To Be Filled By O.E.M.
|
||||||
|
Part Number: To Be Filled By O.E.M.
|
||||||
|
Core Count: 4
|
||||||
|
Core Enabled: 4
|
||||||
|
Thread Count: 8
|
||||||
|
Characteristics:
|
||||||
|
64-bit capable
|
||||||
|
Multi-Core
|
||||||
|
Hardware Thread
|
||||||
|
Execute Protection
|
||||||
|
Enhanced Virtualization
|
||||||
|
Power/Performance Control
|
||||||
|
|
||||||
|
Handle 0x0038, DMI type 16, 23 bytes
|
||||||
|
Physical Memory Array
|
||||||
|
Location: System Board Or Motherboard
|
||||||
|
Use: System Memory
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
Maximum Capacity: 64 GB
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Number Of Devices: 4
|
||||||
|
|
||||||
|
Handle 0x0039, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0038
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: Unknown
|
||||||
|
Data Width: Unknown
|
||||||
|
Size: No Module Installed
|
||||||
|
Form Factor: Unknown
|
||||||
|
Set: None
|
||||||
|
Locator: DIMM A1
|
||||||
|
Bank Locator: CHANNEL A
|
||||||
|
Type: Unknown
|
||||||
|
Type Detail: None
|
||||||
|
Speed: Unknown
|
||||||
|
Manufacturer: Not Specified
|
||||||
|
Serial Number: Not Specified
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Part Number: Not Specified
|
||||||
|
Rank: Unknown
|
||||||
|
Configured Clock Speed: Unknown
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x003A, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0038
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: DIMM A0
|
||||||
|
Bank Locator: CHANNEL A
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: 2133 MHz
|
||||||
|
Manufacturer: Samsung
|
||||||
|
Serial Number: 328CBA1D
|
||||||
|
Asset Tag: 9876543210
|
||||||
|
Part Number: M391A2K43BB1-CPB
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum Voltage: 1.2 V
|
||||||
|
Maximum Voltage: 1.2 V
|
||||||
|
Configured Voltage: 1.2 V
|
||||||
|
|
||||||
|
Handle 0x003B, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0038
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: Unknown
|
||||||
|
Data Width: Unknown
|
||||||
|
Size: No Module Installed
|
||||||
|
Form Factor: Unknown
|
||||||
|
Set: None
|
||||||
|
Locator: DIMM B1
|
||||||
|
Bank Locator: CHANNEL B
|
||||||
|
Type: Unknown
|
||||||
|
Type Detail: None
|
||||||
|
Speed: Unknown
|
||||||
|
Manufacturer: Not Specified
|
||||||
|
Serial Number: Not Specified
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Part Number: Not Specified
|
||||||
|
Rank: Unknown
|
||||||
|
Configured Clock Speed: Unknown
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x003C, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0038
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: DIMM B0
|
||||||
|
Bank Locator: CHANNEL B
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: 2133 MHz
|
||||||
|
Manufacturer: Samsung
|
||||||
|
Serial Number: 328CB9DF
|
||||||
|
Asset Tag: 9876543210
|
||||||
|
Part Number: M391A2K43BB1-CPB
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum Voltage: 1.2 V
|
||||||
|
Maximum Voltage: 1.2 V
|
||||||
|
Configured Voltage: 1.2 V
|
||||||
|
|
||||||
|
Handle 0x003D, DMI type 19, 31 bytes
|
||||||
|
Memory Array Mapped Address
|
||||||
|
Starting Address: 0x00000000000
|
||||||
|
Ending Address: 0x007FFFFFFFF
|
||||||
|
Range Size: 32 GB
|
||||||
|
Physical Array Handle: 0x0038
|
||||||
|
Partition Width: 2
|
||||||
|
|
||||||
|
Handle 0x003E, DMI type 221, 26 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
DD 1A 3E 00 03 01 00 04 01 00 08 00 02 00 00 00
|
||||||
|
00 84 00 03 00 01 03 00 00 00
|
||||||
|
Strings:
|
||||||
|
Reference Code - CPU
|
||||||
|
uCode Version
|
||||||
|
TXT ACM version
|
||||||
|
|
||||||
|
Handle 0x003F, DMI type 221, 68 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
DD 44 3F 00 09 01 00 04 01 00 08 00 02 03 FF FF
|
||||||
|
FF FF FF 04 00 FF FF FF 31 00 05 00 FF FF FF 31
|
||||||
|
00 06 00 FF FF FF FF FF 07 00 3E 00 00 00 00 08
|
||||||
|
00 34 00 00 00 00 09 00 3E 00 00 00 00 0A 00 34
|
||||||
|
00 00 00 00
|
||||||
|
Strings:
|
||||||
|
Reference Code - SKL PCH
|
||||||
|
PCH-CRID Status
|
||||||
|
Disabled
|
||||||
|
PCH-CRID Original Value
|
||||||
|
PCH-CRID New Value
|
||||||
|
OPROM - RST - RAID
|
||||||
|
SKL PCH H Bx Hsio Version
|
||||||
|
SKL PCH H Dx Hsio Version
|
||||||
|
SKL PCH LP Bx Hsio Version
|
||||||
|
SKL PCH LP Cx Hsio Version
|
||||||
|
|
||||||
|
Handle 0x0040, DMI type 221, 54 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
DD 36 40 00 07 01 00 04 01 00 08 00 02 00 04 01
|
||||||
|
00 08 00 03 00 04 01 00 00 00 04 05 FF FF FF FF
|
||||||
|
FF 06 00 FF FF FF 05 00 07 00 FF FF FF 05 00 08
|
||||||
|
00 FF FF FF 00 00
|
||||||
|
Strings:
|
||||||
|
Reference Code - SA - System Agent
|
||||||
|
Reference Code - MRC
|
||||||
|
SA - PCIe Version
|
||||||
|
SA-CRID Status
|
||||||
|
Disabled
|
||||||
|
SA-CRID Original Value
|
||||||
|
SA-CRID New Value
|
||||||
|
OPROM - VBIOS
|
||||||
|
|
||||||
|
Handle 0x0041, DMI type 221, 96 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
DD 60 41 00 0D 01 00 00 00 00 00 00 02 00 FF FF
|
||||||
|
FF FF FF 03 04 FF FF FF FF FF 05 06 FF FF FF FF
|
||||||
|
FF 07 08 FF FF FF FF FF 09 00 00 00 00 00 00 0A
|
||||||
|
00 FF FF FF FF FF 0B 00 FF FF 00 00 00 0C 00 FF
|
||||||
|
FF FF FF FF 0D 00 FF FF FF FF FF 0E 00 FF FF FF
|
||||||
|
FF FF 0F 00 FF FF FF FF FF 10 11 01 02 02 03 00
|
||||||
|
Strings:
|
||||||
|
Lan Phy Version
|
||||||
|
Sensor Firmware Version
|
||||||
|
Debug Mode Status
|
||||||
|
Disabled
|
||||||
|
Performance Mode Status
|
||||||
|
Disabled
|
||||||
|
Debug Use USB(Disabled:Serial)
|
||||||
|
Disabled
|
||||||
|
ICC Overclocking Version
|
||||||
|
UNDI Version
|
||||||
|
EC FW Version
|
||||||
|
GOP Version
|
||||||
|
BIOS Guard Version
|
||||||
|
Base EC FW Version
|
||||||
|
EC-EC Protocol Version
|
||||||
|
Royal Park Version
|
||||||
|
BP1.2.2.0_RP03
|
||||||
|
|
||||||
|
Handle 0x0043, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J1:XDP CONN
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0044, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: JP2:CPLD JTAG
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0045, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J7:HDD0
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: SATA
|
||||||
|
|
||||||
|
Handle 0x0046, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: Not Specified
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: J15:USB CONN_1
|
||||||
|
External Connector Type: Access Bus (USB)
|
||||||
|
Port Type: USB
|
||||||
|
|
||||||
|
Handle 0x0047, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: Not Specified
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: J16:USB CONN_0
|
||||||
|
External Connector Type: Access Bus (USB)
|
||||||
|
Port Type: USB
|
||||||
|
|
||||||
|
Handle 0x0048, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: JP10:SMBUS_HOST
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0049, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J20:TPM CONN
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x004A, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: JP13:SERIAL_A
|
||||||
|
Internal Connector Type: DB-9 male
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Serial Port XT/AT Compatible
|
||||||
|
|
||||||
|
Handle 0x004B, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: Not Specified
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: J22:VGA_Conn
|
||||||
|
External Connector Type: DB-15 female
|
||||||
|
Port Type: Video Port
|
||||||
|
|
||||||
|
Handle 0x004C, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: Mezz Slot(PCIex8 x4)
|
||||||
|
Type: x12 Proprietary
|
||||||
|
Current Usage: In Use
|
||||||
|
Length: Short
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
SMBus signal is supported
|
||||||
|
Bus Address: 0000:00:01.0
|
||||||
|
|
||||||
|
Handle 0x004D, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: OCP Mezz Slot(PCIex4)
|
||||||
|
Type: x4 Proprietary
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Short
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:00:1d.0
|
||||||
|
|
||||||
|
Handle 0x004E, DMI type 41, 11 bytes
|
||||||
|
Onboard Device
|
||||||
|
Reference Designation: Intel(R) C236 chipset SATA Controller
|
||||||
|
Type: SATA Controller
|
||||||
|
Status: Enabled
|
||||||
|
Type Instance: 1
|
||||||
|
Bus Address: 0000:00:17.0
|
||||||
|
|
||||||
|
Handle 0x004F, DMI type 41, 11 bytes
|
||||||
|
Onboard Device
|
||||||
|
Reference Designation: onboard VGA
|
||||||
|
Type: Video
|
||||||
|
Status: Enabled
|
||||||
|
Type Instance: 1
|
||||||
|
Bus Address: 0000:03:00.0
|
||||||
|
|
||||||
|
Handle 0x0050, DMI type 136, 6 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
88 06 50 00 00 00
|
||||||
|
|
||||||
|
Handle 0x0051, DMI type 14, 17 bytes
|
||||||
|
Group Associations
|
||||||
|
Name: Firmware Version Info
|
||||||
|
Items: 4
|
||||||
|
0x003E (<OUT OF SPEC>)
|
||||||
|
0x003F (<OUT OF SPEC>)
|
||||||
|
0x0040 (<OUT OF SPEC>)
|
||||||
|
0x0041 (<OUT OF SPEC>)
|
||||||
|
|
||||||
|
Handle 0x0052, DMI type 13, 22 bytes
|
||||||
|
BIOS Language Information
|
||||||
|
Language Description Format: Long
|
||||||
|
Installable Languages: 1
|
||||||
|
en|US|iso8859-1
|
||||||
|
Currently Installed Language: en|US|iso8859-1
|
||||||
|
|
||||||
|
Handle 0x0053, DMI type 127, 4 bytes
|
||||||
|
End Of Table
|
||||||
|
|
1242
tests/fixtures/dmidecode/SM_SSG-6028R
vendored
Normal file
1242
tests/fixtures/dmidecode/SM_SSG-6028R
vendored
Normal file
File diff suppressed because it is too large
Load diff
957
tests/fixtures/dmidecode/SM_SYS-6018R
vendored
Normal file
957
tests/fixtures/dmidecode/SM_SYS-6018R
vendored
Normal file
|
@ -0,0 +1,957 @@
|
||||||
|
# dmidecode 3.0
|
||||||
|
Getting SMBIOS data from sysfs.
|
||||||
|
SMBIOS 3.0.0 present.
|
||||||
|
Table at 0x000EC9B0.
|
||||||
|
|
||||||
|
Handle 0x0000, DMI type 0, 24 bytes
|
||||||
|
BIOS Information
|
||||||
|
Vendor: American Megatrends Inc.
|
||||||
|
Version: 2.0b
|
||||||
|
Release Date: 04/14/2017
|
||||||
|
Address: 0xF0000
|
||||||
|
Runtime Size: 64 kB
|
||||||
|
ROM Size: 16384 kB
|
||||||
|
Characteristics:
|
||||||
|
PCI is supported
|
||||||
|
BIOS is upgradeable
|
||||||
|
BIOS shadowing is allowed
|
||||||
|
Boot from CD is supported
|
||||||
|
Selectable boot is supported
|
||||||
|
BIOS ROM is socketed
|
||||||
|
EDD is supported
|
||||||
|
5.25"/1.2 MB floppy services are supported (int 13h)
|
||||||
|
3.5"/720 kB floppy services are supported (int 13h)
|
||||||
|
3.5"/2.88 MB floppy services are supported (int 13h)
|
||||||
|
Print screen service is supported (int 5h)
|
||||||
|
8042 keyboard services are supported (int 9h)
|
||||||
|
Serial services are supported (int 14h)
|
||||||
|
Printer services are supported (int 17h)
|
||||||
|
ACPI is supported
|
||||||
|
USB legacy is supported
|
||||||
|
BIOS boot specification is supported
|
||||||
|
Targeted content distribution is supported
|
||||||
|
UEFI is supported
|
||||||
|
BIOS Revision: 5.6
|
||||||
|
|
||||||
|
Handle 0x0001, DMI type 1, 27 bytes
|
||||||
|
System Information
|
||||||
|
Manufacturer: Supermicro
|
||||||
|
Product Name: SYS-6018R-TDTPR
|
||||||
|
Version: 0123456789
|
||||||
|
Serial Number: A177950X7709591
|
||||||
|
UUID: 00000000-0000-0000-0000-0CC47A4B18C0
|
||||||
|
Wake-up Type: Power Switch
|
||||||
|
SKU Number: Default string
|
||||||
|
Family: Default string
|
||||||
|
|
||||||
|
Handle 0x0002, DMI type 2, 15 bytes
|
||||||
|
Base Board Information
|
||||||
|
Manufacturer: Supermicro
|
||||||
|
Product Name: X10DRD-LTP
|
||||||
|
Version: 1.00
|
||||||
|
Serial Number: ZM152S007866
|
||||||
|
Asset Tag: Default string
|
||||||
|
Features:
|
||||||
|
Board is a hosting board
|
||||||
|
Board is replaceable
|
||||||
|
Location In Chassis: Default string
|
||||||
|
Chassis Handle: 0x0003
|
||||||
|
Type: Motherboard
|
||||||
|
Contained Object Handles: 0
|
||||||
|
|
||||||
|
Handle 0x0003, DMI type 3, 22 bytes
|
||||||
|
Chassis Information
|
||||||
|
Manufacturer: Supermicro
|
||||||
|
Type: Other
|
||||||
|
Lock: Not Present
|
||||||
|
Version: 0123456789
|
||||||
|
Serial Number: C8150LG15NH0008
|
||||||
|
Asset Tag: Default string
|
||||||
|
Boot-up State: Safe
|
||||||
|
Power Supply State: Safe
|
||||||
|
Thermal State: Safe
|
||||||
|
Security Status: None
|
||||||
|
OEM Information: 0x00000000
|
||||||
|
Height: Unspecified
|
||||||
|
Number Of Power Cords: 1
|
||||||
|
Contained Elements: 0
|
||||||
|
SKU Number: Default string
|
||||||
|
|
||||||
|
Handle 0x0004, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J1A1
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: PS2Mouse
|
||||||
|
External Connector Type: PS/2
|
||||||
|
Port Type: Mouse Port
|
||||||
|
|
||||||
|
Handle 0x0005, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J1A1
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: Keyboard
|
||||||
|
External Connector Type: PS/2
|
||||||
|
Port Type: Keyboard Port
|
||||||
|
|
||||||
|
Handle 0x0006, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J2A1
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: TV Out
|
||||||
|
External Connector Type: Mini Centronics Type-14
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0007, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J2A2A
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: COM A
|
||||||
|
External Connector Type: DB-9 male
|
||||||
|
Port Type: Serial Port 16550A Compatible
|
||||||
|
|
||||||
|
Handle 0x0008, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J2A2B
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: Video
|
||||||
|
External Connector Type: DB-15 female
|
||||||
|
Port Type: Video Port
|
||||||
|
|
||||||
|
Handle 0x0009, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J3A1
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: USB1
|
||||||
|
External Connector Type: Access Bus (USB)
|
||||||
|
Port Type: USB
|
||||||
|
|
||||||
|
Handle 0x000A, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J3A1
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: USB2
|
||||||
|
External Connector Type: Access Bus (USB)
|
||||||
|
Port Type: USB
|
||||||
|
|
||||||
|
Handle 0x000B, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J3A1
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: USB3
|
||||||
|
External Connector Type: Access Bus (USB)
|
||||||
|
Port Type: USB
|
||||||
|
|
||||||
|
Handle 0x000C, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J9A1 - TPM HDR
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x000D, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J9C1 - PCIE DOCKING CONN
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x000E, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J2B3 - CPU FAN
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x000F, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J6C2 - EXT HDMI
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0010, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J3C1 - GMCH FAN
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0011, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J1D1 - ITP
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0012, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J9E2 - MDC INTPSR
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0013, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J9E4 - MDC INTPSR
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0014, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J9E3 - LPC HOT DOCKING
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0015, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J9E1 - SCAN MATRIX
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0016, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J9G1 - LPC SIDE BAND
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0017, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J8F1 - UNIFIED
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0018, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J6F1 - LVDS
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x0019, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J2F1 - LAI FAN
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x001A, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J2G1 - GFX VID
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x001B, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: J1G6 - AC JACK
|
||||||
|
Internal Connector Type: Other
|
||||||
|
External Reference Designator: Not Specified
|
||||||
|
External Connector Type: None
|
||||||
|
Port Type: Other
|
||||||
|
|
||||||
|
Handle 0x001C, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: CPU1 SLOT4 PCI-E 3.0 X8
|
||||||
|
Type: x8 PCI Express 3 x8
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Short
|
||||||
|
ID: 4
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
Opening is shared
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:05:00.0
|
||||||
|
|
||||||
|
Handle 0x001D, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: CPU1 SLOT5 PCI-E 3.0 X8
|
||||||
|
Type: x8 PCI Express 3 x8
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Short
|
||||||
|
ID: 5
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
Opening is shared
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:03:00.0
|
||||||
|
|
||||||
|
Handle 0x001E, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: CPU1 SLOT6 PCI-E 3.0 X8
|
||||||
|
Type: x8 PCI Express 3 x8
|
||||||
|
Current Usage: In Use
|
||||||
|
Length: Short
|
||||||
|
ID: 6
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
Opening is shared
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:04:00.0
|
||||||
|
|
||||||
|
Handle 0x001F, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: CPU2 SLOT7 PCI-E 3.0 X8
|
||||||
|
Type: x8 PCI Express 3 x8
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Short
|
||||||
|
ID: 7
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
Opening is shared
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:ff:00.0
|
||||||
|
|
||||||
|
Handle 0x0020, DMI type 11, 5 bytes
|
||||||
|
OEM Strings
|
||||||
|
String 1: Intel Haswell/Wellsburg/Grantley
|
||||||
|
String 2: Supermicro motherboard-X10 Series
|
||||||
|
|
||||||
|
Handle 0x0021, DMI type 32, 20 bytes
|
||||||
|
System Boot Information
|
||||||
|
Status: No errors detected
|
||||||
|
|
||||||
|
Handle 0x0022, DMI type 39, 22 bytes
|
||||||
|
System Power Supply
|
||||||
|
Power Unit Group: 1
|
||||||
|
Location: PSU1
|
||||||
|
Name: PWS-504P-1R
|
||||||
|
Manufacturer: SUPERMICRO
|
||||||
|
Serial Number: P5041CG52ST0022
|
||||||
|
Asset Tag: N/A
|
||||||
|
Model Part Number: PWS-504P-1R
|
||||||
|
Revision: 1.4
|
||||||
|
Max Power Capacity: 500 W
|
||||||
|
Status: Present, OK
|
||||||
|
Type: Switching
|
||||||
|
Input Voltage Range Switching: Auto-switch
|
||||||
|
Plugged: Yes
|
||||||
|
Hot Replaceable: Yes
|
||||||
|
|
||||||
|
Handle 0x0023, DMI type 39, 22 bytes
|
||||||
|
System Power Supply
|
||||||
|
Power Unit Group: 2
|
||||||
|
Location: PSU2
|
||||||
|
Name: PWS-504P-1R
|
||||||
|
Manufacturer: SUPERMICRO
|
||||||
|
Serial Number: P5041CG52ST0021
|
||||||
|
Asset Tag: N/A
|
||||||
|
Model Part Number: PWS-504P-1R
|
||||||
|
Revision: 1.4
|
||||||
|
Max Power Capacity: 500 W
|
||||||
|
Status: Present, OK
|
||||||
|
Type: Switching
|
||||||
|
Input Voltage Range Switching: Auto-switch
|
||||||
|
Plugged: Yes
|
||||||
|
Hot Replaceable: Yes
|
||||||
|
|
||||||
|
Handle 0x0024, DMI type 41, 11 bytes
|
||||||
|
Onboard Device
|
||||||
|
Reference Designation: ASPEED Video AST2400
|
||||||
|
Type: Video
|
||||||
|
Status: Enabled
|
||||||
|
Type Instance: 1
|
||||||
|
Bus Address: 0000:09:00.0
|
||||||
|
|
||||||
|
Handle 0x0025, DMI type 41, 11 bytes
|
||||||
|
Onboard Device
|
||||||
|
Reference Designation: Intel Ethernet 82599ES/EN SFP+ #1
|
||||||
|
Type: Ethernet
|
||||||
|
Status: Enabled
|
||||||
|
Type Instance: 1
|
||||||
|
Bus Address: 0000:06:00.0
|
||||||
|
|
||||||
|
Handle 0x0026, DMI type 41, 11 bytes
|
||||||
|
Onboard Device
|
||||||
|
Reference Designation: Intel Ethernet 82599ES/EN SFP+ #2
|
||||||
|
Type: Ethernet
|
||||||
|
Status: Enabled
|
||||||
|
Type Instance: 2
|
||||||
|
Bus Address: 0000:06:00.1
|
||||||
|
|
||||||
|
Handle 0x0027, DMI type 38, 18 bytes
|
||||||
|
IPMI Device Information
|
||||||
|
Interface Type: KCS (Keyboard Control Style)
|
||||||
|
Specification Version: 2.0
|
||||||
|
I2C Slave Address: 0x10
|
||||||
|
NV Storage Device: Not Present
|
||||||
|
Base Address: 0x0000000000000CA2 (I/O)
|
||||||
|
Register Spacing: Successive Byte Boundaries
|
||||||
|
|
||||||
|
Handle 0x002A, DMI type 16, 23 bytes
|
||||||
|
Physical Memory Array
|
||||||
|
Location: System Board Or Motherboard
|
||||||
|
Use: System Memory
|
||||||
|
Error Correction Type: Multi-bit ECC
|
||||||
|
Maximum Capacity: 256 GB
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Number Of Devices: 4
|
||||||
|
|
||||||
|
Handle 0x002B, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x002A
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: P1-DIMMA1
|
||||||
|
Bank Locator: P0_Node0_Channel0_Dimm0
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: SK Hynix
|
||||||
|
Serial Number: 2AA5B8E9
|
||||||
|
Asset Tag: P1-DIMMA1_AssetTag (date:17/39)
|
||||||
|
Part Number: HMA42GR7AFR4N-UH
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x002C, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x002A
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: P1-DIMMB1
|
||||||
|
Bank Locator: P0_Node0_Channel1_Dimm0
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: SK Hynix
|
||||||
|
Serial Number: 2AA5B923
|
||||||
|
Asset Tag: P1-DIMMB1_AssetTag (date:17/39)
|
||||||
|
Part Number: HMA42GR7AFR4N-UH
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x002D, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x002A
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: Unknown
|
||||||
|
Data Width: Unknown
|
||||||
|
Size: No Module Installed
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: P1-DIMMC1
|
||||||
|
Bank Locator: P0_Node0_Channel2_Dimm0
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Manufacturer: NO DIMM
|
||||||
|
Serial Number: NO DIMM
|
||||||
|
Asset Tag: NO DIMM
|
||||||
|
Part Number: NO DIMM
|
||||||
|
Rank: Unknown
|
||||||
|
Configured Clock Speed: Unknown
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x002E, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x002A
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: Unknown
|
||||||
|
Data Width: Unknown
|
||||||
|
Size: No Module Installed
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: P1-DIMMD1
|
||||||
|
Bank Locator: P0_Node0_Channel3_Dimm0
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Manufacturer: NO DIMM
|
||||||
|
Serial Number: NO DIMM
|
||||||
|
Asset Tag: NO DIMM
|
||||||
|
Part Number: NO DIMM
|
||||||
|
Rank: Unknown
|
||||||
|
Configured Clock Speed: Unknown
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x002F, DMI type 16, 23 bytes
|
||||||
|
Physical Memory Array
|
||||||
|
Location: System Board Or Motherboard
|
||||||
|
Use: System Memory
|
||||||
|
Error Correction Type: Multi-bit ECC
|
||||||
|
Maximum Capacity: 256 GB
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Number Of Devices: 4
|
||||||
|
|
||||||
|
Handle 0x0030, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x002F
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: P2-DIMME1
|
||||||
|
Bank Locator: P1_Node1_Channel0_Dimm0
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: SK Hynix
|
||||||
|
Serial Number: 2AA5B88C
|
||||||
|
Asset Tag: P2-DIMME1_AssetTag (date:17/39)
|
||||||
|
Part Number: HMA42GR7AFR4N-UH
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x0031, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x002F
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: P2-DIMMF1
|
||||||
|
Bank Locator: P1_Node1_Channel1_Dimm0
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: 2400 MHz
|
||||||
|
Manufacturer: SK Hynix
|
||||||
|
Serial Number: 2AA5B86B
|
||||||
|
Asset Tag: P2-DIMMF1_AssetTag (date:17/39)
|
||||||
|
Part Number: HMA42GR7AFR4N-UH
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MHz
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x0032, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x002F
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: Unknown
|
||||||
|
Data Width: Unknown
|
||||||
|
Size: No Module Installed
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: P2-DIMMG1
|
||||||
|
Bank Locator: P1_Node1_Channel2_Dimm0
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Manufacturer: NO DIMM
|
||||||
|
Serial Number: NO DIMM
|
||||||
|
Asset Tag: NO DIMM
|
||||||
|
Part Number: NO DIMM
|
||||||
|
Rank: Unknown
|
||||||
|
Configured Clock Speed: Unknown
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x0033, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x002F
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: Unknown
|
||||||
|
Data Width: Unknown
|
||||||
|
Size: No Module Installed
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: P2-DIMMH1
|
||||||
|
Bank Locator: P1_Node1_Channel3_Dimm0
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Manufacturer: NO DIMM
|
||||||
|
Serial Number: NO DIMM
|
||||||
|
Asset Tag: NO DIMM
|
||||||
|
Part Number: NO DIMM
|
||||||
|
Rank: Unknown
|
||||||
|
Configured Clock Speed: Unknown
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x0034, DMI type 19, 31 bytes
|
||||||
|
Memory Array Mapped Address
|
||||||
|
Starting Address: 0x00000000000
|
||||||
|
Ending Address: 0x007FFFFFFFF
|
||||||
|
Range Size: 32 GB
|
||||||
|
Physical Array Handle: 0x002A
|
||||||
|
Partition Width: 2
|
||||||
|
|
||||||
|
Handle 0x0035, DMI type 20, 35 bytes
|
||||||
|
Memory Device Mapped Address
|
||||||
|
Starting Address: 0x00000000000
|
||||||
|
Ending Address: 0x003FFFFFFFF
|
||||||
|
Range Size: 16 GB
|
||||||
|
Physical Device Handle: 0x002B
|
||||||
|
Memory Array Mapped Address Handle: 0x0034
|
||||||
|
Partition Row Position: 1
|
||||||
|
|
||||||
|
Handle 0x0036, DMI type 20, 35 bytes
|
||||||
|
Memory Device Mapped Address
|
||||||
|
Starting Address: 0x00400000000
|
||||||
|
Ending Address: 0x007FFFFFFFF
|
||||||
|
Range Size: 16 GB
|
||||||
|
Physical Device Handle: 0x002C
|
||||||
|
Memory Array Mapped Address Handle: 0x0034
|
||||||
|
Partition Row Position: 1
|
||||||
|
|
||||||
|
Handle 0x0037, DMI type 19, 31 bytes
|
||||||
|
Memory Array Mapped Address
|
||||||
|
Starting Address: 0x00800000000
|
||||||
|
Ending Address: 0x00FFFFFFFFF
|
||||||
|
Range Size: 32 GB
|
||||||
|
Physical Array Handle: 0x002F
|
||||||
|
Partition Width: 2
|
||||||
|
|
||||||
|
Handle 0x0038, DMI type 20, 35 bytes
|
||||||
|
Memory Device Mapped Address
|
||||||
|
Starting Address: 0x00800000000
|
||||||
|
Ending Address: 0x00BFFFFFFFF
|
||||||
|
Range Size: 16 GB
|
||||||
|
Physical Device Handle: 0x0030
|
||||||
|
Memory Array Mapped Address Handle: 0x0037
|
||||||
|
Partition Row Position: 1
|
||||||
|
|
||||||
|
Handle 0x0039, DMI type 20, 35 bytes
|
||||||
|
Memory Device Mapped Address
|
||||||
|
Starting Address: 0x00C00000000
|
||||||
|
Ending Address: 0x00FFFFFFFFF
|
||||||
|
Range Size: 16 GB
|
||||||
|
Physical Device Handle: 0x0031
|
||||||
|
Memory Array Mapped Address Handle: 0x0037
|
||||||
|
Partition Row Position: 1
|
||||||
|
|
||||||
|
Handle 0x003A, DMI type 15, 73 bytes
|
||||||
|
System Event Log
|
||||||
|
Area Length: 65535 bytes
|
||||||
|
Header Start Offset: 0x0000
|
||||||
|
Header Length: 16 bytes
|
||||||
|
Data Start Offset: 0x0010
|
||||||
|
Access Method: Memory-mapped physical 32-bit address
|
||||||
|
Access Address: 0xFF540000
|
||||||
|
Status: Valid, Not Full
|
||||||
|
Change Token: 0x00000001
|
||||||
|
Header Format: Type 1
|
||||||
|
Supported Log Type Descriptors: 25
|
||||||
|
Descriptor 1: Single-bit ECC memory error
|
||||||
|
Data Format 1: Multiple-event handle
|
||||||
|
Descriptor 2: Multi-bit ECC memory error
|
||||||
|
Data Format 2: Multiple-event handle
|
||||||
|
Descriptor 3: Parity memory error
|
||||||
|
Data Format 3: None
|
||||||
|
Descriptor 4: Bus timeout
|
||||||
|
Data Format 4: None
|
||||||
|
Descriptor 5: I/O channel block
|
||||||
|
Data Format 5: None
|
||||||
|
Descriptor 6: Software NMI
|
||||||
|
Data Format 6: None
|
||||||
|
Descriptor 7: POST memory resize
|
||||||
|
Data Format 7: None
|
||||||
|
Descriptor 8: POST error
|
||||||
|
Data Format 8: POST results bitmap
|
||||||
|
Descriptor 9: PCI parity error
|
||||||
|
Data Format 9: Multiple-event handle
|
||||||
|
Descriptor 10: PCI system error
|
||||||
|
Data Format 10: Multiple-event handle
|
||||||
|
Descriptor 11: CPU failure
|
||||||
|
Data Format 11: None
|
||||||
|
Descriptor 12: EISA failsafe timer timeout
|
||||||
|
Data Format 12: None
|
||||||
|
Descriptor 13: Correctable memory log disabled
|
||||||
|
Data Format 13: None
|
||||||
|
Descriptor 14: Logging disabled
|
||||||
|
Data Format 14: None
|
||||||
|
Descriptor 15: System limit exceeded
|
||||||
|
Data Format 15: None
|
||||||
|
Descriptor 16: Asynchronous hardware timer expired
|
||||||
|
Data Format 16: None
|
||||||
|
Descriptor 17: System configuration information
|
||||||
|
Data Format 17: None
|
||||||
|
Descriptor 18: Hard disk information
|
||||||
|
Data Format 18: None
|
||||||
|
Descriptor 19: System reconfigured
|
||||||
|
Data Format 19: None
|
||||||
|
Descriptor 20: Uncorrectable CPU-complex error
|
||||||
|
Data Format 20: None
|
||||||
|
Descriptor 21: Log area reset/cleared
|
||||||
|
Data Format 21: None
|
||||||
|
Descriptor 22: System boot
|
||||||
|
Data Format 22: None
|
||||||
|
Descriptor 23: End of log
|
||||||
|
Data Format 23: None
|
||||||
|
Descriptor 24: OEM-specific
|
||||||
|
Data Format 24: OEM-specific
|
||||||
|
Descriptor 25: OEM-specific
|
||||||
|
Data Format 25: OEM-specific
|
||||||
|
|
||||||
|
Handle 0x003B, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: CPU Internal L1
|
||||||
|
Configuration: Enabled, Not Socketed, Level 1
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 640 kB
|
||||||
|
Maximum Size: 640 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Unknown
|
||||||
|
Installed SRAM Type: Unknown
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Parity
|
||||||
|
System Type: Other
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x003C, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: CPU Internal L2
|
||||||
|
Configuration: Enabled, Not Socketed, Level 2
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 2560 kB
|
||||||
|
Maximum Size: 2560 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Unknown
|
||||||
|
Installed SRAM Type: Unknown
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x003D, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: CPU Internal L3
|
||||||
|
Configuration: Enabled, Not Socketed, Level 3
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 25600 kB
|
||||||
|
Maximum Size: 25600 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Unknown
|
||||||
|
Installed SRAM Type: Unknown
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 20-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x003E, DMI type 4, 42 bytes
|
||||||
|
Processor Information
|
||||||
|
Socket Designation: CPU1
|
||||||
|
Type: Central Processor
|
||||||
|
Family: Xeon
|
||||||
|
Manufacturer: Intel
|
||||||
|
ID: F1 06 04 00 FF FB EB BF
|
||||||
|
Signature: Type 0, Family 6, Model 79, Stepping 1
|
||||||
|
Flags:
|
||||||
|
FPU (Floating-point unit on-chip)
|
||||||
|
VME (Virtual mode extension)
|
||||||
|
DE (Debugging extension)
|
||||||
|
PSE (Page size extension)
|
||||||
|
TSC (Time stamp counter)
|
||||||
|
MSR (Model specific registers)
|
||||||
|
PAE (Physical address extension)
|
||||||
|
MCE (Machine check exception)
|
||||||
|
CX8 (CMPXCHG8 instruction supported)
|
||||||
|
APIC (On-chip APIC hardware supported)
|
||||||
|
SEP (Fast system call)
|
||||||
|
MTRR (Memory type range registers)
|
||||||
|
PGE (Page global enable)
|
||||||
|
MCA (Machine check architecture)
|
||||||
|
CMOV (Conditional move instruction supported)
|
||||||
|
PAT (Page attribute table)
|
||||||
|
PSE-36 (36-bit page size extension)
|
||||||
|
CLFSH (CLFLUSH instruction supported)
|
||||||
|
DS (Debug store)
|
||||||
|
ACPI (ACPI supported)
|
||||||
|
MMX (MMX technology supported)
|
||||||
|
FXSR (FXSAVE and FXSTOR instructions supported)
|
||||||
|
SSE (Streaming SIMD extensions)
|
||||||
|
SSE2 (Streaming SIMD extensions 2)
|
||||||
|
SS (Self-snoop)
|
||||||
|
HTT (Multi-threading)
|
||||||
|
TM (Thermal monitor supported)
|
||||||
|
PBE (Pending break enabled)
|
||||||
|
Version: Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz
|
||||||
|
Voltage: 1.8 V
|
||||||
|
External Clock: 100 MHz
|
||||||
|
Max Speed: 4000 MHz
|
||||||
|
Current Speed: 2200 MHz
|
||||||
|
Status: Populated, Enabled
|
||||||
|
Upgrade: Socket LGA2011-3
|
||||||
|
L1 Cache Handle: 0x003B
|
||||||
|
L2 Cache Handle: 0x003C
|
||||||
|
L3 Cache Handle: 0x003D
|
||||||
|
Serial Number: Not Specified
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Part Number: Not Specified
|
||||||
|
Core Count: 10
|
||||||
|
Core Enabled: 10
|
||||||
|
Thread Count: 20
|
||||||
|
Characteristics:
|
||||||
|
64-bit capable
|
||||||
|
Multi-Core
|
||||||
|
Hardware Thread
|
||||||
|
Execute Protection
|
||||||
|
Enhanced Virtualization
|
||||||
|
Power/Performance Control
|
||||||
|
|
||||||
|
Handle 0x003F, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: CPU Internal L1
|
||||||
|
Configuration: Enabled, Not Socketed, Level 1
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 640 kB
|
||||||
|
Maximum Size: 640 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Unknown
|
||||||
|
Installed SRAM Type: Unknown
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Parity
|
||||||
|
System Type: Other
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0040, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: CPU Internal L2
|
||||||
|
Configuration: Enabled, Not Socketed, Level 2
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 2560 kB
|
||||||
|
Maximum Size: 2560 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Unknown
|
||||||
|
Installed SRAM Type: Unknown
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0041, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: CPU Internal L3
|
||||||
|
Configuration: Enabled, Not Socketed, Level 3
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 25600 kB
|
||||||
|
Maximum Size: 25600 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Unknown
|
||||||
|
Installed SRAM Type: Unknown
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 20-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0042, DMI type 4, 42 bytes
|
||||||
|
Processor Information
|
||||||
|
Socket Designation: CPU2
|
||||||
|
Type: Central Processor
|
||||||
|
Family: Xeon
|
||||||
|
Manufacturer: Intel
|
||||||
|
ID: F1 06 04 00 FF FB EB BF
|
||||||
|
Signature: Type 0, Family 6, Model 79, Stepping 1
|
||||||
|
Flags:
|
||||||
|
FPU (Floating-point unit on-chip)
|
||||||
|
VME (Virtual mode extension)
|
||||||
|
DE (Debugging extension)
|
||||||
|
PSE (Page size extension)
|
||||||
|
TSC (Time stamp counter)
|
||||||
|
MSR (Model specific registers)
|
||||||
|
PAE (Physical address extension)
|
||||||
|
MCE (Machine check exception)
|
||||||
|
CX8 (CMPXCHG8 instruction supported)
|
||||||
|
APIC (On-chip APIC hardware supported)
|
||||||
|
SEP (Fast system call)
|
||||||
|
MTRR (Memory type range registers)
|
||||||
|
PGE (Page global enable)
|
||||||
|
MCA (Machine check architecture)
|
||||||
|
CMOV (Conditional move instruction supported)
|
||||||
|
PAT (Page attribute table)
|
||||||
|
PSE-36 (36-bit page size extension)
|
||||||
|
CLFSH (CLFLUSH instruction supported)
|
||||||
|
DS (Debug store)
|
||||||
|
ACPI (ACPI supported)
|
||||||
|
MMX (MMX technology supported)
|
||||||
|
FXSR (FXSAVE and FXSTOR instructions supported)
|
||||||
|
SSE (Streaming SIMD extensions)
|
||||||
|
SSE2 (Streaming SIMD extensions 2)
|
||||||
|
SS (Self-snoop)
|
||||||
|
HTT (Multi-threading)
|
||||||
|
TM (Thermal monitor supported)
|
||||||
|
PBE (Pending break enabled)
|
||||||
|
Version: Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz
|
||||||
|
Voltage: 1.8 V
|
||||||
|
External Clock: 100 MHz
|
||||||
|
Max Speed: 4000 MHz
|
||||||
|
Current Speed: 2200 MHz
|
||||||
|
Status: Populated, Enabled
|
||||||
|
Upgrade: Socket LGA2011-3
|
||||||
|
L1 Cache Handle: 0x003F
|
||||||
|
L2 Cache Handle: 0x0040
|
||||||
|
L3 Cache Handle: 0x0041
|
||||||
|
Serial Number: Not Specified
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Part Number: Not Specified
|
||||||
|
Core Count: 10
|
||||||
|
Core Enabled: 10
|
||||||
|
Thread Count: 20
|
||||||
|
Characteristics:
|
||||||
|
64-bit capable
|
||||||
|
Multi-Core
|
||||||
|
Hardware Thread
|
||||||
|
Execute Protection
|
||||||
|
Enhanced Virtualization
|
||||||
|
Power/Performance Control
|
||||||
|
|
||||||
|
Handle 0x0043, DMI type 40, 27 bytes
|
||||||
|
Additional Information 1
|
||||||
|
|
||||||
|
Handle 0x0044, DMI type 40, 27 bytes
|
||||||
|
Additional Information 1
|
||||||
|
|
||||||
|
Handle 0x0045, DMI type 40, 27 bytes
|
||||||
|
Additional Information 1
|
||||||
|
|
||||||
|
Handle 0x0046, DMI type 40, 27 bytes
|
||||||
|
Additional Information 1
|
||||||
|
|
||||||
|
Handle 0x0047, DMI type 127, 4 bytes
|
||||||
|
End Of Table
|
||||||
|
|
536
tests/fixtures/dmidecode/SYS-5039MS-H12TRF-OS012.txt
vendored
Normal file
536
tests/fixtures/dmidecode/SYS-5039MS-H12TRF-OS012.txt
vendored
Normal file
|
@ -0,0 +1,536 @@
|
||||||
|
# dmidecode 3.1
|
||||||
|
Getting SMBIOS data from sysfs.
|
||||||
|
SMBIOS 3.0 present.
|
||||||
|
32 structures occupying 2366 bytes.
|
||||||
|
Table at 0x6FB76000.
|
||||||
|
|
||||||
|
Handle 0x0000, DMI type 0, 24 bytes
|
||||||
|
BIOS Information
|
||||||
|
Vendor: American Megatrends Inc.
|
||||||
|
Version: 2.2
|
||||||
|
Release Date: 05/16/2018
|
||||||
|
Address: 0xF0000
|
||||||
|
Runtime Size: 64 kB
|
||||||
|
ROM Size: 16 MB
|
||||||
|
Characteristics:
|
||||||
|
PCI is supported
|
||||||
|
BIOS is upgradeable
|
||||||
|
BIOS shadowing is allowed
|
||||||
|
Boot from CD is supported
|
||||||
|
Selectable boot is supported
|
||||||
|
BIOS ROM is socketed
|
||||||
|
EDD is supported
|
||||||
|
5.25"/1.2 MB floppy services are supported (int 13h)
|
||||||
|
3.5"/720 kB floppy services are supported (int 13h)
|
||||||
|
3.5"/2.88 MB floppy services are supported (int 13h)
|
||||||
|
Print screen service is supported (int 5h)
|
||||||
|
Serial services are supported (int 14h)
|
||||||
|
Printer services are supported (int 17h)
|
||||||
|
ACPI is supported
|
||||||
|
USB legacy is supported
|
||||||
|
BIOS boot specification is supported
|
||||||
|
Targeted content distribution is supported
|
||||||
|
UEFI is supported
|
||||||
|
BIOS Revision: 5.11
|
||||||
|
|
||||||
|
Handle 0x0001, DMI type 1, 27 bytes
|
||||||
|
System Information
|
||||||
|
Manufacturer: Supermicro
|
||||||
|
Product Name: SYS-5039MS-H12TRF-OS012
|
||||||
|
Version: 0123456789
|
||||||
|
Serial Number: E235735X6B01665
|
||||||
|
UUID: 00000000-0000-0000-0000-0CC47AE14338
|
||||||
|
Wake-up Type: Power Switch
|
||||||
|
SKU Number: To be filled by O.E.M.
|
||||||
|
Family: To be filled by O.E.M.
|
||||||
|
|
||||||
|
Handle 0x0002, DMI type 2, 15 bytes
|
||||||
|
Base Board Information
|
||||||
|
Manufacturer: Supermicro
|
||||||
|
Product Name: X11SSE-F
|
||||||
|
Version: 1.01
|
||||||
|
Serial Number: ZM169S040205
|
||||||
|
Asset Tag: To be filled by O.E.M.
|
||||||
|
Features:
|
||||||
|
Board is a hosting board
|
||||||
|
Board is replaceable
|
||||||
|
Location In Chassis: To be filled by O.E.M.
|
||||||
|
Chassis Handle: 0x0003
|
||||||
|
Type: Motherboard
|
||||||
|
Contained Object Handles: 0
|
||||||
|
|
||||||
|
Handle 0x0003, DMI type 3, 22 bytes
|
||||||
|
Chassis Information
|
||||||
|
Manufacturer: Supermicro
|
||||||
|
Type: Other
|
||||||
|
Lock: Not Present
|
||||||
|
Version: 0123456789
|
||||||
|
Serial Number: C9390AF40A20098
|
||||||
|
Asset Tag: To be filled by O.E.M.
|
||||||
|
Boot-up State: Safe
|
||||||
|
Power Supply State: Safe
|
||||||
|
Thermal State: Safe
|
||||||
|
Security Status: None
|
||||||
|
OEM Information: 0x00000000
|
||||||
|
Height: Unspecified
|
||||||
|
Number Of Power Cords: 1
|
||||||
|
Contained Elements: 0
|
||||||
|
SKU Number: To be filled by O.E.M.
|
||||||
|
|
||||||
|
Handle 0x0004, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: CPU MICRO-LP PCI-E 3.0 X8
|
||||||
|
Type: x8 PCI Express 3 x8
|
||||||
|
Current Usage: In Use
|
||||||
|
Length: Short
|
||||||
|
ID: 1
|
||||||
|
Characteristics:
|
||||||
|
3.3 V is provided
|
||||||
|
Opening is shared
|
||||||
|
PME signal is supported
|
||||||
|
Bus Address: 0000:01:00.0
|
||||||
|
|
||||||
|
Handle 0x0005, DMI type 11, 5 bytes
|
||||||
|
OEM Strings
|
||||||
|
String 1: Intel Skylake-S/Skylake-H/Greenlow
|
||||||
|
String 2: Supermicro motherboard-X11 Series
|
||||||
|
|
||||||
|
Handle 0x0006, DMI type 32, 20 bytes
|
||||||
|
System Boot Information
|
||||||
|
Status: No errors detected
|
||||||
|
|
||||||
|
Handle 0x0007, DMI type 39, 22 bytes
|
||||||
|
System Power Supply
|
||||||
|
Power Unit Group: 1
|
||||||
|
Location: PSU1
|
||||||
|
Name: PWS-2K04F-1R
|
||||||
|
Manufacturer: SUPERMICRO
|
||||||
|
Serial Number: P2K4FCG37KT0851
|
||||||
|
Asset Tag: N/A
|
||||||
|
Model Part Number: PWS-2K04F-1R
|
||||||
|
Revision: 1.0
|
||||||
|
Max Power Capacity: 2000 W
|
||||||
|
Status: Present, OK
|
||||||
|
Type: Switching
|
||||||
|
Input Voltage Range Switching: Auto-switch
|
||||||
|
Plugged: Yes
|
||||||
|
Hot Replaceable: No
|
||||||
|
|
||||||
|
Handle 0x0008, DMI type 39, 22 bytes
|
||||||
|
System Power Supply
|
||||||
|
Power Unit Group: 2
|
||||||
|
Location: PSU2
|
||||||
|
Name: PWS-2K04F-1R
|
||||||
|
Manufacturer: SUPERMICRO
|
||||||
|
Serial Number: P2K4FCG37KT0852
|
||||||
|
Asset Tag: N/A
|
||||||
|
Model Part Number: PWS-2K04F-1R
|
||||||
|
Revision: 1.0
|
||||||
|
Max Power Capacity: 2000 W
|
||||||
|
Status: Present, OK
|
||||||
|
Type: Switching
|
||||||
|
Input Voltage Range Switching: Auto-switch
|
||||||
|
Plugged: Yes
|
||||||
|
Hot Replaceable: No
|
||||||
|
|
||||||
|
Handle 0x0009, DMI type 41, 11 bytes
|
||||||
|
Onboard Device
|
||||||
|
Reference Designation: ASPEED Video AST2400
|
||||||
|
Type: Video
|
||||||
|
Status: Enabled
|
||||||
|
Type Instance: 1
|
||||||
|
Bus Address: 0000:04:00.0
|
||||||
|
|
||||||
|
Handle 0x000A, DMI type 38, 18 bytes
|
||||||
|
IPMI Device Information
|
||||||
|
Interface Type: KCS (Keyboard Control Style)
|
||||||
|
Specification Version: 2.0
|
||||||
|
I2C Slave Address: 0x10
|
||||||
|
NV Storage Device: Not Present
|
||||||
|
Base Address: 0x0000000000000CA2 (I/O)
|
||||||
|
Register Spacing: Successive Byte Boundaries
|
||||||
|
|
||||||
|
Handle 0x000B, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: L1 Cache
|
||||||
|
Configuration: Enabled, Not Socketed, Level 1
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 128 kB
|
||||||
|
Maximum Size: 128 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Synchronous
|
||||||
|
Installed SRAM Type: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Parity
|
||||||
|
System Type: Data
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x000C, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: L1 Cache
|
||||||
|
Configuration: Enabled, Not Socketed, Level 1
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 128 kB
|
||||||
|
Maximum Size: 128 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Synchronous
|
||||||
|
Installed SRAM Type: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Parity
|
||||||
|
System Type: Instruction
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x000D, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: L2 Cache
|
||||||
|
Configuration: Enabled, Not Socketed, Level 2
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 1024 kB
|
||||||
|
Maximum Size: 1024 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Synchronous
|
||||||
|
Installed SRAM Type: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 4-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x000E, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: L3 Cache
|
||||||
|
Configuration: Enabled, Not Socketed, Level 3
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 8192 kB
|
||||||
|
Maximum Size: 8192 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Synchronous
|
||||||
|
Installed SRAM Type: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Multi-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 16-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x000F, DMI type 4, 48 bytes
|
||||||
|
Processor Information
|
||||||
|
Socket Designation: CPU
|
||||||
|
Type: Central Processor
|
||||||
|
Family: Xeon
|
||||||
|
Manufacturer: Intel(R) Corporation
|
||||||
|
ID: E3 06 05 00 FF FB EB BF
|
||||||
|
Signature: Type 0, Family 6, Model 94, Stepping 3
|
||||||
|
Flags:
|
||||||
|
FPU (Floating-point unit on-chip)
|
||||||
|
VME (Virtual mode extension)
|
||||||
|
DE (Debugging extension)
|
||||||
|
PSE (Page size extension)
|
||||||
|
TSC (Time stamp counter)
|
||||||
|
MSR (Model specific registers)
|
||||||
|
PAE (Physical address extension)
|
||||||
|
MCE (Machine check exception)
|
||||||
|
CX8 (CMPXCHG8 instruction supported)
|
||||||
|
APIC (On-chip APIC hardware supported)
|
||||||
|
SEP (Fast system call)
|
||||||
|
MTRR (Memory type range registers)
|
||||||
|
PGE (Page global enable)
|
||||||
|
MCA (Machine check architecture)
|
||||||
|
CMOV (Conditional move instruction supported)
|
||||||
|
PAT (Page attribute table)
|
||||||
|
PSE-36 (36-bit page size extension)
|
||||||
|
CLFSH (CLFLUSH instruction supported)
|
||||||
|
DS (Debug store)
|
||||||
|
ACPI (ACPI supported)
|
||||||
|
MMX (MMX technology supported)
|
||||||
|
FXSR (FXSAVE and FXSTOR instructions supported)
|
||||||
|
SSE (Streaming SIMD extensions)
|
||||||
|
SSE2 (Streaming SIMD extensions 2)
|
||||||
|
SS (Self-snoop)
|
||||||
|
HTT (Multi-threading)
|
||||||
|
TM (Thermal monitor supported)
|
||||||
|
PBE (Pending break enabled)
|
||||||
|
Version: Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz
|
||||||
|
Voltage: 1.1 V
|
||||||
|
External Clock: 100 MHz
|
||||||
|
Max Speed: 3900 MHz
|
||||||
|
Current Speed: 3500 MHz
|
||||||
|
Status: Populated, Enabled
|
||||||
|
Upgrade: Other
|
||||||
|
L1 Cache Handle: 0x000C
|
||||||
|
L2 Cache Handle: 0x000D
|
||||||
|
L3 Cache Handle: 0x000E
|
||||||
|
Serial Number: To Be Filled By O.E.M.
|
||||||
|
Asset Tag: To Be Filled By O.E.M.
|
||||||
|
Part Number: To Be Filled By O.E.M.
|
||||||
|
Core Count: 4
|
||||||
|
Core Enabled: 4
|
||||||
|
Thread Count: 8
|
||||||
|
Characteristics:
|
||||||
|
64-bit capable
|
||||||
|
Multi-Core
|
||||||
|
Hardware Thread
|
||||||
|
Execute Protection
|
||||||
|
Enhanced Virtualization
|
||||||
|
Power/Performance Control
|
||||||
|
|
||||||
|
Handle 0x0010, DMI type 16, 23 bytes
|
||||||
|
Physical Memory Array
|
||||||
|
Location: System Board Or Motherboard
|
||||||
|
Use: System Memory
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
Maximum Capacity: 64 GB
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Number Of Devices: 4
|
||||||
|
|
||||||
|
Handle 0x0011, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0010
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: Unknown
|
||||||
|
Data Width: Unknown
|
||||||
|
Size: No Module Installed
|
||||||
|
Form Factor: Unknown
|
||||||
|
Set: None
|
||||||
|
Locator: DIMMA1
|
||||||
|
Bank Locator: P0_Node0_Channel0_Dimm0
|
||||||
|
Type: Unknown
|
||||||
|
Type Detail: None
|
||||||
|
Speed: Unknown
|
||||||
|
Manufacturer: Not Specified
|
||||||
|
Serial Number: Not Specified
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Part Number: Not Specified
|
||||||
|
Rank: Unknown
|
||||||
|
Configured Clock Speed: Unknown
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x0012, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0010
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: DIMMA2
|
||||||
|
Bank Locator: P0_Node0_Channel0_Dimm1
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: 2400 MT/s
|
||||||
|
Manufacturer: Micron
|
||||||
|
Serial Number: 13DA8BB7
|
||||||
|
Asset Tag: DIMMA2_AssetTag(16/36)
|
||||||
|
Part Number: 18ADF2G72AZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MT/s
|
||||||
|
Minimum Voltage: 1.2 V
|
||||||
|
Maximum Voltage: 1.2 V
|
||||||
|
Configured Voltage: 1.2 V
|
||||||
|
|
||||||
|
Handle 0x0013, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0010
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: Unknown
|
||||||
|
Data Width: Unknown
|
||||||
|
Size: No Module Installed
|
||||||
|
Form Factor: Unknown
|
||||||
|
Set: None
|
||||||
|
Locator: DIMMB1
|
||||||
|
Bank Locator: P0_Node0_Channel1_Dimm0
|
||||||
|
Type: Unknown
|
||||||
|
Type Detail: None
|
||||||
|
Speed: Unknown
|
||||||
|
Manufacturer: Not Specified
|
||||||
|
Serial Number: Not Specified
|
||||||
|
Asset Tag: Not Specified
|
||||||
|
Part Number: Not Specified
|
||||||
|
Rank: Unknown
|
||||||
|
Configured Clock Speed: Unknown
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x0014, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0010
|
||||||
|
Error Information Handle: Not Provided
|
||||||
|
Total Width: 72 bits
|
||||||
|
Data Width: 64 bits
|
||||||
|
Size: 16384 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: DIMMB2
|
||||||
|
Bank Locator: P0_Node0_Channel1_Dimm1
|
||||||
|
Type: DDR4
|
||||||
|
Type Detail: Synchronous
|
||||||
|
Speed: 2400 MT/s
|
||||||
|
Manufacturer: Micron
|
||||||
|
Serial Number: 13DA8C08
|
||||||
|
Asset Tag: DIMMB2_AssetTag(16/36)
|
||||||
|
Part Number: 18ADF2G72AZ-2G3B1
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 2133 MT/s
|
||||||
|
Minimum Voltage: 1.2 V
|
||||||
|
Maximum Voltage: 1.2 V
|
||||||
|
Configured Voltage: 1.2 V
|
||||||
|
|
||||||
|
Handle 0x0015, DMI type 19, 31 bytes
|
||||||
|
Memory Array Mapped Address
|
||||||
|
Starting Address: 0x00000000000
|
||||||
|
Ending Address: 0x007FFFFFFFF
|
||||||
|
Range Size: 32 GB
|
||||||
|
Physical Array Handle: 0x0010
|
||||||
|
Partition Width: 2
|
||||||
|
|
||||||
|
Handle 0x0016, DMI type 15, 73 bytes
|
||||||
|
System Event Log
|
||||||
|
Area Length: 65535 bytes
|
||||||
|
Header Start Offset: 0x0000
|
||||||
|
Header Length: 16 bytes
|
||||||
|
Data Start Offset: 0x0010
|
||||||
|
Access Method: Memory-mapped physical 32-bit address
|
||||||
|
Access Address: 0xFF610000
|
||||||
|
Status: Valid, Not Full
|
||||||
|
Change Token: 0x00000001
|
||||||
|
Header Format: Type 1
|
||||||
|
Supported Log Type Descriptors: 25
|
||||||
|
Descriptor 1: Single-bit ECC memory error
|
||||||
|
Data Format 1: Multiple-event handle
|
||||||
|
Descriptor 2: Multi-bit ECC memory error
|
||||||
|
Data Format 2: Multiple-event handle
|
||||||
|
Descriptor 3: Parity memory error
|
||||||
|
Data Format 3: None
|
||||||
|
Descriptor 4: Bus timeout
|
||||||
|
Data Format 4: None
|
||||||
|
Descriptor 5: I/O channel block
|
||||||
|
Data Format 5: None
|
||||||
|
Descriptor 6: Software NMI
|
||||||
|
Data Format 6: None
|
||||||
|
Descriptor 7: POST memory resize
|
||||||
|
Data Format 7: None
|
||||||
|
Descriptor 8: POST error
|
||||||
|
Data Format 8: POST results bitmap
|
||||||
|
Descriptor 9: PCI parity error
|
||||||
|
Data Format 9: Multiple-event handle
|
||||||
|
Descriptor 10: PCI system error
|
||||||
|
Data Format 10: Multiple-event handle
|
||||||
|
Descriptor 11: CPU failure
|
||||||
|
Data Format 11: None
|
||||||
|
Descriptor 12: EISA failsafe timer timeout
|
||||||
|
Data Format 12: None
|
||||||
|
Descriptor 13: Correctable memory log disabled
|
||||||
|
Data Format 13: None
|
||||||
|
Descriptor 14: Logging disabled
|
||||||
|
Data Format 14: None
|
||||||
|
Descriptor 15: System limit exceeded
|
||||||
|
Data Format 15: None
|
||||||
|
Descriptor 16: Asynchronous hardware timer expired
|
||||||
|
Data Format 16: None
|
||||||
|
Descriptor 17: System configuration information
|
||||||
|
Data Format 17: None
|
||||||
|
Descriptor 18: Hard disk information
|
||||||
|
Data Format 18: None
|
||||||
|
Descriptor 19: System reconfigured
|
||||||
|
Data Format 19: None
|
||||||
|
Descriptor 20: Uncorrectable CPU-complex error
|
||||||
|
Data Format 20: None
|
||||||
|
Descriptor 21: Log area reset/cleared
|
||||||
|
Data Format 21: None
|
||||||
|
Descriptor 22: System boot
|
||||||
|
Data Format 22: None
|
||||||
|
Descriptor 23: End of log
|
||||||
|
Data Format 23: None
|
||||||
|
Descriptor 24: OEM-specific
|
||||||
|
Data Format 24: OEM-specific
|
||||||
|
Descriptor 25: OEM-specific
|
||||||
|
Data Format 25: OEM-specific
|
||||||
|
|
||||||
|
Handle 0x0017, DMI type 20, 35 bytes
|
||||||
|
Memory Device Mapped Address
|
||||||
|
Starting Address: 0x00000000000
|
||||||
|
Ending Address: 0x003FFFFFFFF
|
||||||
|
Range Size: 16 GB
|
||||||
|
Physical Device Handle: 0x0012
|
||||||
|
Memory Array Mapped Address Handle: 0x0015
|
||||||
|
Partition Row Position: Unknown
|
||||||
|
Interleave Position: 1
|
||||||
|
Interleaved Data Depth: 2
|
||||||
|
|
||||||
|
Handle 0x0018, DMI type 20, 35 bytes
|
||||||
|
Memory Device Mapped Address
|
||||||
|
Starting Address: 0x00400000000
|
||||||
|
Ending Address: 0x007FFFFFFFF
|
||||||
|
Range Size: 16 GB
|
||||||
|
Physical Device Handle: 0x0014
|
||||||
|
Memory Array Mapped Address Handle: 0x0015
|
||||||
|
Partition Row Position: Unknown
|
||||||
|
Interleave Position: 2
|
||||||
|
Interleaved Data Depth: 2
|
||||||
|
|
||||||
|
Handle 0x0019, DMI type 221, 26 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
DD 1A 19 00 03 01 00 04 01 00 08 00 02 00 00 00
|
||||||
|
00 C6 00 03 00 00 05 00 00 00
|
||||||
|
Strings:
|
||||||
|
Reference Code - CPU
|
||||||
|
uCode Version
|
||||||
|
TXT ACM version
|
||||||
|
|
||||||
|
Handle 0x001A, DMI type 221, 68 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
DD 44 1A 00 09 01 00 04 01 00 08 00 02 03 FF FF
|
||||||
|
FF FF FF 04 00 FF FF FF 31 00 05 00 FF FF FF 31
|
||||||
|
00 06 00 FF FF FF FF FF 07 00 3E 00 00 00 00 08
|
||||||
|
00 34 00 00 00 00 09 00 3E 00 00 00 00 0A 00 34
|
||||||
|
00 00 00 00
|
||||||
|
Strings:
|
||||||
|
Reference Code - SKL PCH
|
||||||
|
PCH-CRID Status
|
||||||
|
Disabled
|
||||||
|
PCH-CRID Original Value
|
||||||
|
PCH-CRID New Value
|
||||||
|
OPROM - RST - RAID
|
||||||
|
SKL PCH H Bx Hsio Version
|
||||||
|
SKL PCH H Dx Hsio Version
|
||||||
|
SKL PCH LP Bx Hsio Version
|
||||||
|
SKL PCH LP Cx Hsio Version
|
||||||
|
|
||||||
|
Handle 0x001B, DMI type 221, 54 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
DD 36 1B 00 07 01 00 04 01 00 08 00 02 00 02 01
|
||||||
|
00 00 00 03 00 04 01 00 00 00 04 05 FF FF FF FF
|
||||||
|
FF 06 00 FF FF FF 07 00 07 00 FF FF FF 07 00 08
|
||||||
|
00 FF FF FF 00 00
|
||||||
|
Strings:
|
||||||
|
Reference Code - SA - System Agent
|
||||||
|
Reference Code - MRC
|
||||||
|
SA - PCIe Version
|
||||||
|
SA-CRID Status
|
||||||
|
Disabled
|
||||||
|
SA-CRID Original Value
|
||||||
|
SA-CRID New Value
|
||||||
|
OPROM - VBIOS
|
||||||
|
|
||||||
|
Handle 0x001C, DMI type 40, 27 bytes
|
||||||
|
Additional Information 1
|
||||||
|
|
||||||
|
Handle 0x001D, DMI type 40, 27 bytes
|
||||||
|
Additional Information 1
|
||||||
|
|
||||||
|
Handle 0x001E, DMI type 136, 6 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
88 06 1E 00 00 00
|
||||||
|
|
||||||
|
Handle 0x001F, DMI type 127, 4 bytes
|
||||||
|
End Of Table
|
||||||
|
|
571
tests/fixtures/dmidecode/unknown.txt
vendored
Normal file
571
tests/fixtures/dmidecode/unknown.txt
vendored
Normal file
|
@ -0,0 +1,571 @@
|
||||||
|
# dmidecode 3.1
|
||||||
|
Getting SMBIOS data from sysfs.
|
||||||
|
SMBIOS 2.8 present.
|
||||||
|
44 structures occupying 2055 bytes.
|
||||||
|
Table at 0x000E4E00.
|
||||||
|
|
||||||
|
Handle 0x0000, DMI type 0, 24 bytes
|
||||||
|
BIOS Information
|
||||||
|
Vendor: Online Labs
|
||||||
|
Version: 00.00.00.0007
|
||||||
|
Release Date: 03/04/2016
|
||||||
|
Address: 0xE0000
|
||||||
|
Runtime Size: 128 kB
|
||||||
|
ROM Size: 6144 kB
|
||||||
|
Characteristics:
|
||||||
|
PCI is supported
|
||||||
|
BIOS is upgradeable
|
||||||
|
BIOS shadowing is allowed
|
||||||
|
Boot from CD is supported
|
||||||
|
Selectable boot is supported
|
||||||
|
EDD is supported
|
||||||
|
Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)
|
||||||
|
Japanese floppy for Toshiba 1.2 MB is supported (int 13h)
|
||||||
|
5.25"/360 kB floppy services are supported (int 13h)
|
||||||
|
5.25"/1.2 MB floppy services are supported (int 13h)
|
||||||
|
3.5"/720 kB floppy services are supported (int 13h)
|
||||||
|
3.5"/2.88 MB floppy services are supported (int 13h)
|
||||||
|
8042 keyboard services are supported (int 9h)
|
||||||
|
CGA/mono video services are supported (int 10h)
|
||||||
|
ACPI is supported
|
||||||
|
USB legacy is supported
|
||||||
|
BIOS boot specification is supported
|
||||||
|
Targeted content distribution is supported
|
||||||
|
UEFI is supported
|
||||||
|
BIOS Revision: 0.0
|
||||||
|
|
||||||
|
Handle 0x0001, DMI type 1, 27 bytes
|
||||||
|
System Information
|
||||||
|
Manufacturer: Online Labs
|
||||||
|
Product Name: SR
|
||||||
|
Version: (^_^)
|
||||||
|
Serial Number: 42
|
||||||
|
UUID: 12345678-1234-5678-90AB-CDDEEFAABBCC
|
||||||
|
Wake-up Type: Power Switch
|
||||||
|
SKU Number: (^_^)
|
||||||
|
Family: Avoton
|
||||||
|
|
||||||
|
Handle 0x0002, DMI type 2, 15 bytes
|
||||||
|
Base Board Information
|
||||||
|
Manufacturer: Online Labs
|
||||||
|
Product Name: SR
|
||||||
|
Version: 42
|
||||||
|
Serial Number: 42
|
||||||
|
Asset Tag: 42
|
||||||
|
Features:
|
||||||
|
Board is a hosting board
|
||||||
|
Board is replaceable
|
||||||
|
Location In Chassis: <BAD INDEX>
|
||||||
|
Chassis Handle: 0x0003
|
||||||
|
Type: Motherboard
|
||||||
|
Contained Object Handles: 0
|
||||||
|
|
||||||
|
Handle 0x0003, DMI type 3, 22 bytes
|
||||||
|
Chassis Information
|
||||||
|
Manufacturer: Chassis Manufacturer
|
||||||
|
Type: Desktop
|
||||||
|
Lock: Not Present
|
||||||
|
Version: Chassis Version
|
||||||
|
Serial Number: Chassis Serial Number
|
||||||
|
Asset Tag: Chassis Asset Tag
|
||||||
|
Boot-up State: Safe
|
||||||
|
Power Supply State: Safe
|
||||||
|
Thermal State: Safe
|
||||||
|
Security Status: None
|
||||||
|
OEM Information: 0x00000000
|
||||||
|
Height: Unspecified
|
||||||
|
Number Of Power Cords: 1
|
||||||
|
Contained Elements: 0
|
||||||
|
SKU Number: SKU Number
|
||||||
|
|
||||||
|
Handle 0x0004, DMI type 4, 42 bytes
|
||||||
|
Processor Information
|
||||||
|
Socket Designation: CPU0
|
||||||
|
Type: Central Processor
|
||||||
|
Family: Atom
|
||||||
|
Manufacturer: Intel(R) Corporation
|
||||||
|
ID: D8 06 04 00 FF FB EB BF
|
||||||
|
Signature: Type 0, Family 6, Model 77, Stepping 8
|
||||||
|
Flags:
|
||||||
|
FPU (Floating-point unit on-chip)
|
||||||
|
VME (Virtual mode extension)
|
||||||
|
DE (Debugging extension)
|
||||||
|
PSE (Page size extension)
|
||||||
|
TSC (Time stamp counter)
|
||||||
|
MSR (Model specific registers)
|
||||||
|
PAE (Physical address extension)
|
||||||
|
MCE (Machine check exception)
|
||||||
|
CX8 (CMPXCHG8 instruction supported)
|
||||||
|
APIC (On-chip APIC hardware supported)
|
||||||
|
SEP (Fast system call)
|
||||||
|
MTRR (Memory type range registers)
|
||||||
|
PGE (Page global enable)
|
||||||
|
MCA (Machine check architecture)
|
||||||
|
CMOV (Conditional move instruction supported)
|
||||||
|
PAT (Page attribute table)
|
||||||
|
PSE-36 (36-bit page size extension)
|
||||||
|
CLFSH (CLFLUSH instruction supported)
|
||||||
|
DS (Debug store)
|
||||||
|
ACPI (ACPI supported)
|
||||||
|
MMX (MMX technology supported)
|
||||||
|
FXSR (FXSAVE and FXSTOR instructions supported)
|
||||||
|
SSE (Streaming SIMD extensions)
|
||||||
|
SSE2 (Streaming SIMD extensions 2)
|
||||||
|
SS (Self-snoop)
|
||||||
|
HTT (Multi-threading)
|
||||||
|
TM (Thermal monitor supported)
|
||||||
|
PBE (Pending break enabled)
|
||||||
|
Version: Intel(R) Atom(TM) CPU C2750 @ 2.40GHz
|
||||||
|
Voltage: 1.6 V
|
||||||
|
External Clock: 100 MHz
|
||||||
|
Max Speed: 2400 MHz
|
||||||
|
Current Speed: 2400 MHz
|
||||||
|
Status: Populated, Enabled
|
||||||
|
Upgrade: Socket LGA775
|
||||||
|
L1 Cache Handle: 0x0005
|
||||||
|
L2 Cache Handle: 0x0006
|
||||||
|
L3 Cache Handle: Not Provided
|
||||||
|
Serial Number: Not Specified
|
||||||
|
Asset Tag: UNKNOWN
|
||||||
|
Part Number: Not Specified
|
||||||
|
Core Count: 8
|
||||||
|
Core Enabled: 8
|
||||||
|
Thread Count: 8
|
||||||
|
Characteristics:
|
||||||
|
64-bit capable
|
||||||
|
|
||||||
|
Handle 0x0005, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: L1-Cache
|
||||||
|
Configuration: Enabled, Not Socketed, Level 1
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 448 kB
|
||||||
|
Maximum Size: 448 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Synchronous
|
||||||
|
Installed SRAM Type: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Instruction
|
||||||
|
Associativity: 8-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0006, DMI type 7, 19 bytes
|
||||||
|
Cache Information
|
||||||
|
Socket Designation: L2-Cache
|
||||||
|
Configuration: Enabled, Not Socketed, Level 2
|
||||||
|
Operational Mode: Write Back
|
||||||
|
Location: Internal
|
||||||
|
Installed Size: 4096 kB
|
||||||
|
Maximum Size: 4096 kB
|
||||||
|
Supported SRAM Types:
|
||||||
|
Synchronous
|
||||||
|
Installed SRAM Type: Synchronous
|
||||||
|
Speed: Unknown
|
||||||
|
Error Correction Type: Single-bit ECC
|
||||||
|
System Type: Unified
|
||||||
|
Associativity: 16-way Set-associative
|
||||||
|
|
||||||
|
Handle 0x0007, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: EC5
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: USB
|
||||||
|
External Connector Type: Access Bus (USB)
|
||||||
|
Port Type: USB
|
||||||
|
|
||||||
|
Handle 0x0008, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: EC6
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: USB
|
||||||
|
External Connector Type: Access Bus (USB)
|
||||||
|
Port Type: USB
|
||||||
|
|
||||||
|
Handle 0x0009, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: LAN1
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: 1G Network
|
||||||
|
External Connector Type: RJ-45
|
||||||
|
Port Type: Network Port
|
||||||
|
|
||||||
|
Handle 0x000A, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: LAN1
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: 1G Network
|
||||||
|
External Connector Type: RJ-45
|
||||||
|
Port Type: Network Port
|
||||||
|
|
||||||
|
Handle 0x000B, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: 10GLAN1
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: 10G Network
|
||||||
|
External Connector Type: RJ-45
|
||||||
|
Port Type: Network Port
|
||||||
|
|
||||||
|
Handle 0x000C, DMI type 8, 9 bytes
|
||||||
|
Port Connector Information
|
||||||
|
Internal Reference Designator: 10GLAN2
|
||||||
|
Internal Connector Type: None
|
||||||
|
External Reference Designator: 10G Network
|
||||||
|
External Connector Type: RJ-45
|
||||||
|
Port Type: Network Port
|
||||||
|
|
||||||
|
Handle 0x000D, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI_E_1
|
||||||
|
Type: x8 PCI Express x8
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Other
|
||||||
|
ID: 1
|
||||||
|
Characteristics:
|
||||||
|
PME signal is supported
|
||||||
|
Hot-plug devices are supported
|
||||||
|
Bus Address: 0000:00:01.0
|
||||||
|
|
||||||
|
Handle 0x000E, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI_E_2
|
||||||
|
Type: x4 PCI Express x4
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Other
|
||||||
|
ID: 2
|
||||||
|
Characteristics:
|
||||||
|
PME signal is supported
|
||||||
|
Hot-plug devices are supported
|
||||||
|
Bus Address: 0000:00:02.0
|
||||||
|
|
||||||
|
Handle 0x000F, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI_E_3
|
||||||
|
Type: x4 PCI Express x4
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Other
|
||||||
|
ID: 3
|
||||||
|
Characteristics:
|
||||||
|
PME signal is supported
|
||||||
|
Hot-plug devices are supported
|
||||||
|
Bus Address: 0000:04:08.0
|
||||||
|
|
||||||
|
Handle 0x0010, DMI type 9, 17 bytes
|
||||||
|
System Slot Information
|
||||||
|
Designation: PCI_E_4
|
||||||
|
Type: x16 PCI Express x16
|
||||||
|
Current Usage: Available
|
||||||
|
Length: Other
|
||||||
|
ID: 4
|
||||||
|
Characteristics:
|
||||||
|
PME signal is supported
|
||||||
|
Hot-plug devices are supported
|
||||||
|
Bus Address: 0000:04:09.0
|
||||||
|
|
||||||
|
Handle 0x0011, DMI type 11, 5 bytes
|
||||||
|
OEM Strings
|
||||||
|
String 1: OemString1
|
||||||
|
String 2: OemString2
|
||||||
|
String 3: OemString3
|
||||||
|
|
||||||
|
Handle 0x0012, DMI type 12, 5 bytes
|
||||||
|
System Configuration Options
|
||||||
|
Option 1: ConfigOptions1
|
||||||
|
Option 2: ConfigOptions2
|
||||||
|
Option 3: ConfigOptions3
|
||||||
|
|
||||||
|
Handle 0x0013, DMI type 13, 22 bytes
|
||||||
|
BIOS Language Information
|
||||||
|
Language Description Format: Long
|
||||||
|
Installable Languages: 4
|
||||||
|
en|US|iso8859-1,0
|
||||||
|
fr|CA|iso8859-1,0
|
||||||
|
zh|TW|unicode,0
|
||||||
|
ja|JP|unicode,0
|
||||||
|
Currently Installed Language: en|US|iso8859-1,0
|
||||||
|
|
||||||
|
Handle 0x0014, DMI type 15, 29 bytes
|
||||||
|
System Event Log
|
||||||
|
Area Length: 0 bytes
|
||||||
|
Header Start Offset: 0x0000
|
||||||
|
Header Length: 8192 bytes
|
||||||
|
Data Start Offset: 0x2000
|
||||||
|
Access Method: General-purpose non-volatile data functions
|
||||||
|
Access Address: 0x0000
|
||||||
|
Status: Valid, Not Full
|
||||||
|
Change Token: 0x12345678
|
||||||
|
Header Format: OEM-specific
|
||||||
|
Supported Log Type Descriptors: 3
|
||||||
|
Descriptor 1: POST memory resize
|
||||||
|
Data Format 1: None
|
||||||
|
Descriptor 2: POST error
|
||||||
|
Data Format 2: POST results bitmap
|
||||||
|
Descriptor 3: Log area reset/cleared
|
||||||
|
Data Format 3: None
|
||||||
|
|
||||||
|
Handle 0x0015, DMI type 16, 23 bytes
|
||||||
|
Physical Memory Array
|
||||||
|
Location: System Board Or Motherboard
|
||||||
|
Use: System Memory
|
||||||
|
Error Correction Type: None
|
||||||
|
Maximum Capacity: 64 GB
|
||||||
|
Error Information Handle: No Error
|
||||||
|
Number Of Devices: 4
|
||||||
|
|
||||||
|
Handle 0x0016, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0015
|
||||||
|
Error Information Handle: No Error
|
||||||
|
Total Width: Unknown
|
||||||
|
Data Width: Unknown
|
||||||
|
Size: 8192 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: DIMM0
|
||||||
|
Bank Locator: BANK 0
|
||||||
|
Type: DDR3
|
||||||
|
Type Detail: Synchronous Unbuffered (Unregistered)
|
||||||
|
Speed: 1600 MT/s
|
||||||
|
Manufacturer: Micron
|
||||||
|
Serial Number: 23115200
|
||||||
|
Asset Tag: 01
|
||||||
|
Part Number: DVM64453C DATARAM
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 1600 MT/s
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x0017, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0015
|
||||||
|
Error Information Handle: No Error
|
||||||
|
Total Width: Unknown
|
||||||
|
Data Width: Unknown
|
||||||
|
Size: 8192 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: DIMM0
|
||||||
|
Bank Locator: BANK 1
|
||||||
|
Type: DDR3
|
||||||
|
Type Detail: Synchronous Unbuffered (Unregistered)
|
||||||
|
Speed: 1600 MT/s
|
||||||
|
Manufacturer: Micron
|
||||||
|
Serial Number: 00001639
|
||||||
|
Asset Tag: 02
|
||||||
|
Part Number: DVM64453C DATARAM
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 1600 MT/s
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x0018, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0015
|
||||||
|
Error Information Handle: No Error
|
||||||
|
Total Width: Unknown
|
||||||
|
Data Width: Unknown
|
||||||
|
Size: 8192 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: DIMM1
|
||||||
|
Bank Locator: BANK 0
|
||||||
|
Type: DDR3
|
||||||
|
Type Detail: Synchronous Unbuffered (Unregistered)
|
||||||
|
Speed: 1600 MT/s
|
||||||
|
Manufacturer: Micron
|
||||||
|
Serial Number: 23115200
|
||||||
|
Asset Tag: 03
|
||||||
|
Part Number: DVM64453C DATARAM
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 1600 MT/s
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x0019, DMI type 17, 40 bytes
|
||||||
|
Memory Device
|
||||||
|
Array Handle: 0x0015
|
||||||
|
Error Information Handle: No Error
|
||||||
|
Total Width: Unknown
|
||||||
|
Data Width: Unknown
|
||||||
|
Size: 8192 MB
|
||||||
|
Form Factor: DIMM
|
||||||
|
Set: None
|
||||||
|
Locator: DIMM1
|
||||||
|
Bank Locator: BANK 1
|
||||||
|
Type: DDR3
|
||||||
|
Type Detail: Synchronous Unbuffered (Unregistered)
|
||||||
|
Speed: 1600 MT/s
|
||||||
|
Manufacturer: Micron
|
||||||
|
Serial Number: 23115200
|
||||||
|
Asset Tag: 04
|
||||||
|
Part Number: DVM64453C DATARAM
|
||||||
|
Rank: 2
|
||||||
|
Configured Clock Speed: 1600 MT/s
|
||||||
|
Minimum Voltage: Unknown
|
||||||
|
Maximum Voltage: Unknown
|
||||||
|
Configured Voltage: Unknown
|
||||||
|
|
||||||
|
Handle 0x001A, DMI type 19, 31 bytes
|
||||||
|
Memory Array Mapped Address
|
||||||
|
Starting Address: 0x00000000000
|
||||||
|
Ending Address: 0x007FFFFFFFF
|
||||||
|
Range Size: 32 GB
|
||||||
|
Physical Array Handle: 0x0015
|
||||||
|
Partition Width: 4
|
||||||
|
|
||||||
|
Handle 0x001B, DMI type 20, 35 bytes
|
||||||
|
Memory Device Mapped Address
|
||||||
|
Starting Address: 0x00000000000
|
||||||
|
Ending Address: 0x001FFFFFFFF
|
||||||
|
Range Size: 8 GB
|
||||||
|
Physical Device Handle: 0x0016
|
||||||
|
Memory Array Mapped Address Handle: 0x0015
|
||||||
|
Partition Row Position: Unknown
|
||||||
|
|
||||||
|
Handle 0x001C, DMI type 20, 35 bytes
|
||||||
|
Memory Device Mapped Address
|
||||||
|
Starting Address: 0x00200000000
|
||||||
|
Ending Address: 0x003FFFFFFFF
|
||||||
|
Range Size: 8 GB
|
||||||
|
Physical Device Handle: 0x0017
|
||||||
|
Memory Array Mapped Address Handle: 0x0015
|
||||||
|
Partition Row Position: Unknown
|
||||||
|
|
||||||
|
Handle 0x001D, DMI type 20, 35 bytes
|
||||||
|
Memory Device Mapped Address
|
||||||
|
Starting Address: 0x00400000000
|
||||||
|
Ending Address: 0x005FFFFFFFF
|
||||||
|
Range Size: 8 GB
|
||||||
|
Physical Device Handle: 0x0018
|
||||||
|
Memory Array Mapped Address Handle: 0x0015
|
||||||
|
Partition Row Position: Unknown
|
||||||
|
|
||||||
|
Handle 0x001E, DMI type 20, 35 bytes
|
||||||
|
Memory Device Mapped Address
|
||||||
|
Starting Address: 0x00600000000
|
||||||
|
Ending Address: 0x007FFFFFFFF
|
||||||
|
Range Size: 8 GB
|
||||||
|
Physical Device Handle: 0x0019
|
||||||
|
Memory Array Mapped Address Handle: 0x0015
|
||||||
|
Partition Row Position: Unknown
|
||||||
|
|
||||||
|
Handle 0x001F, DMI type 21, 7 bytes
|
||||||
|
Built-in Pointing Device
|
||||||
|
Type: Touch Pad
|
||||||
|
Interface: PS/2
|
||||||
|
Buttons: 4
|
||||||
|
|
||||||
|
Handle 0x0020, DMI type 22, 26 bytes
|
||||||
|
Portable Battery
|
||||||
|
Location: Fake
|
||||||
|
Manufacturer: -Virtual Battery 0-
|
||||||
|
Manufacture Date: 08/08/2010
|
||||||
|
Serial Number: Battery 0
|
||||||
|
Name: CRB Battery 0
|
||||||
|
Chemistry: Zinc Air
|
||||||
|
Design Capacity: Unknown
|
||||||
|
Design Voltage: Unknown
|
||||||
|
SBDS Version: LithiumPolymer
|
||||||
|
Maximum Error: Unknown
|
||||||
|
OEM-specific Information: 0x00000000
|
||||||
|
|
||||||
|
Handle 0x0021, DMI type 26, 24 bytes
|
||||||
|
Voltage Probe
|
||||||
|
Description: Voltage Probe Description
|
||||||
|
Location: Unknown
|
||||||
|
Status: Unknown
|
||||||
|
Maximum Value: Unknown
|
||||||
|
Minimum Value: Unknown
|
||||||
|
Resolution: Unknown
|
||||||
|
Tolerance: Unknown
|
||||||
|
Accuracy: Unknown
|
||||||
|
OEM-specific Information: 0x00008000
|
||||||
|
Nominal Value: 0.000 V
|
||||||
|
|
||||||
|
Handle 0x0022, DMI type 27, 15 bytes
|
||||||
|
Cooling Device
|
||||||
|
Temperature Probe Handle: 0x0023
|
||||||
|
Type: Fan
|
||||||
|
Status: OK
|
||||||
|
OEM-specific Information: 0x00000000
|
||||||
|
Nominal Speed: 8192 rpm
|
||||||
|
Description: Cooling Device Description
|
||||||
|
|
||||||
|
Handle 0x0023, DMI type 28, 24 bytes
|
||||||
|
Temperature Probe
|
||||||
|
Description: Temperature Probe Description
|
||||||
|
Location: Unknown
|
||||||
|
Status: Unknown
|
||||||
|
Maximum Value: Unknown
|
||||||
|
Minimum Value: Unknown
|
||||||
|
Resolution: Unknown
|
||||||
|
Tolerance: Unknown
|
||||||
|
Accuracy: Unknown
|
||||||
|
OEM-specific Information: 0x00008000
|
||||||
|
Nominal Value: 0.0 deg C
|
||||||
|
|
||||||
|
Handle 0x0024, DMI type 32, 11 bytes
|
||||||
|
System Boot Information
|
||||||
|
Status: No errors detected
|
||||||
|
|
||||||
|
Handle 0x0025, DMI type 39, 22 bytes
|
||||||
|
System Power Supply
|
||||||
|
Location: OEM Define 0
|
||||||
|
Name: OEM Define 1
|
||||||
|
Manufacturer: OEM Define 2
|
||||||
|
Serial Number: OEM Define 3
|
||||||
|
Asset Tag: OEM Define 4
|
||||||
|
Model Part Number: OEM Define 5
|
||||||
|
Revision: OEM Define 6
|
||||||
|
Max Power Capacity: 75 W
|
||||||
|
Status: Not Present
|
||||||
|
Type: Regulator
|
||||||
|
Input Voltage Range Switching: Auto-switch
|
||||||
|
Plugged: No
|
||||||
|
Hot Replaceable: No
|
||||||
|
|
||||||
|
Handle 0x0026, DMI type 40, 17 bytes
|
||||||
|
Additional Information 1
|
||||||
|
Referenced Handle: 0x000c
|
||||||
|
Referenced Offset: 0x05
|
||||||
|
String: PCIExpressx16
|
||||||
|
Value: 0xaa
|
||||||
|
Additional Information 2
|
||||||
|
Referenced Handle: 0x0000
|
||||||
|
Referenced Offset: 0x05
|
||||||
|
String: Compiler Version: VC 9.0
|
||||||
|
Value: 0x00
|
||||||
|
|
||||||
|
Handle 0x0027, DMI type 128, 8 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
80 08 27 00 55 AA 55 AA
|
||||||
|
Strings:
|
||||||
|
Oem Type 128 Test 1
|
||||||
|
Oem Type 128 Test 2
|
||||||
|
|
||||||
|
Handle 0x0028, DMI type 129, 8 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
81 08 28 00 01 01 02 01
|
||||||
|
Strings:
|
||||||
|
Insyde_ASF_001
|
||||||
|
Insyde_ASF_002
|
||||||
|
|
||||||
|
Handle 0x0029, DMI type 130, 20 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
82 14 29 00 24 41 4D 54 01 01 01 01 01 A5 1F 02
|
||||||
|
00 00 00 00
|
||||||
|
|
||||||
|
Handle 0x002A, DMI type 136, 6 bytes
|
||||||
|
OEM-specific Type
|
||||||
|
Header and Data:
|
||||||
|
88 06 2A 00 FF FF
|
||||||
|
|
||||||
|
Handle 0xFEFF, DMI type 127, 4 bytes
|
||||||
|
End Of Table
|
||||||
|
|
16
tests/fixtures/inventory/nvme.json
vendored
Normal file
16
tests/fixtures/inventory/nvme.json
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"Devices" : [
|
||||||
|
{
|
||||||
|
"DevicePath" : "/dev/nvme0n1",
|
||||||
|
"Firmware" : "10604103",
|
||||||
|
"Index" : 0,
|
||||||
|
"ModelNumber" : "KXG60ZNV1T02 NVMe TOSHIBA 1024GB",
|
||||||
|
"ProductName" : "Non-Volatile memory controller: Toshiba America Info Systems Device 0x011a",
|
||||||
|
"SerialNumber" : "19FA109SK07N",
|
||||||
|
"UsedBytes" : 1024209543168,
|
||||||
|
"MaximumLBA" : 2000409264,
|
||||||
|
"PhysicalSize" : 1024209543168,
|
||||||
|
"SectorSize" : 512
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
56
tests/fixtures/lldp/cumulus.txt
vendored
Normal file
56
tests/fixtures/lldp/cumulus.txt
vendored
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
lldp.eno1.via=LLDP
|
||||||
|
lldp.eno1.rid=4
|
||||||
|
lldp.eno1.age=35 days, 08:24:00
|
||||||
|
lldp.eno1.chassis.mac=e4:f0:04:b6:47:32
|
||||||
|
lldp.eno1.chassis.name=toto-chassis.dc42
|
||||||
|
lldp.eno1.chassis.descr=Cumulus Linux version 3.7.3 running on Dell EMC S4100
|
||||||
|
lldp.eno1.chassis.ttl=120
|
||||||
|
lldp.eno1.chassis.mgmt-ip=10.160.20.18
|
||||||
|
lldp.eno1.chassis.mgmt-ip=fe80::e6f0:4ff:feb6:4732
|
||||||
|
lldp.eno1.chassis.Bridge.enabled=on
|
||||||
|
lldp.eno1.chassis.Router.enabled=on
|
||||||
|
lldp.eno1.port.ifname=swp46
|
||||||
|
lldp.eno1.port.descr=BXVWNR2:lom2
|
||||||
|
lldp.eno1.port.auto-negotiation.supported=yes
|
||||||
|
lldp.eno1.port.auto-negotiation.enabled=no
|
||||||
|
lldp.eno1.port.auto-negotiation.current=10GigBaseLR - R fiber over 1310 nm optics
|
||||||
|
lldp.eno1.lldp-med.device-type=Network Connectivity Device
|
||||||
|
lldp.eno1.lldp-med.Capabilities.available=yes
|
||||||
|
lldp.eno1.lldp-med.Policy.available=yes
|
||||||
|
lldp.eno1.lldp-med.Location.available=yes
|
||||||
|
lldp.eno1.lldp-med.MDI/PSE.available=yes
|
||||||
|
lldp.eno1.lldp-med.MDI/PD.available=yes
|
||||||
|
lldp.eno1.lldp-med.Inventory.available=yes
|
||||||
|
lldp.eno1.lldp-med.inventory.software=3.7.3
|
||||||
|
lldp.eno1.lldp-med.inventory.firmware=5.6.5
|
||||||
|
lldp.eno1.lldp-med.inventory.serial=To be filled by O.E.M.
|
||||||
|
lldp.eno1.lldp-med.inventory.manufacturer=Dell EMC
|
||||||
|
lldp.eno1.lldp-med.inventory.model=S4100
|
||||||
|
lldp.eno2d1.via=LLDP
|
||||||
|
lldp.eno2d1.rid=3
|
||||||
|
lldp.eno2d1.age=35 days, 08:30:52
|
||||||
|
lldp.eno2d1.chassis.mac=e4:f0:04:b6:4e:32
|
||||||
|
lldp.eno1.chassis.name=toto-chassis.dc42
|
||||||
|
lldp.eno2d1.chassis.descr=Cumulus Linux version 3.7.5 running on Dell EMC S4100
|
||||||
|
lldp.eno2d1.chassis.ttl=120
|
||||||
|
lldp.eno2d1.chassis.mgmt-ip=10.160.20.17
|
||||||
|
lldp.eno2d1.chassis.mgmt-ip=fe80::e6f0:4ff:feb6:4e32
|
||||||
|
lldp.eno2d1.chassis.Bridge.enabled=on
|
||||||
|
lldp.eno2d1.chassis.Router.enabled=on
|
||||||
|
lldp.eno2d1.port.ifname=swp46
|
||||||
|
lldp.eno2d1.port.descr=BXVWNR2:lom1
|
||||||
|
lldp.eno2d1.port.auto-negotiation.supported=yes
|
||||||
|
lldp.eno2d1.port.auto-negotiation.enabled=no
|
||||||
|
lldp.eno2d1.port.auto-negotiation.current=10GigBaseLR - R fiber over 1310 nm optics
|
||||||
|
lldp.eno2d1.lldp-med.device-type=Network Connectivity Device
|
||||||
|
lldp.eno2d1.lldp-med.Capabilities.available=yes
|
||||||
|
lldp.eno2d1.lldp-med.Policy.available=yes
|
||||||
|
lldp.eno2d1.lldp-med.Location.available=yes
|
||||||
|
lldp.eno2d1.lldp-med.MDI/PSE.available=yes
|
||||||
|
lldp.eno2d1.lldp-med.MDI/PD.available=yes
|
||||||
|
lldp.eno2d1.lldp-med.Inventory.available=yes
|
||||||
|
lldp.eno2d1.lldp-med.inventory.software=3.7.5
|
||||||
|
lldp.eno2d1.lldp-med.inventory.firmware=5.6.5
|
||||||
|
lldp.eno2d1.lldp-med.inventory.serial=To be filled by O.E.M.
|
||||||
|
lldp.eno2d1.lldp-med.inventory.manufacturer=Dell EMC
|
||||||
|
lldp.eno2d1.lldp-med.inventory.model=S4100
|
8
tests/fixtures/lldp/dedibox1.txt
vendored
Normal file
8
tests/fixtures/lldp/dedibox1.txt
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
lldp.enp1s0f0.via=LLDP
|
||||||
|
lldp.enp1s0f0.rid=1
|
||||||
|
lldp.enp1s0f0.age=145 days, 00:00:39
|
||||||
|
lldp.enp1s0f0.chassis.mac=00:07:cb:0b:6c:d7
|
||||||
|
lldp.enp1s0f0.chassis.name=s120-f3-2.itx4
|
||||||
|
lldp.enp1s0f0.chassis.mgmt-ip=10.48.16.15
|
||||||
|
lldp.enp1s0f0.port.ifname=RJ-9
|
||||||
|
lldp.enp1s0f0.port.ttl=120
|
25
tests/fixtures/lldp/dedibox2.txt
vendored
Normal file
25
tests/fixtures/lldp/dedibox2.txt
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
lldp.eno1.via=LLDP
|
||||||
|
lldp.eno1.rid=1
|
||||||
|
lldp.eno1.age=1 day, 06:17:13
|
||||||
|
lldp.eno1.chassis.mac=38:20:56:67:90:80
|
||||||
|
lldp.eno1.chassis.name=s35-b12.dc3
|
||||||
|
lldp.eno1.chassis.descr=Cisco IOS Software, C2960X Software (C2960X-UNIVERSALK9-M), Version 15.0(2a)EX5, RELEASE SOFTWARE (fc3)
|
||||||
|
Technical Support: http://www.cisco.com/techsupport
|
||||||
|
Copyright (c) 1986-2015 by Cisco Systems, Inc.
|
||||||
|
Compiled Mon 16-Feb-15 08:16 by prod_rel_team
|
||||||
|
lldp.eno1.chassis.mgmt-ip=10.43.31.35
|
||||||
|
lldp.eno1.chassis.Bridge.enabled=on
|
||||||
|
lldp.eno1.chassis.Router.enabled=off
|
||||||
|
lldp.eno1.port.ifname=Gi1/0/29
|
||||||
|
lldp.eno1.port.descr=GigabitEthernet1/0/29
|
||||||
|
lldp.eno1.port.auto-negotiation.supported=yes
|
||||||
|
lldp.eno1.port.auto-negotiation.enabled=yes
|
||||||
|
lldp.eno1.port.auto-negotiation.10Base-T.hd=yes
|
||||||
|
lldp.eno1.port.auto-negotiation.10Base-T.fd=yes
|
||||||
|
lldp.eno1.port.auto-negotiation.100Base-TX.hd=yes
|
||||||
|
lldp.eno1.port.auto-negotiation.100Base-TX.fd=yes
|
||||||
|
lldp.eno1.port.auto-negotiation.1000Base-T.hd=no
|
||||||
|
lldp.eno1.port.auto-negotiation.1000Base-T.fd=yes
|
||||||
|
lldp.eno1.port.auto-negotiation.current=1000BaseTFD - Four-pair Category 5 UTP, full duplex mode
|
||||||
|
lldp.eno1.vlan.vlan-id=140
|
||||||
|
lldp.eno1.vlan.pvid=yes
|
38
tests/fixtures/lldp/qfx.txt
vendored
Normal file
38
tests/fixtures/lldp/qfx.txt
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
lldp.eth0.via=LLDP
|
||||||
|
lldp.eth0.rid=1
|
||||||
|
lldp.eth0.age=163 days, 23:03:53
|
||||||
|
lldp.eth0.chassis.mac=40:a6:77:7a:72:00
|
||||||
|
lldp.eth0.chassis.name=sw-filer-f06.dc42
|
||||||
|
lldp.eth0.chassis.descr=Juniper Networks, Inc. qfx5100-48s-6q Ethernet Switch, kernel JUNOS 14.1X53-D43.7, Build date: 2017-04-28 02:22:48 UTC Copyright (c) 1996-2017 Juniper Networks, Inc.
|
||||||
|
lldp.eth0.chassis.mgmt-ip=10.192.192.116
|
||||||
|
lldp.eth0.chassis.Bridge.enabled=on
|
||||||
|
lldp.eth0.chassis.Router.enabled=on
|
||||||
|
lldp.eth0.port.local=512
|
||||||
|
lldp.eth0.port.descr=xe-0/0/1
|
||||||
|
lldp.eth0.port.mfs=1514
|
||||||
|
lldp.eth0.vlan.vlan-id=296
|
||||||
|
lldp.eth0.vlan.pvid=yes
|
||||||
|
lldp.eth0.vlan=vlan-296
|
||||||
|
lldp.eth0.unknown-tlvs.unknown-tlv.oui=00,90,69
|
||||||
|
lldp.eth0.unknown-tlvs.unknown-tlv.subtype=1
|
||||||
|
lldp.eth0.unknown-tlvs.unknown-tlv.len=12
|
||||||
|
lldp.eth0.unknown-tlvs.unknown-tlv=56,46,33,37,31,35,30,33,30,31,36,34
|
||||||
|
lldp.eth1.via=LLDP
|
||||||
|
lldp.eth1.rid=2
|
||||||
|
lldp.eth1.age=163 days, 23:03:51
|
||||||
|
lldp.eth1.chassis.mac=40:a6:77:7c:fb:20
|
||||||
|
lldp.eth1.chassis.name=sw-filer-f05.dc42
|
||||||
|
lldp.eth1.chassis.descr=Juniper Networks, Inc. qfx5100-48s-6q Ethernet Switch, kernel JUNOS 17.3R3-S3.3, Build date: 2019-01-10 19:17:42 UTC Copyright (c) 1996-2019 Juniper Networks, Inc.
|
||||||
|
lldp.eth1.chassis.mgmt-ip=10.192.192.115
|
||||||
|
lldp.eth1.chassis.Bridge.enabled=on
|
||||||
|
lldp.eth1.chassis.Router.enabled=on
|
||||||
|
lldp.eth1.port.local=512
|
||||||
|
lldp.eth1.port.descr=xe-0/0/1
|
||||||
|
lldp.eth1.port.mfs=1514
|
||||||
|
lldp.eth1.vlan.vlan-id=296
|
||||||
|
lldp.eth1.vlan.pvid=yes
|
||||||
|
lldp.eth1.vlan=vlan-296
|
||||||
|
lldp.eth1.unknown-tlvs.unknown-tlv.oui=00,90,69
|
||||||
|
lldp.eth1.unknown-tlvs.unknown-tlv.subtype=1
|
||||||
|
lldp.eth1.unknown-tlvs.unknown-tlv.len=12
|
||||||
|
lldp.eth1.unknown-tlvs.unknown-tlv=56,46,33,37,31,35,30,33,30,30,34,35
|
16
tests/fixtures/netbox_agent.conf1.ok
vendored
Normal file
16
tests/fixtures/netbox_agent.conf1.ok
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
netbox:
|
||||||
|
url: 'https://netbox.company.com'
|
||||||
|
token: xx
|
||||||
|
|
||||||
|
datacenter_location:
|
||||||
|
driver: "cmd:cat /etc/qualification | tr [A-Z] [a-z]"
|
||||||
|
regex: "datacenter: (?P<datacenter>[A-Za-z0-9]+)"
|
||||||
|
|
||||||
|
rack_location:
|
||||||
|
driver: 'cmd:lldpctl'
|
||||||
|
regex: 'SysName:[ ]+[A-Za-z]+-[A-Za-z]+-([A-Za-z0-9]+)'
|
||||||
|
|
||||||
|
network:
|
||||||
|
ignore_interfaces: "(dummy.*|docker.*)"
|
||||||
|
ignore_ips: (127\.0\.0\..*)
|
||||||
|
lldp: true
|
24
tests/network.py
Normal file
24
tests/network.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
from netbox_agent.lldp import LLDP
|
||||||
|
from tests.conftest import parametrize_with_fixtures
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_with_fixtures(
|
||||||
|
"lldp/",
|
||||||
|
only_filenames=[
|
||||||
|
"dedibox1.txt",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_lldp_parse_with_port_desc(fixture):
|
||||||
|
lldp = LLDP(fixture)
|
||||||
|
assert lldp.get_switch_port("enp1s0f0") == "RJ-9"
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_with_fixtures(
|
||||||
|
"lldp/",
|
||||||
|
only_filenames=[
|
||||||
|
"qfx.txt",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_lldp_parse_without_ifname(fixture):
|
||||||
|
lldp = LLDP(fixture)
|
||||||
|
assert lldp.get_switch_port("eth0") == "xe-0/0/1"
|
91
tests/server.py
Normal file
91
tests/server.py
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
from netbox_agent.dmidecode import parse
|
||||||
|
from netbox_agent.server import ServerBase
|
||||||
|
from netbox_agent.vendors.hp import HPHost
|
||||||
|
from netbox_agent.vendors.qct import QCTHost
|
||||||
|
from netbox_agent.vendors.supermicro import SupermicroHost
|
||||||
|
from tests.conftest import parametrize_with_fixtures
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_with_fixtures("dmidecode/")
|
||||||
|
def test_init(fixture):
|
||||||
|
dmi = parse(fixture)
|
||||||
|
server = ServerBase(dmi)
|
||||||
|
assert server
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_with_fixtures(
|
||||||
|
"dmidecode/",
|
||||||
|
only_filenames=[
|
||||||
|
"HP_SL4540_Gen8",
|
||||||
|
"HP_BL460c_Gen9",
|
||||||
|
"HP_DL380p_Gen8",
|
||||||
|
"HP_SL4540_Gen8" "HP_ProLiant_BL460c_Gen10_Graphics_Exp",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_hp_service_tag(fixture):
|
||||||
|
dmi = parse(fixture)
|
||||||
|
server = HPHost(dmi)
|
||||||
|
assert server.get_service_tag() == "4242"
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_with_fixtures("dmidecode/", only_filenames=["HP_ProLiant_m710x"])
|
||||||
|
def test_moonshot_blade(fixture):
|
||||||
|
dmi = parse(fixture)
|
||||||
|
server = HPHost(dmi)
|
||||||
|
assert server.get_service_tag() == "CN66480BLA"
|
||||||
|
assert server.get_chassis_service_tag() == "CZ3702MD5K"
|
||||||
|
assert server.is_blade() is True
|
||||||
|
assert server.own_expansion_slot() is False
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_with_fixtures("dmidecode/", only_filenames=["SYS-5039MS-H12TRF-OS012.txt"])
|
||||||
|
def test_supermicro_blade(fixture):
|
||||||
|
dmi = parse(fixture)
|
||||||
|
server = SupermicroHost(dmi)
|
||||||
|
assert server.get_service_tag() == "E235735X6B01665"
|
||||||
|
assert server.get_chassis_service_tag() == "C9390AF40A20098"
|
||||||
|
assert server.get_chassis() == "SYS-5039MS-H12TRF-OS012"
|
||||||
|
assert server.is_blade() is True
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_with_fixtures("dmidecode/", only_filenames=["SM_SYS-6018R"])
|
||||||
|
def test_supermicro_pizza(fixture):
|
||||||
|
dmi = parse(fixture)
|
||||||
|
server = SupermicroHost(dmi)
|
||||||
|
assert server.get_service_tag() == "A177950X7709591"
|
||||||
|
assert server.get_chassis() == "SYS-6018R-TDTPR"
|
||||||
|
assert server.is_blade() is False
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_with_fixtures("dmidecode/", only_filenames=["QCT_X10E-9N"])
|
||||||
|
def test_qct_x10(fixture):
|
||||||
|
dmi = parse(fixture)
|
||||||
|
server = QCTHost(dmi)
|
||||||
|
assert server.get_service_tag() == "QTFCQ57140285"
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_with_fixtures("dmidecode/", only_filenames=["unknown.txt"])
|
||||||
|
def test_generic_host_service_tag(fixture):
|
||||||
|
dmi = parse(fixture)
|
||||||
|
server = ServerBase(dmi)
|
||||||
|
assert server.get_service_tag() == "42"
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_with_fixtures("dmidecode/", only_filenames=["unknown.txt"])
|
||||||
|
def test_generic_host_product_name(fixture):
|
||||||
|
dmi = parse(fixture)
|
||||||
|
server = ServerBase(dmi)
|
||||||
|
assert server.get_product_name() == "SR"
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_with_fixtures(
|
||||||
|
"dmidecode/", only_filenames=["HP_ProLiant_BL460c_Gen10_Graphics_Exp"]
|
||||||
|
)
|
||||||
|
def test_hp_blade_with_gpu_expansion(fixture):
|
||||||
|
dmi = parse(fixture)
|
||||||
|
server = HPHost(dmi)
|
||||||
|
assert server.get_service_tag() == "4242"
|
||||||
|
assert server.get_chassis_service_tag() == "4343"
|
||||||
|
assert server.is_blade() is True
|
||||||
|
assert server.own_expansion_slot() is True
|
||||||
|
assert server.get_expansion_service_tag() == "4242 expansion"
|
40
tox.ini
40
tox.ini
|
@ -2,38 +2,16 @@
|
||||||
# These are the default environments that will be run
|
# These are the default environments that will be run
|
||||||
# when ``tox`` is run without arguments.
|
# when ``tox`` is run without arguments.
|
||||||
envlist =
|
envlist =
|
||||||
py35
|
pytest
|
||||||
py36
|
flake8
|
||||||
py37
|
|
||||||
coverage
|
|
||||||
mypy
|
|
||||||
pep8
|
|
||||||
docs
|
|
||||||
skip_missing_interpreters = True
|
skip_missing_interpreters = True
|
||||||
|
|
||||||
[flake8]
|
|
||||||
# Use the more relaxed max line length permitted in PEP8.
|
|
||||||
max-line-length = 99
|
|
||||||
|
|
||||||
# Enforce the Google Python style for grouping and sorting imports:
|
|
||||||
# https://github.com/google/styleguide/blob/gh-pages/pyguide.md#313-imports-formatting
|
|
||||||
import-order-style = google
|
|
||||||
|
|
||||||
# Inform flake8-import-order plugin that `fact` should be treated as a local package name.
|
|
||||||
application-import-names = netbox_agent
|
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
# This is required in order to get UTF-8 output inside of the subprocesses
|
deps = -r{toxinidir}/dev-requirements.txt
|
||||||
# that our tests use.
|
whitelist_externals = bash
|
||||||
setenv = LC_CTYPE = en_US.UTF-8
|
|
||||||
# Pass Display down to have it for the tests available
|
|
||||||
passenv = DISPLAY TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH
|
|
||||||
whitelist_externals=convert
|
|
||||||
deps =
|
|
||||||
-r{toxinidir}/requirements.txt
|
|
||||||
|
|
||||||
[testenv:pep8]
|
[testenv:pytest]
|
||||||
deps =
|
commands = bash tests.sh
|
||||||
flake8
|
|
||||||
pep8-naming
|
[testenv:flake8]
|
||||||
commands = flake8 {toxinidir}/netbox_agent {toxinidir}/tests
|
commands = flake8
|
||||||
|
|
Loading…
Reference in a new issue