Skip to content

Commit 55fae43

Browse files
alielhoh
authored andcommitted
Update CPU and memory details by switching to lshw method instead of cpuinfo
Add CPU information (model, vendor, frequency) and memory details (clock, size, type) to API
1 parent d6025f5 commit 55fae43

File tree

10 files changed

+142
-15
lines changed

10 files changed

+142
-15
lines changed

.github/workflows/code-quality.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
run: |
1717
sudo apt-get update
1818
sudo apt-get -y upgrade
19-
sudo apt-get install -y python3 python3-pip python3-aiohttp python3-msgpack python3-aiodns python3-alembic python3-sqlalchemy python3-setproctitle redis python3-aioredis python3-psutil sudo acl curl systemd-container squashfs-tools debootstrap python3-packaging python3-cpuinfo python3-nftables python3-jsonschema nftables
19+
sudo apt-get install -y python3 python3-pip python3-aiohttp python3-msgpack python3-aiodns python3-alembic python3-sqlalchemy python3-setproctitle redis python3-aioredis python3-psutil sudo acl curl systemd-container squashfs-tools debootstrap python3-packaging python3-nftables python3-jsonschema nftables lshw
2020
pip install --upgrade typing-extensions types-PyYAML
2121
2222
- name: Install required Python packages

docker/vm_supervisor-dev.dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ FROM debian:bullseye
55
RUN apt-get update && apt-get -y upgrade && apt-get install -y \
66
sudo acl curl squashfs-tools git \
77
python3 python3-aiohttp python3-alembic python3-msgpack python3-pip python3-aiodns python3-aioredis\
8-
python3-nftables python3-psutil python3-setproctitle python3-sqlalchemy python3-packaging python3-cpuinfo ndppd nftables \
8+
python3-nftables python3-psutil python3-setproctitle python3-sqlalchemy python3-packaging ndppd nftables \
99
&& rm -rf /var/lib/apt/lists/*
1010

1111
RUN useradd jailman

packaging/aleph-vm/DEBIAN/control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ Version: 0.1.8
33
Architecture: all
44
Maintainer: Aleph.im
55
Description: Aleph.im VM execution engine
6-
Depends: python3,python3-pip,python3-aiohttp,python3-msgpack,python3-aiodns,python3-alembic,python3-sqlalchemy,python3-setproctitle,redis,python3-aioredis,python3-psutil,sudo,acl,curl,systemd-container,squashfs-tools,debootstrap,python3-packaging,python3-cpuinfo,python3-nftables,python3-jsonschema,cloud-image-utils,ndppd,python3-yaml,python3-dotenv,python3-schedule,qemu-system-x86,qemu-utils,python3-systemd,python3-dbus,btrfs-progs,nftables
6+
Depends: python3,python3-pip,python3-aiohttp,python3-msgpack,python3-aiodns,python3-alembic,python3-sqlalchemy,python3-setproctitle,redis,python3-aioredis,python3-psutil,sudo,acl,curl,systemd-container,squashfs-tools,debootstrap,python3-packaging,python3-nftables,python3-jsonschema,cloud-image-utils,ndppd,python3-yaml,python3-dotenv,python3-schedule,qemu-system-x86,qemu-utils,python3-systemd,python3-dbus,btrfs-progs,nftables,lshw
77
Section: aleph-im
88
Priority: Extra

packaging/requirements-debian-11.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ multidict==5.1.0
1717
git+https://salsa.debian.org/pkg-netfilter-team/pkg-nftables#egg=nftables&subdirectory=py
1818
packaging==20.9
1919
psutil==5.8.0
20-
py-cpuinfo==5.0.0
2120
pycares==3.1.1
2221
pyparsing==2.4.7
2322
pyrsistent==0.15.5

packaging/requirements-ubuntu-20.04.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ multidict==4.7.3
1818
git+https://salsa.debian.org/pkg-netfilter-team/pkg-nftables#egg=nftables&subdirectory=py
1919
packaging==20.3
2020
psutil==5.5.1
21-
py-cpuinfo==5.0.0
2221
pycares==3.1.1
2322
PyGObject==3.36.0
2423
pyparsing==2.4.6

packaging/requirements-ubuntu-22.04.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ multidict==5.1.0
2121
git+https://salsa.debian.org/pkg-netfilter-team/pkg-nftables#egg=nftables&subdirectory=py
2222
packaging==21.3
2323
psutil==5.9.0
24-
py-cpuinfo==5.0.0
2524
pycares==4.1.2
2625
PyGObject==3.42.1
2726
pyparsing==2.4.7

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ dependencies = [
3535
"sentry-sdk==1.31.0",
3636
"aioredis==1.3.1",
3737
"psutil==5.9.5",
38-
"py-cpuinfo==9.0.0",
3938
"schedule==1.2.1",
4039
"nftables @ git+https://salsa.debian.org/pkg-netfilter-team/pkg-nftables#egg=nftables&subdirectory=py",
4140
"msgpack==1.0.7",

src/aleph/vm/orchestrator/machine.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import json
2+
import re
3+
import subprocess
4+
from functools import lru_cache
5+
6+
import psutil
7+
8+
9+
@lru_cache
10+
def get_hardware_info():
11+
lshw = subprocess.Popen(["lshw", "-sanitize", "-json"], stdout=subprocess.PIPE, shell=False)
12+
output, _ = lshw.communicate()
13+
data = json.loads(output)
14+
15+
hw_info = {}
16+
17+
for hw in data["children"][0]["children"]:
18+
if hw["id"] == "cpu":
19+
hw_info["cpu"] = hw
20+
elif hw["class"] == "memory" and hw["id"] == "memory":
21+
hw_info["memory"] = hw
22+
23+
return hw_info
24+
25+
26+
@lru_cache
27+
def get_cpu_info():
28+
hw = get_hardware_info()
29+
30+
cpu_info = hw["cpu"]
31+
architecture = cpu_info["width"]
32+
33+
if "x86_64" in cpu_info["capabilities"] or "x86-64" in cpu_info["capabilities"]:
34+
architecture = "x86_64"
35+
elif "arm64" in cpu_info["capabilities"] or "arm-64" in cpu_info["capabilities"]:
36+
architecture = "arm64"
37+
38+
vendor = cpu_info["vendor"]
39+
# lshw vendor implementation => https://github.com/lyonel/lshw/blob/15e4ca64647ad119b69be63274e5de2696d3934f/src/core/cpuinfo.cc#L308
40+
41+
if "Intel Corp" in vendor:
42+
vendor = "GenuineIntel"
43+
elif "Advanced Micro Devices [AMD]" in vendor:
44+
vendor = "AuthenticAMD"
45+
46+
return {
47+
"architecture": architecture,
48+
"vendor": vendor,
49+
"model": cpu_info["product"],
50+
"frequency": cpu_info["capacity"],
51+
"count": psutil.cpu_count(),
52+
}
53+
54+
55+
@lru_cache
56+
def get_memory_info():
57+
hw = get_hardware_info()
58+
mem_info = hw["memory"]
59+
60+
memory_type = ""
61+
memory_clock = ""
62+
63+
for bank in mem_info["children"]:
64+
memory_clock = bank["clock"]
65+
try:
66+
memory_type = re.search("(DDR[2-6])", bank["description"]).group(0)
67+
break
68+
except:
69+
pass
70+
71+
return {
72+
"size": mem_info["size"],
73+
"units": mem_info["units"],
74+
"type": memory_type,
75+
"clock": memory_clock,
76+
"clock_units": "Hz",
77+
}

src/aleph/vm/orchestrator/resources.py

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@
33
from functools import lru_cache
44
from typing import Optional
55

6-
import cpuinfo
76
import psutil
87
from aiohttp import web
8+
from aleph.vm.conf import settings
9+
from aleph.vm.orchestrator.machine import get_cpu_info, get_memory_info
910
from aleph_message.models import ItemHash
1011
from aleph_message.models.execution.environment import CpuProperties
1112
from pydantic import BaseModel, Field
1213

13-
from aleph.vm.conf import settings
14-
1514

1615
class Period(BaseModel):
1716
datetime: datetime
@@ -76,18 +75,66 @@ class MachineUsage(BaseModel):
7675
active: bool = True
7776

7877

78+
class ExtendedCpuProperties(CpuProperties):
79+
"""CPU properties."""
80+
81+
model: Optional[str] = Field(default=None, description="CPU model")
82+
frequency: Optional[str] = Field(default=None, description="CPU frequency")
83+
count: Optional[str] = Field(default=None, description="CPU count")
84+
85+
86+
87+
class MemoryProperties(BaseModel):
88+
"""MEMORY properties."""
89+
90+
size: Optional[str] = Field(default=None, description="Memory size")
91+
units: Optional[str] = Field(default=None, description="Memory size units")
92+
type: Optional[str] = Field(default=None, description="Memory type")
93+
clock: Optional[str] = Field(default=None, description="Memory clock")
94+
clock_units: Optional[str] = Field(default=None, description="Memory clock units")
95+
96+
97+
class MachineCapability(BaseModel):
98+
cpu: ExtendedCpuProperties
99+
memory: MemoryProperties
100+
101+
79102
@lru_cache
80103
def get_machine_properties() -> MachineProperties:
81104
"""Fetch machine properties such as architecture, CPU vendor, ...
82105
These should not change while the supervisor is running.
83106
84107
In the future, some properties may have to be fetched from within a VM.
85108
"""
86-
cpu_info = cpuinfo.get_cpu_info() # Slow
109+
110+
cpu_info = get_cpu_info()
87111
return MachineProperties(
88112
cpu=CpuProperties(
89-
architecture=cpu_info["raw_arch_string"],
90-
vendor=cpu_info["vendor_id"],
113+
architecture=cpu_info["architecture"],
114+
vendor=cpu_info["vendor"],
115+
),
116+
)
117+
118+
119+
@lru_cache
120+
def get_machine_capability() -> MachineCapability:
121+
cpu_info = get_cpu_info()
122+
mem_info = get_memory_info()
123+
124+
return MachineCapability(
125+
cpu=ExtendedCpuProperties(
126+
architecture=cpu_info["architecture"],
127+
vendor=cpu_info["vendor"],
128+
model=cpu_info["model"],
129+
frequency=cpu_info["frequency"],
130+
count=cpu_info["count"],
131+
),
132+
memory=MemoryProperties(
133+
size=mem_info["size"],
134+
units=mem_info["units"],
135+
type=mem_info["type"],
136+
clock=mem_info["clock"],
137+
clock_units=mem_info["clock_units"],
91138
),
92139
)
93140

@@ -119,6 +166,13 @@ async def about_system_usage(_: web.Request):
119166
return web.json_response(text=usage.json(exclude_none=True), headers={"Access-Control-Allow-Origin:": "*"})
120167

121168

169+
async def about_capability(_: web.Request):
170+
"""Public endpoint to expose information about the CRN capability."""
171+
172+
capability: MachineCapability = get_machine_capability()
173+
return web.json_response(text=capability.json(exclude_none=False), headers={"Access-Control-Allow-Origin:": "*"})
174+
175+
122176
class Allocation(BaseModel):
123177
"""An allocation is the set of resources that are currently allocated on this orchestrator.
124178
It contains the item_hashes of all persistent VMs, instances, on-demand VMs and jobs.

src/aleph/vm/orchestrator/supervisor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,12 @@
1515

1616
import aiohttp_cors
1717
from aiohttp import web
18-
1918
from aleph.vm.conf import settings
2019
from aleph.vm.pool import VmPool
2120
from aleph.vm.version import __version__
2221

2322
from .metrics import create_tables, setup_engine
24-
from .resources import about_system_usage
23+
from .resources import about_capability, about_system_usage
2524
from .tasks import (
2625
start_payment_monitoring_task,
2726
start_watch_for_messages_task,
@@ -94,6 +93,7 @@ async def allow_cors_on_endpoint(request: web.Request):
9493
web.get("/about/executions/records", about_execution_records),
9594
web.get("/about/usage/system", about_system_usage),
9695
web.get("/about/config", about_config),
96+
web.get("/about/capability", about_capability),
9797
# /control APIs are used to control the VMs and access their logs
9898
web.post("/control/allocations", update_allocations),
9999
web.post("/control/allocation/notify", notify_allocation),

0 commit comments

Comments
 (0)