Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ycai
simbricks
Commits
facea554
Unverified
Commit
facea554
authored
Nov 18, 2024
by
Jakob Görgen
Browse files
added toJSON methods for system module
parent
789df39b
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
350 additions
and
12 deletions
+350
-12
experiments/simbricks/orchestration/simulation/base.py
experiments/simbricks/orchestration/simulation/base.py
+2
-1
experiments/simbricks/orchestration/system/base.py
experiments/simbricks/orchestration/system/base.py
+68
-2
experiments/simbricks/orchestration/system/eth.py
experiments/simbricks/orchestration/system/eth.py
+22
-0
experiments/simbricks/orchestration/system/host/app.py
experiments/simbricks/orchestration/system/host/app.py
+65
-6
experiments/simbricks/orchestration/system/host/base.py
experiments/simbricks/orchestration/system/host/base.py
+59
-2
experiments/simbricks/orchestration/system/host/disk_images.py
...iments/simbricks/orchestration/system/host/disk_images.py
+45
-0
experiments/simbricks/orchestration/system/mem.py
experiments/simbricks/orchestration/system/mem.py
+14
-1
experiments/simbricks/orchestration/system/pcie.py
experiments/simbricks/orchestration/system/pcie.py
+10
-0
experiments/simbricks/orchestration/utils/base.py
experiments/simbricks/orchestration/utils/base.py
+18
-0
experiments/simbricks/orchestration/utils/json.py
experiments/simbricks/orchestration/utils/json.py
+47
-0
No files found.
experiments/simbricks/orchestration/simulation/base.py
View file @
facea554
...
...
@@ -277,7 +277,7 @@ class Simulation(utils_base.IdObj):
Contains the simulators to be run and experiment-wide parameters.
"""
def
__init__
(
self
,
name
:
str
)
->
None
:
def
__init__
(
self
,
name
:
str
,
system
:
sys_conf
.
System
)
->
None
:
super
().
__init__
()
self
.
name
=
name
"""
...
...
@@ -285,6 +285,7 @@ class Simulation(utils_base.IdObj):
Can be used to run only a selection of experiments.
"""
self
.
system
:
sys_conf
.
System
=
system
self
.
timeout
:
int
|
None
=
None
"""Timeout for experiment in seconds."""
self
.
metadata
:
dict
[
str
,
tp
.
Any
]
=
{}
...
...
experiments/simbricks/orchestration/system/base.py
View file @
facea554
...
...
@@ -29,17 +29,36 @@ from simbricks.orchestration.utils import base as util_base
if
tp
.
TYPE_CHECKING
:
from
simbricks.orchestration.instantiation
import
base
as
inst_base
class
System
:
class
System
(
util_base
.
IdObj
):
"""Defines System configuration of the whole simulation"""
def
__init__
(
self
)
->
None
:
super
().
__init__
()
self
.
all_component
:
list
[
Component
]
=
[]
def
add_component
(
self
,
c
:
Component
)
->
None
:
assert
c
.
system
==
self
self
.
all_component
.
append
(
c
)
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"type"
]
=
self
.
__class__
.
__name__
json_obj
[
"module"
]
=
self
.
__class__
.
__module__
components_json
=
[]
for
comp
in
self
.
all_component
:
util_base
.
has_attribute
(
comp
,
'toJSON'
)
comp_json
=
comp
.
toJSON
()
components_json
.
append
(
comp_json
)
json_obj
[
"all_component"
]
=
components_json
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
class
Component
(
util_base
.
IdObj
):
...
...
@@ -64,6 +83,26 @@ class Component(util_base.IdObj):
async
def
prepare
(
self
,
inst
:
inst_base
.
Instantiation
)
->
None
:
pass
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"type"
]
=
self
.
__class__
.
__name__
json_obj
[
"module"
]
=
self
.
__class__
.
__module__
json_obj
[
"system"
]
=
self
.
system
.
id
()
json_obj
[
"name"
]
=
self
.
name
interfaces_json
=
[]
for
inf
in
self
.
interfaces
():
util_base
.
has_attribute
(
inf
,
'toJSON'
)
interfaces_json
.
append
(
inf
.
toJSON
())
json_obj
[
"interfaces"
]
=
interfaces_json
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
class
Interface
(
util_base
.
IdObj
):
def
__init__
(
self
,
c
:
Component
)
->
None
:
...
...
@@ -103,6 +142,19 @@ class Interface(util_base.IdObj):
@
staticmethod
def
filter_by_type
(
interfaces
:
list
[
Interface
],
ty
:
type
[
T
])
->
list
[
T
]:
return
list
(
filter
(
lambda
inf
:
isinstance
(
inf
,
ty
),
interfaces
))
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"type"
]
=
self
.
__class__
.
__name__
json_obj
[
"module"
]
=
self
.
__class__
.
__module__
json_obj
[
"component"
]
=
self
.
component
.
id
()
json_obj
[
"channel"
]
=
self
.
channel
.
id
()
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
class
Channel
(
util_base
.
IdObj
):
...
...
@@ -131,3 +183,17 @@ class Channel(util_base.IdObj):
opposing
=
self
.
a
if
interface
is
self
.
b
else
self
.
b
assert
opposing
!=
interface
return
opposing
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"type"
]
=
self
.
__class__
.
__name__
json_obj
[
"module"
]
=
self
.
__class__
.
__module__
json_obj
[
"latency"
]
=
self
.
latency
json_obj
[
"interface_a"
]
=
self
.
a
.
id
()
json_obj
[
"interface_b"
]
=
self
.
b
.
id
()
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
experiments/simbricks/orchestration/system/eth.py
View file @
facea554
...
...
@@ -51,6 +51,17 @@ class EthSimpleNIC(base.Component):
def
add_if
(
self
,
interface
:
EthInterface
)
->
None
:
raise
Exception
(
"EthSimpleNIC already has ethernet interface"
)
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"ip"
]
=
self
.
_ip
json_obj
[
"eth_if"
]
=
self
.
_eth_if
.
id
()
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
class
BaseEthNetComponent
(
base
.
Component
):
def
__init__
(
self
,
s
:
base
.
System
)
->
None
:
...
...
@@ -62,6 +73,17 @@ class BaseEthNetComponent(base.Component):
def
interfaces
(
self
)
->
list
[
EthInterface
]:
return
self
.
eth_ifs
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
eth_interfaces
=
[
inf
.
id
()
for
inf
in
self
.
eth_ifs
]
json_obj
[
"eth_if"
]
=
eth_interfaces
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
class
EthWire
(
BaseEthNetComponent
):
...
...
experiments/simbricks/orchestration/system/host/app.py
View file @
facea554
...
...
@@ -26,21 +26,35 @@ import typing as tp
import
abc
import
io
from
simbricks.orchestration.instantiation
import
base
as
inst_base
from
simbricks.orchestration.utils
import
base
as
utils_base
if
tp
.
TYPE_CHECKING
:
from
simbricks.orchestration.system
import
host
as
sys_host
class
Application
(
abc
.
ABC
):
class
Application
(
utils_base
.
IdObj
):
def
__init__
(
self
,
h
:
sys_host
.
Host
)
->
None
:
super
().
__init__
()
self
.
host
=
h
def
toJSON
(
self
)
->
dict
:
json_obj
=
{}
json_obj
[
"type"
]
=
self
.
__class__
.
__name__
json_obj
[
"module"
]
=
self
.
__class__
.
__module__
json_obj
[
"host"
]
=
self
.
host
.
id
()
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
# Note AK: Maybe we can factor most of the duplicate calls with the host out
# into a separate module.
class
BaseLinuxApplication
(
abc
.
ABC
):
class
BaseLinuxApplication
(
Application
):
def
__init__
(
self
,
h
:
sys_host
.
LinuxHost
)
->
None
:
s
elf
.
host
=
h
s
uper
().
__init__
(
h
)
self
.
start_delay
:
float
|
None
=
None
self
.
end_delay
:
float
|
None
=
None
self
.
wait
=
False
...
...
@@ -87,6 +101,18 @@ class BaseLinuxApplication(abc.ABC):
simulated node.
"""
return
io
.
BytesIO
(
bytes
(
s
,
encoding
=
"UTF-8"
))
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"start_delay"
]
=
self
.
start_delay
json_obj
[
"end_delay"
]
=
self
.
end_delay
json_obj
[
"wait"
]
=
self
.
wait
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
class
PingClient
(
BaseLinuxApplication
):
...
...
@@ -96,6 +122,16 @@ class PingClient(BaseLinuxApplication):
def
run_cmds
(
self
,
inst
:
inst_base
.
Instantiation
)
->
tp
.
List
[
str
]:
return
[
f
"ping
{
self
.
server_ip
}
-c 10"
]
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"server_ip"
]
=
self
.
server_ip
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
class
Sleep
(
BaseLinuxApplication
):
...
...
@@ -108,6 +144,17 @@ class Sleep(BaseLinuxApplication):
if
self
.
infinite
:
return
[
f
"sleep infinity"
]
return
[
f
"sleep
{
self
.
delay
}
"
]
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"infinite"
]
=
self
.
infinite
json_obj
[
"delay"
]
=
self
.
delay
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
class
NetperfServer
(
BaseLinuxApplication
):
...
...
@@ -121,9 +168,9 @@ class NetperfServer(BaseLinuxApplication):
class
NetperfClient
(
BaseLinuxApplication
):
def
__init__
(
self
,
h
:
sys_host
.
LinuxHost
,
server_ip
:
str
=
"192.168.64.1"
)
->
None
:
super
().
__init__
(
h
)
self
.
server_ip
=
server_ip
self
.
duration_tp
=
10
self
.
duration_lat
=
10
self
.
server_ip
:
str
=
server_ip
self
.
duration_tp
:
int
=
10
self
.
duration_lat
:
int
=
10
def
run_cmds
(
self
,
inst
:
inst_base
.
Instantiation
)
->
list
[
str
]:
return
[
...
...
@@ -135,3 +182,15 @@ class NetperfClient(BaseLinuxApplication):
" -- -o mean_latency,p50_latency,p90_latency,p99_latency"
),
]
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"server_ip"
]
=
self
.
server_ip
json_obj
[
"duration_tp"
]
=
self
.
duration_tp
json_obj
[
"duration_lat"
]
=
self
.
duration_lat
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
experiments/simbricks/orchestration/system/host/base.py
View file @
facea554
...
...
@@ -40,17 +40,33 @@ class Host(base.Component):
def
__init__
(
self
,
s
:
base
.
System
):
super
().
__init__
(
s
)
self
.
ifs
:
list
[
base
.
Interface
]
=
[]
self
.
applications
:
list
[
app
.
Application
]
self
.
applications
:
list
[
app
.
Application
]
=
[]
def
interfaces
(
self
)
->
list
[
base
.
Interface
]:
return
self
.
ifs
def
add_if
(
self
,
interface
:
base
.
Interface
)
->
None
:
self
.
ifs
.
append
(
interface
)
def
add_app
(
self
,
a
:
app
.
Application
)
->
None
:
self
.
applications
.
append
(
a
)
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
applications_json
=
[]
for
app
in
self
.
applications
:
utils_base
.
has_attribute
(
app
,
'toJSON'
)
applications_json
.
append
(
app
.
toJSON
())
json_obj
[
"applications"
]
=
applications_json
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
class
FullSystemHost
(
Host
):
def
__init__
(
self
,
s
:
base
.
System
)
->
None
:
...
...
@@ -67,6 +83,25 @@ class FullSystemHost(Host):
promises
=
[
disk
.
prepare
(
inst
)
for
disk
in
self
.
disks
]
await
asyncio
.
gather
(
*
promises
)
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"memory"
]
=
self
.
memory
json_obj
[
"cores"
]
=
self
.
cores
json_obj
[
"cpu_freq"
]
=
self
.
cpu_freq
disks_json
=
[]
for
disk
in
self
.
disks
:
utils_base
.
has_attribute
(
disk
,
'toJSON'
)
disks_json
.
append
(
disk
.
toJSON
())
json_obj
[
"disks"
]
=
disks_json
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
class
BaseLinuxHost
(
FullSystemHost
):
def
__init__
(
self
,
s
:
base
.
System
)
->
None
:
...
...
@@ -165,6 +200,17 @@ class BaseLinuxHost(FullSystemHost):
simulated node.
"""
return
io
.
BytesIO
(
bytes
(
s
,
encoding
=
"UTF-8"
))
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"load_modules"
]
=
self
.
load_modules
json_obj
[
"kcmd_append"
]
=
self
.
kcmd_append
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
class
LinuxHost
(
BaseLinuxHost
):
...
...
@@ -229,6 +275,17 @@ class LinuxHost(BaseLinuxHost):
cmds
.
append
(
f
"ip addr add
{
com
.
_ip
}
/24 dev
{
ifn
}
"
)
return
cmds
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"drivers"
]
=
self
.
drivers
json_obj
[
"hostname"
]
=
self
.
hostname
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
class
I40ELinuxHost
(
LinuxHost
):
...
...
experiments/simbricks/orchestration/system/host/disk_images.py
View file @
facea554
...
...
@@ -84,6 +84,19 @@ class DiskImage(utils_base.IdObj):
await
self
.
_prepare_format
(
inst
,
format
)
def
toJSON
(
self
)
->
dict
:
json_obj
=
{}
json_obj
[
"type"
]
=
self
.
__class__
.
__name__
json_obj
[
"module"
]
=
self
.
__class__
.
__module__
json_obj
[
"host"
]
=
self
.
host
.
id
()
json_obj
[
"qemu_img_exec"
]
=
self
.
_qemu_img_exec
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
# Disk image where user just provides a path
class
ExternalDiskImage
(
DiskImage
):
...
...
@@ -98,6 +111,17 @@ class ExternalDiskImage(DiskImage):
def
path
(
self
,
inst
:
inst_base
.
Instantiation
,
format
:
str
)
->
str
:
DiskImage
.
assert_is_file
(
self
.
_path
)
return
self
.
_path
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"path"
]
=
self
.
_path
json_obj
[
"formats"
]
=
self
.
formats
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
# Disk images shipped with simbricks
...
...
@@ -120,6 +144,17 @@ class DistroDiskImage(DiskImage):
raise
RuntimeError
(
"Unsupported disk format"
)
DiskImage
.
assert_is_file
(
path
)
return
path
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"name"
]
=
self
.
name
json_obj
[
"formats"
]
=
self
.
formats
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
# Abstract base class for dynamically generated images
...
...
@@ -186,3 +221,13 @@ class PackerDiskImage(DynamicDiskImage):
async
def
_prepare_format
(
self
,
inst
:
inst_base
.
Instantiation
,
format
:
str
)
->
None
:
# TODO: invoke packer to build the image if necessary
pass
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"config_path"
]
=
self
.
config_path
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
experiments/simbricks/orchestration/system/mem.py
View file @
facea554
...
...
@@ -67,4 +67,17 @@ class MemSimpleDevice(base.Component):
def
add_if
(
self
,
interface
:
MemDeviceInterface
)
->
None
:
utils_base
.
has_expected_type
(
obj
=
interface
,
expected_type
=
MemDeviceInterface
)
assert
self
.
_mem_if
is
None
self
.
_mem_if
=
interface
\ No newline at end of file
self
.
_mem_if
=
interface
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"mem_if"
]
=
self
.
_mem_if
.
id
()
json_obj
[
"addr"
]
=
self
.
_addr
json_obj
[
"size"
]
=
self
.
_size
json_obj
[
"as_id"
]
=
self
.
_as_id
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
\ No newline at end of file
experiments/simbricks/orchestration/system/pcie.py
View file @
facea554
...
...
@@ -63,3 +63,13 @@ class PCIeSimpleDevice(base.Component):
def
add_if
(
self
,
interface
:
PCIeDeviceInterface
)
->
None
:
raise
Exception
(
"PCIeSimpleDevice already has PCI device interface"
)
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"pci_if"
]
=
self
.
_pci_if
.
id
()
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
\ No newline at end of file
experiments/simbricks/orchestration/utils/base.py
View file @
facea554
...
...
@@ -30,6 +30,18 @@ class IdObj(abc.ABC):
def
__init__
(
self
):
self
.
_id
=
next
(
self
.
__id_iter
)
def
id
(
self
)
->
int
:
return
self
.
_id
def
toJSON
(
self
):
json_obj
=
{}
json_obj
[
"id"
]
=
self
.
_id
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
def
check_type
(
obj
,
expected_type
)
->
bool
:
"""
...
...
@@ -45,3 +57,9 @@ def has_expected_type(obj, expected_type) -> None:
raise
Exception
(
f
"obj of type
{
type
(
obj
)
}
has not the type or is not a subtype of
{
expected_type
}
"
)
def
has_attribute
(
obj
,
attr
:
str
)
->
None
:
if
not
hasattr
(
obj
,
attr
):
raise
Exception
(
f
"obj of type
{
type
(
obj
)
}
no attribute called
{
attr
}
"
)
experiments/simbricks/orchestration/utils/json.py
0 → 100644
View file @
facea554
# Copyright 2024 Max Planck Institute for Software Systems, and
# National University of Singapore
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import
json
from
simbricks.orchestration.utils
import
base
as
util_base
from
simbricks.orchestration.system
import
base
as
sys_base
def
toJSON
(
system
:
sys_base
.
System
)
->
dict
:
json_obj
=
{}
util_base
.
has_attribute
(
system
,
"toJSON"
)
json_obj
[
"system"
]
=
system
.
toJSON
()
channels
:
set
[
sys_base
.
Channel
]
=
set
()
for
comp
in
system
.
all_component
:
for
inf
in
comp
.
interfaces
():
channels
.
add
(
inf
.
channel
)
channels_json
=
[]
for
chan
in
channels
:
util_base
.
has_attribute
(
chan
,
"toJSON"
)
channels_json
.
append
(
chan
.
toJSON
())
json_obj
[
"channels"
]
=
channels_json
return
json
.
dumps
({
"specification"
:
json_obj
})
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment