Skip to content

Commit

Permalink
inject complete lshw and adapt example to work with whole lshw (#1242)
Browse files Browse the repository at this point in the history
## Problem

There is only limited subset of hardware information for jsonnet.


## Solution

Add complete json tree from lshw and adapt example how to search for the
biggest disk. Also add utils library for easier search in lshw output
and enhance example.


## Testing

- *Tested manually*
  • Loading branch information
jreidinger committed May 22, 2024
2 parents 6b5b013 + 11ec35b commit 2807a14
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 10 deletions.
13 changes: 8 additions & 5 deletions autoinstallation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,21 @@ running. For such use cases, Agama injects the hardware information into the pro
using Jsonnet.

In the following example, the profile is adapted to install the system on the biggest disk on the
system. The hardware information (from `lshw`) is available as a JSON object in the `hw.libsonnet`.
system. It also selects product based on amount of available RAM memory. The hardware information
(from `lshw`) is available as a JSON object in the `hw.libsonnet`.
There is also a set of helpers as part of hw. For documentation of those helpers see agama.libsonnet file.

```jsonnet
local agama = import 'hw.libsonnet';
local findBiggestDisk(disks) =
local sizedDisks = std.filter(function(d) std.objectHas(d, 'size'), disks);
local sorted = std.sort(sizedDisks, function(x) x.size);
sorted[0].logicalname;
local memory = agama.findByID(agama.lshw, 'memory').size;
{
software: {
product: 'ALP-Dolomite',
product: if memory < 8000000000 then 'MicroOS' else 'Tumbleweed',
},
root: {
password: 'nots3cr3t',
Expand All @@ -97,13 +100,13 @@ local findBiggestDisk(disks) =
language: 'en_US',
},
storage: {
bootDevice: findBiggestDisk(agama.disks),
bootDevice: findBiggestDisk(agama.selectByClass(agama.lshw, 'disk')),
},
}
```

**:warning: At this point, only the storage information is injected. You can inspect the available
data by installing the `lshw` package and running the following command: `lshw -json -class disk`.**
**You can inspect the available
data by installing the `lshw` package and running the following command: `lshw -json`.**

### Validating and evaluating a profile

Expand Down
11 changes: 8 additions & 3 deletions rust/agama-lib/src/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,22 @@ impl ProfileEvaluator {
Ok(())
}

// Write the hardware information in JSON format to a given path
// Write the hardware information in JSON format to a given path and also helpers to help with it
//
// TODO: we need a better way to generate this information, as lshw and hwinfo are not usable
// out of the box.
fn write_hwinfo(&self, path: &Path) -> anyhow::Result<()> {
let result = Command::new("/usr/sbin/lshw")
.args(["-json", "-class", "disk"])
.args(["-json"])
.output()
.context("Failed to run lshw")?;
let helpers = fs::read_to_string("agama.libsonnet")
.or_else(|_| fs::read_to_string("/usr/share/agama-cli/agama.libsonnet"))
.context("Failed to read agama.libsonnet")?;
let mut file = fs::File::create(path)?;
file.write_all(b"{ \"disks\":\n")?;
file.write_all(b"{\n")?;
file.write_all(helpers.as_bytes())?;
file.write_all(b"\n\"lshw\":\n")?;
file.write_all(&result.stdout)?;
file.write_all(b"\n}")?;
Ok(())
Expand Down
10 changes: 8 additions & 2 deletions rust/package/agama.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Wed May 22 12:31:25 UTC 2024 - Josef Reidinger <jreidinger@suse.com>

- autoinstallation jsonnet: Inject complete lshw json output and
provide helper functions for filtering it (gh#openSUSE/agama#1242)

-------------------------------------------------------------------
Fri May 17 09:52:25 UTC 2024 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

Expand All @@ -6,8 +12,8 @@ Fri May 17 09:52:25 UTC 2024 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>
-------------------------------------------------------------------
Tue May 16 12:48:42 UTC 2024 - Knut Anderssen <kanderssen@suse.com>

- Allow to download Agama los throgh the manager HTTP API
(gh#openSUSE/1216).
- Allow to download Agama logs through the manager HTTP API
(gh#openSUSE/agama#1216).

-------------------------------------------------------------------
Thu May 16 12:34:43 UTC 2024 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>
Expand Down
1 change: 1 addition & 0 deletions rust/package/agama.spec
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ install -m 0755 %{_builddir}/agama/target/release/agama-web-server %{buildroot}%
install -D -p -m 644 %{_builddir}/agama/share/agama.pam $RPM_BUILD_ROOT%{_pam_vendordir}/agama
install -D -d -m 0755 %{buildroot}%{_datadir}/agama-cli
install -m 0644 %{_builddir}/agama/agama-lib/share/profile.schema.json %{buildroot}%{_datadir}/agama-cli
install -m 0644 %{_builddir}/agama/share/agama.libsonnet %{buildroot}%{_datadir}/agama-cli
install --directory %{buildroot}%{_datadir}/dbus-1/agama-services
install -m 0644 --target-directory=%{buildroot}%{_datadir}/dbus-1/agama-services %{_builddir}/agama/share/org.opensuse.Agama1.service
install -D -m 0644 %{_builddir}/agama/share/agama-web-server.service %{buildroot}%{_unitdir}/agama-web-server.service
Expand Down
32 changes: 32 additions & 0 deletions rust/share/agama.libsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// function go throught lshw output and enlist only given class.
// Basically it is same as calling `lshw -class <class>`.
// @param lshw: Object with content of `lshw -json`
// @param class: String with class identifier as can be found in "class" element of lshw
// @return Array of objects with given class
selectByClass(lshw, class)::
local selectClass_(parent, class) =
if std.objectHas(parent, 'class') && parent.class == class then
[ parent ]
else if std.objectHas(parent, 'children') then
std.flattenArrays(std.prune(std.map(function(x) selectClass_(x, class), parent.children )))
else
[];

local result = selectClass_(lshw, class);
result,

// function go throught lshw output and returns object with given "id" or null if not found.
// @param lshw: Object with content of `lshw -json`
// @param id: String with identifier as can be found in "id" element of lshw
// @return Object with given id or null
findByID(lshw, id)::
local findID_(parent, id) =
if std.objectHas(parent, 'id') && parent.id == id then
[parent]
else if std.objectHas(parent, 'children') then
std.flattenArrays(std.prune(std.map(function(x) findID_(x, id), parent.children )))
else
null;

local result = findID_(lshw, id);
if std.length(result) > 0 then result[0] else null,

0 comments on commit 2807a14

Please sign in to comment.