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
3bbc0c04
"vscode:/vscode.git/clone" did not exist on "8525a021205965cc4ee76173561c6cb671f704ce"
Unverified
Commit
3bbc0c04
authored
Nov 26, 2024
by
Jakob Görgen
Browse files
added json deserialization to system module
parent
7fac851b
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
420 additions
and
186 deletions
+420
-186
experiments/simbricks/orchestration/simulation/channel.py
experiments/simbricks/orchestration/simulation/channel.py
+2
-0
experiments/simbricks/orchestration/system/base.py
experiments/simbricks/orchestration/system/base.py
+107
-34
experiments/simbricks/orchestration/system/eth.py
experiments/simbricks/orchestration/system/eth.py
+29
-23
experiments/simbricks/orchestration/system/host/app.py
experiments/simbricks/orchestration/system/host/app.py
+59
-35
experiments/simbricks/orchestration/system/host/base.py
experiments/simbricks/orchestration/system/host/base.py
+52
-34
experiments/simbricks/orchestration/system/host/disk_images.py
...iments/simbricks/orchestration/system/host/disk_images.py
+42
-23
experiments/simbricks/orchestration/system/mem.py
experiments/simbricks/orchestration/system/mem.py
+25
-13
experiments/simbricks/orchestration/system/nic.py
experiments/simbricks/orchestration/system/nic.py
+43
-6
experiments/simbricks/orchestration/system/pcie.py
experiments/simbricks/orchestration/system/pcie.py
+17
-9
experiments/simbricks/orchestration/utils/base.py
experiments/simbricks/orchestration/utils/base.py
+44
-9
No files found.
experiments/simbricks/orchestration/simulation/channel.py
View file @
3bbc0c04
...
...
@@ -44,6 +44,8 @@ class Channel(utils_base.IdObj):
def
toJSON
(
self
):
json_obj
=
super
().
toJSON
()
json_obj
[
"type"
]
=
self
.
__class__
.
__name__
json_obj
[
"module"
]
=
self
.
__class__
.
__module__
json_obj
[
"synchronized"
]
=
self
.
_synchronized
json_obj
[
"sync_period"
]
=
self
.
sync_period
json_obj
[
"sys_channel"
]
=
self
.
sys_channel
.
id
()
...
...
experiments/simbricks/orchestration/system/base.py
View file @
3bbc0c04
...
...
@@ -35,11 +35,36 @@ class System(util_base.IdObj):
def
__init__
(
self
)
->
None
:
super
().
__init__
()
self
.
all_component
:
list
[
Component
]
=
[]
self
.
_all_components
:
dict
[
int
,
Component
]
=
{}
self
.
_all_interfaces
:
dict
[
int
,
Interface
]
=
{}
self
.
_all_channels
:
dict
[
int
,
Channel
]
=
{}
def
add_component
(
self
,
c
:
Component
)
->
None
:
def
_
add_component
(
self
,
c
:
Component
)
->
None
:
assert
c
.
system
==
self
self
.
all_component
.
append
(
c
)
assert
c
.
id
()
not
in
self
.
_all_components
self
.
_all_components
[
c
.
id
()]
=
c
def
get_comp
(
self
,
ident
:
int
)
->
Component
:
assert
ident
in
self
.
_all_components
return
self
.
_all_components
[
ident
]
def
_add_interface
(
self
,
i
:
Interface
)
->
None
:
assert
i
.
component
.
id
()
in
self
.
_all_components
assert
i
.
id
()
not
in
self
.
_all_interfaces
self
.
_all_interfaces
[
i
.
id
()]
=
i
def
get_inf
(
self
,
ident
:
int
)
->
Interface
:
assert
ident
in
self
.
_all_interfaces
return
self
.
_all_interfaces
[
ident
]
def
_add_channel
(
self
,
c
:
Channel
)
->
None
:
assert
c
.
a
.
id
()
in
self
.
_all_interfaces
and
c
.
b
.
id
()
in
self
.
_all_interfaces
assert
c
.
id
()
not
in
self
.
_all_channels
self
.
_all_channels
[
c
.
id
()]
=
c
def
get_chan
(
self
,
ident
:
int
)
->
Channel
:
assert
ident
in
self
.
_all_channels
return
self
.
_all_channels
[
ident
]
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
...
...
@@ -47,19 +72,15 @@ class System(util_base.IdObj):
json_obj
[
"module"
]
=
self
.
__class__
.
__module__
components_json
=
[]
channels
:
set
[
Channel
]
=
set
()
for
comp
in
self
.
all_component
:
for
_
,
comp
in
self
.
_all_components
.
items
():
util_base
.
has_attribute
(
comp
,
"toJSON"
)
comp_json
=
comp
.
toJSON
()
components_json
.
append
(
comp_json
)
for
inf
in
comp
.
interfaces
():
channels
.
add
(
inf
.
channel
)
json_obj
[
"all_component"
]
=
components_json
json_obj
[
"all_components"
]
=
components_json
channels_json
=
[]
for
chan
in
channels
:
for
_
,
chan
in
self
.
_all_channels
.
items
()
:
util_base
.
has_attribute
(
chan
,
"toJSON"
)
channels_json
.
append
(
chan
.
toJSON
())
...
...
@@ -67,10 +88,26 @@ class System(util_base.IdObj):
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
@
classmethod
def
fromJSON
(
cls
,
json_obj
:
dict
)
->
System
:
instance
=
super
().
fromJSON
(
json_obj
)
instance
.
_all_components
=
{}
instance
.
_all_interfaces
=
{}
instance
.
_all_channels
=
{}
components_json
=
util_base
.
get_json_attr_top
(
json_obj
,
"all_components"
)
for
comp_json
in
components_json
:
comp_class
=
util_base
.
get_cls_by_json
(
comp_json
)
util_base
.
has_attribute
(
comp_class
,
"fromJSON"
)
comp
=
comp_class
.
fromJSON
(
instance
,
comp_json
)
channels_json
=
util_base
.
get_json_attr_top
(
json_obj
,
"channels"
)
for
chan_json
in
channels_json
:
chan_class
=
util_base
.
get_cls_by_json
(
chan_json
)
util_base
.
has_attribute
(
chan_class
,
"fromJSON"
)
chan
=
chan_class
.
fromJSON
(
instance
,
chan_json
)
return
instance
class
Component
(
util_base
.
IdObj
):
...
...
@@ -78,17 +115,17 @@ class Component(util_base.IdObj):
def
__init__
(
self
,
s
:
System
)
->
None
:
super
().
__init__
()
self
.
system
=
s
self
.
ifs
:
list
[
Interface
]
=
[]
s
.
parameters
=
{}
s
.
add_component
(
self
)
self
.
name
:
str
=
""
s
.
_
add_component
(
self
)
self
.
name
:
str
|
None
=
None
@
abc
.
abstractmethod
def
interfaces
(
self
)
->
list
[
Interface
]:
return
[]
return
self
.
ifs
@
abc
.
abstractmethod
def
add_if
(
self
,
interface
:
tp
.
Any
)
->
None
:
raise
Exception
(
"must be overwritten by subclass"
)
# NOTE: overwrite and call in subclasses
def
add_if
(
self
,
interface
:
Interface
)
->
None
:
self
.
ifs
.
append
(
interface
)
def
channels
(
self
)
->
list
[
Channel
]:
return
[
i
.
channel
for
i
in
self
.
interfaces
()
if
i
.
is_connected
()]
...
...
@@ -111,16 +148,29 @@ class Component(util_base.IdObj):
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
@
classmethod
def
fromJSON
(
cls
,
system
:
System
,
json_obj
:
dict
)
->
Component
:
instance
=
super
().
fromJSON
(
json_obj
)
instance
.
name
=
util_base
.
get_json_attr_top_or_none
(
json_obj
,
"name"
)
instance
.
system
=
system
system
.
_add_component
(
instance
)
instance
.
ifs
=
[]
interfaces_json
=
util_base
.
get_json_attr_top
(
json_obj
,
"interfaces"
)
for
inf_json
in
interfaces_json
:
inf_class
=
util_base
.
get_cls_by_json
(
inf_json
)
util_base
.
has_attribute
(
inf_class
,
"fromJSON"
)
# NOTE: this will add the interface to the system map for retrieval in sub-classes
inf
=
inf_class
.
fromJSON
(
system
,
inf_json
)
return
instance
class
Interface
(
util_base
.
IdObj
):
def
__init__
(
self
,
c
:
Component
)
->
None
:
super
().
__init__
()
self
.
component
=
c
c
.
system
.
_add_interface
(
self
)
self
.
channel
:
Channel
|
None
=
None
def
is_connected
(
self
)
->
bool
:
...
...
@@ -130,7 +180,10 @@ class Interface(util_base.IdObj):
self
.
channel
=
None
def
connect
(
self
,
c
:
Channel
)
->
None
:
assert
self
.
channel
is
None
if
self
.
channel
is
not
None
:
raise
Exception
(
f
"cannot connect interface
{
self
.
id
()
}
to channel
{
c
.
id
()
}
. interface is already connected to channel
{
self
.
channel
.
id
()
}
"
)
self
.
channel
=
c
def
find_peer
(
self
)
->
Interface
:
...
...
@@ -164,10 +217,16 @@ class Interface(util_base.IdObj):
json_obj
[
"channel"
]
=
self
.
channel
.
id
()
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
@
classmethod
def
fromJSON
(
cls
,
system
:
System
,
json_obj
:
dict
)
->
Interface
:
instance
=
super
().
fromJSON
(
json_obj
)
comp_id
=
util_base
.
get_json_attr_top
(
json_obj
,
"component"
)
comp
=
system
.
get_comp
(
comp_id
)
instance
.
component
=
comp
comp
.
add_if
(
instance
)
system
.
_add_interface
(
instance
)
instance
.
channel
=
None
return
instance
class
Channel
(
util_base
.
IdObj
):
...
...
@@ -178,6 +237,7 @@ class Channel(util_base.IdObj):
self
.
a
.
connect
(
self
)
self
.
b
:
Interface
=
b
self
.
b
.
connect
(
self
)
a
.
component
.
system
.
_add_channel
(
self
)
def
interfaces
(
self
)
->
list
[
Interface
]:
return
[
self
.
a
,
self
.
b
]
...
...
@@ -206,7 +266,20 @@ class Channel(util_base.IdObj):
json_obj
[
"interface_b"
]
=
self
.
b
.
id
()
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
@
classmethod
def
fromJSON
(
cls
,
system
:
System
,
json_obj
:
dict
)
->
Channel
:
instance
=
super
().
fromJSON
(
json_obj
)
instance
.
latency
=
int
(
util_base
.
get_json_attr_top
(
json_obj
,
"latency"
))
inf_id_a
=
int
(
util_base
.
get_json_attr_top
(
json_obj
,
"interface_a"
))
inf_id_b
=
int
(
util_base
.
get_json_attr_top
(
json_obj
,
"interface_b"
))
inf_a
=
system
.
get_inf
(
ident
=
inf_id_a
)
inf_b
=
system
.
get_inf
(
ident
=
inf_id_b
)
instance
.
a
=
inf_a
instance
.
a
.
connect
(
instance
)
instance
.
b
=
inf_b
instance
.
b
.
connect
(
instance
)
system
.
_add_channel
(
instance
)
return
instance
experiments/simbricks/orchestration/system/eth.py
View file @
3bbc0c04
...
...
@@ -20,6 +20,8 @@
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from
__future__
import
annotations
from
simbricks.orchestration.system
import
base
from
simbricks.orchestration.utils
import
base
as
utils_base
...
...
@@ -44,46 +46,50 @@ class EthSimpleNIC(base.Component):
super
().
__init__
(
s
)
self
.
_ip
:
str
|
None
=
None
self
.
_eth_if
:
EthInterface
=
EthInterface
(
self
)
super
().
add_if
(
self
.
_eth_if
)
def
add_ipv4
(
self
,
ip
:
str
)
->
None
:
assert
self
.
_ip
is
None
self
.
_ip
=
ip
def
add_if
(
self
,
interface
:
EthInterface
)
->
None
:
raise
Exception
(
"EthSimpleNIC already has ethernet interface"
)
utils_base
.
has_expected_type
(
interface
,
EthInterface
)
if
hasattr
(
self
,
"_eth_if"
)
and
self
.
_eth_if
:
raise
Exception
(
f
"you overwrite EthSimpleNIC._eth_if (
{
self
.
_eth_if
.
id
()
}
->
{
interface
.
id
()
}
) "
)
self
.
_eth_if
=
interface
super
().
add_if
(
self
.
_eth_if
)
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
@
classmethod
def
fromJSON
(
cls
,
system
:
base
.
System
,
json_obj
:
dict
)
->
EthSimpleNIC
:
instance
=
super
().
fromJSON
(
system
,
json_obj
)
instance
.
_ip
=
utils_base
.
get_json_attr_top
(
json_obj
,
"ip"
)
eth_inf_id
=
int
(
utils_base
.
get_json_attr_top
(
json_obj
,
"eth_if"
))
instance
.
_eth_if
=
system
.
get_inf
(
eth_inf_id
)
return
instance
class
BaseEthNetComponent
(
base
.
Component
):
def
__init__
(
self
,
s
:
base
.
System
)
->
None
:
super
().
__init__
(
s
)
self
.
eth_ifs
:
list
[
EthInterface
]
=
[]
def
add_if
(
self
,
i
:
EthInterface
)
->
None
:
self
.
eth_ifs
.
append
(
i
)
utils_base
.
has_expected_type
(
i
,
EthInterface
)
super
().
add_if
(
i
)
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
return
super
().
toJSON
()
@
classmethod
def
fromJSON
(
cls
,
system
:
base
.
System
,
json_obj
:
dict
)
->
BaseEthNetComponent
:
return
super
().
fromJSON
(
system
,
json_obj
)
class
EthWire
(
BaseEthNetComponent
):
...
...
@@ -91,9 +97,9 @@ class EthWire(BaseEthNetComponent):
super
().
__init__
(
s
)
def
add_if
(
self
,
i
:
EthInterface
)
->
None
:
if
len
(
self
.
eth_
ifs
)
>
2
:
if
len
(
self
.
ifs
)
>
2
:
raise
Exception
(
"one can only add 2 interfaces to a EthWire"
)
s
elf
.
eth_ifs
.
append
(
i
)
s
uper
().
add_if
(
i
)
class
EthSwitch
(
BaseEthNetComponent
):
...
...
experiments/simbricks/orchestration/system/host/app.py
View file @
3bbc0c04
...
...
@@ -27,6 +27,7 @@ import abc
import
io
from
simbricks.orchestration.instantiation
import
base
as
inst_base
from
simbricks.orchestration.utils
import
base
as
utils_base
from
simbricks.orchestration.system
import
base
as
sys_base
if
tp
.
TYPE_CHECKING
:
from
simbricks.orchestration.system
import
host
as
sys_host
...
...
@@ -35,19 +36,21 @@ if tp.TYPE_CHECKING:
class
Application
(
utils_base
.
IdObj
):
def
__init__
(
self
,
h
:
sys_host
.
Host
)
->
None
:
super
().
__init__
()
self
.
host
=
h
self
.
host
:
sys_host
.
Host
=
h
def
toJSON
(
self
)
->
dict
:
json_obj
=
{}
json_obj
=
super
().
toJSON
()
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
@
classmethod
def
fromJSON
(
cls
,
system
:
sys_base
.
System
,
json_obj
:
dict
):
instance
=
super
().
fromJSON
(
json_obj
)
host_id
=
utils_base
.
get_json_attr_top
(
json_obj
,
"host"
)
instance
.
host
=
system
.
get_comp
(
host_id
)
return
instance
# Note AK: Maybe we can factor most of the duplicate calls with the host out
...
...
@@ -57,7 +60,7 @@ class BaseLinuxApplication(Application):
super
().
__init__
(
h
)
self
.
start_delay
:
float
|
None
=
None
self
.
end_delay
:
float
|
None
=
None
self
.
wait
=
False
self
.
wait
:
bool
=
False
@
abc
.
abstractmethod
def
run_cmds
(
self
,
inst
:
inst_base
.
Instantiation
)
->
list
[
str
]:
...
...
@@ -101,60 +104,70 @@ class BaseLinuxApplication(Application):
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
@
classmethod
def
fromJSON
(
cls
,
system
:
sys_base
.
System
,
json_obj
:
dict
):
instance
=
super
().
fromJSON
(
system
,
json_obj
)
instance
.
start_delay
=
utils_base
.
get_json_attr_top_or_none
(
json_obj
,
"start_delay"
)
instance
.
end_delay
=
utils_base
.
get_json_attr_top_or_none
(
json_obj
,
"end_delay"
)
instance
.
wait
=
utils_base
.
get_json_attr_top
(
json_obj
,
"wait"
)
return
instance
class
PingClient
(
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
.
server_ip
:
str
=
server_ip
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
@
classmethod
def
fromJSON
(
cls
,
system
:
sys_base
.
System
,
json_obj
:
dict
):
instance
=
super
().
fromJSON
(
system
,
json_obj
)
instance
.
server_ip
=
utils_base
.
get_json_attr_top
(
json_obj
,
"server_ip"
)
return
instance
class
Sleep
(
BaseLinuxApplication
):
def
__init__
(
self
,
h
:
sys_host
.
LinuxHost
,
delay
:
float
=
10
,
infinite
:
bool
=
False
)
->
None
:
def
__init__
(
self
,
h
:
sys_host
.
LinuxHost
,
delay
:
float
=
10
,
infinite
:
bool
=
False
)
->
None
:
super
().
__init__
(
h
)
self
.
infinite
:
bool
=
infinite
self
.
delay
=
delay
self
.
delay
:
float
=
delay
def
run_cmds
(
self
,
inst
:
inst_base
.
Instantiation
)
->
list
[
str
]:
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
@
classmethod
def
fromJSON
(
cls
,
system
:
sys_base
.
System
,
json_obj
:
dict
)
->
Sleep
:
instance
=
super
().
fromJSON
(
system
,
json_obj
)
instance
.
infinite
=
bool
(
utils_base
.
get_json_attr_top
(
json_obj
,
"infinite"
))
instance
.
delay
=
float
(
utils_base
.
get_json_attr_top
(
json_obj
,
"delay"
))
return
instance
class
NetperfServer
(
BaseLinuxApplication
):
...
...
@@ -164,6 +177,10 @@ class NetperfServer(BaseLinuxApplication):
def
run_cmds
(
self
,
inst
:
inst_base
.
Instantiation
)
->
list
[
str
]:
return
[
"netserver"
,
"sleep infinity"
]
@
classmethod
def
fromJSON
(
cls
,
system
:
sys_base
.
System
,
json_obj
:
dict
)
->
NetperfServer
:
return
super
().
fromJSON
(
system
,
json_obj
)
class
NetperfClient
(
BaseLinuxApplication
):
def
__init__
(
self
,
h
:
sys_host
.
LinuxHost
,
server_ip
:
str
=
"192.168.64.1"
)
->
None
:
...
...
@@ -182,15 +199,22 @@ 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
@
classmethod
def
fromJSON
(
cls
,
system
:
sys_base
.
System
,
json_obj
:
dict
)
->
NetperfClient
:
instance
=
super
().
fromJSON
(
system
,
json_obj
)
instance
.
server_ip
=
utils_base
.
get_json_attr_top
(
json_obj
,
"server_ip"
)
instance
.
duration_tp
=
int
(
utils_base
.
get_json_attr_top
(
json_obj
,
"duration_tp"
)
)
instance
.
duration_lat
=
int
(
utils_base
.
get_json_attr_top
(
json_obj
,
"duration_lat"
)
)
return
instance
experiments/simbricks/orchestration/system/host/base.py
View file @
3bbc0c04
...
...
@@ -39,15 +39,8 @@ if tp.TYPE_CHECKING:
class
Host
(
base
.
Component
):
def
__init__
(
self
,
s
:
base
.
System
):
super
().
__init__
(
s
)
self
.
ifs
:
list
[
base
.
Interface
]
=
[]
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
)
...
...
@@ -56,24 +49,33 @@ class Host(base.Component):
applications_json
=
[]
for
app
in
self
.
applications
:
utils_base
.
has_attribute
(
app
,
'
toJSON
'
)
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
@
classmethod
def
fromJSON
(
cls
,
system
:
base
.
System
,
json_obj
:
dict
)
->
Host
:
instance
=
super
().
fromJSON
(
system
=
system
,
json_obj
=
json_obj
)
instance
.
applications
=
[]
applications_json
=
utils_base
.
get_json_attr_top
(
json_obj
,
"applications"
)
for
app_json
in
applications_json
:
app_class
=
utils_base
.
get_cls_by_json
(
app_json
)
utils_base
.
has_attribute
(
app_class
,
"fromJSON"
)
app
=
app_class
.
fromJSON
(
system
,
app_json
)
instance
.
add_app
(
app
)
return
instance
class
FullSystemHost
(
Host
):
def
__init__
(
self
,
s
:
base
.
System
)
->
None
:
super
().
__init__
(
s
)
self
.
memory
=
512
self
.
cores
=
1
self
.
cpu_freq
=
"3GHz"
self
.
memory
:
int
=
512
self
.
cores
:
int
=
1
self
.
cpu_freq
:
str
=
"3GHz"
self
.
disks
:
list
[
disk_images
.
DiskImage
]
=
[]
def
add_disk
(
self
,
disk
:
disk_images
.
DiskImage
)
->
None
:
...
...
@@ -91,16 +93,28 @@ class FullSystemHost(Host):
disks_json
=
[]
for
disk
in
self
.
disks
:
utils_base
.
has_attribute
(
disk
,
'
toJSON
'
)
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
@
classmethod
def
fromJSON
(
cls
,
system
:
base
.
System
,
json_obj
:
dict
)
->
FullSystemHost
:
instance
=
super
().
fromJSON
(
system
,
json_obj
)
instance
.
memory
=
int
(
utils_base
.
get_json_attr_top
(
json_obj
,
"memory"
))
instance
.
cores
=
int
(
utils_base
.
get_json_attr_top
(
json_obj
,
"cores"
))
instance
.
cpu_freq
=
utils_base
.
get_json_attr_top
(
json_obj
,
"cpu_freq"
)
instance
.
disks
=
[]
disks_json
=
utils_base
.
get_json_attr_top
(
json_obj
,
"disks"
)
for
disk_js
in
disks_json
:
disk_class
=
utils_base
.
get_cls_by_json
(
disk_js
)
utils_base
.
has_attribute
(
disk_class
,
"fromJSON"
)
disk
=
disk_class
.
fromJSON
(
system
,
disk_js
)
instance
.
add_disk
(
disk
)
return
instance
class
BaseLinuxHost
(
FullSystemHost
):
...
...
@@ -200,17 +214,19 @@ 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
@
classmethod
def
fromJSON
(
cls
,
system
:
base
.
System
,
json_obj
:
dict
)
->
BaseLinuxHost
:
instance
=
super
().
fromJSON
(
system
,
json_obj
)
instance
.
load_modules
=
utils_base
.
get_json_attr_top
(
json_obj
,
"load_modules"
)
instance
.
kcmd_append
=
utils_base
.
get_json_attr_top
(
json_obj
,
"kcmd_append"
)
return
instance
class
LinuxHost
(
BaseLinuxHost
):
...
...
@@ -275,17 +291,19 @@ 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
@
classmethod
def
fromJSON
(
cls
,
system
:
base
.
System
,
json_obj
:
dict
)
->
LinuxHost
:
instance
=
super
().
fromJSON
(
system
,
json_obj
)
instance
.
drivers
=
utils_base
.
get_json_attr_top
(
json_obj
,
"drivers"
)
instance
.
hostname
=
utils_base
.
get_json_attr_top
(
json_obj
,
"hostname"
)
return
instance
class
I40ELinuxHost
(
LinuxHost
):
...
...
experiments/simbricks/orchestration/system/host/disk_images.py
View file @
3bbc0c04
...
...
@@ -29,6 +29,7 @@ import tarfile
import
typing
as
tp
from
simbricks.orchestration.utils
import
base
as
utils_base
from
simbricks.orchestration.instantiation
import
base
as
inst_base
from
simbricks.orchestration.system
import
base
as
sys_base
if
tp
.
TYPE_CHECKING
:
from
simbricks.orchestration.system
import
host
as
sys_host
...
...
@@ -85,17 +86,22 @@ class DiskImage(utils_base.IdObj):
await
self
.
_prepare_format
(
inst
,
format
)
def
toJSON
(
self
)
->
dict
:
json_obj
=
{}
json_obj
=
super
().
toJSON
()
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
@
classmethod
def
fromJSON
(
cls
,
system
:
sys_base
.
System
,
json_obj
:
dict
)
->
DiskImage
:
instance
=
super
().
fromJSON
(
json_obj
)
host_id
=
int
(
utils_base
.
get_json_attr_top
(
json_obj
,
"host"
))
instance
.
host
=
system
.
get_comp
(
host_id
)
instance
.
_qemu_img_exec
=
utils_base
.
get_json_attr_top
(
json_obj
,
"qemu_img_exec"
)
return
instance
# Disk image where user just provides a path
...
...
@@ -111,17 +117,19 @@ 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
@
classmethod
def
fromJSON
(
cls
,
system
:
sys_base
.
System
,
json_obj
:
dict
)
->
DiskImage
:
instance
=
super
().
fromJSON
(
system
,
json_obj
)
instance
.
_path
=
utils_base
.
get_json_attr_top
(
json_obj
,
"path"
)
instance
.
formats
=
utils_base
.
get_json_attr_top
(
json_obj
,
"formats"
)
return
instance
# Disk images shipped with simbricks
...
...
@@ -144,17 +152,19 @@ 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
@
classmethod
def
fromJSON
(
cls
,
system
:
sys_base
.
System
,
json_obj
:
dict
)
->
DiskImage
:
instance
=
super
().
fromJSON
(
system
,
json_obj
)
instance
.
name
=
utils_base
.
get_json_attr_top
(
json_obj
,
"name"
)
instance
.
formats
=
utils_base
.
get_json_attr_top
(
json_obj
,
"formats"
)
return
instance
# Abstract base class for dynamically generated images
...
...
@@ -169,6 +179,10 @@ class DynamicDiskImage(DiskImage):
async
def
_prepare_format
(
self
,
inst
:
inst_base
.
Instantiation
,
format
:
str
)
->
None
:
pass
@
classmethod
def
fromJSON
(
cls
,
system
:
sys_base
.
System
,
json_obj
:
dict
)
->
DynamicDiskImage
:
return
super
().
fromJSON
(
system
,
json_obj
)
# Builds the Tar with the commands to run etc.
class
LinuxConfigDiskImage
(
DynamicDiskImage
):
...
...
@@ -206,6 +220,10 @@ class LinuxConfigDiskImage(DynamicDiskImage):
tar
.
addfile
(
tarinfo
=
f_i
,
fileobj
=
f
)
f
.
close
()
@
classmethod
def
fromJSON
(
cls
,
system
:
sys_base
.
System
,
json_obj
:
dict
)
->
LinuxConfigDiskImage
:
return
super
().
fromJSON
(
system
,
json_obj
)
# This is an additional example: building disk images directly from python
# Could of course also have a version that generates the packer config from
...
...
@@ -226,8 +244,9 @@ class PackerDiskImage(DynamicDiskImage):
json_obj
=
super
().
toJSON
()
json_obj
[
"config_path"
]
=
self
.
config_path
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
@
classmethod
def
fromJSON
(
cls
,
system
:
sys_base
.
System
,
json_obj
:
dict
)
->
PackerDiskImage
:
instance
=
super
().
fromJSON
(
system
,
json_obj
)
instance
.
config_path
=
utils_base
.
get_json_attr_top
(
json_obj
,
"config_path"
)
return
instance
experiments/simbricks/orchestration/system/mem.py
View file @
3bbc0c04
...
...
@@ -20,6 +20,8 @@
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from
__future__
import
annotations
from
simbricks.orchestration.system
import
base
from
simbricks.orchestration.utils
import
base
as
utils_base
...
...
@@ -38,7 +40,7 @@ class MemDeviceInterface(base.Interface):
def
connect
(
self
,
c
:
base
.
Channel
)
->
None
:
# Note AK: a bit ugly, but I think we can't get around a rt check here
if
not
c
is
isinstance
(
c
,
MemChannel
):
raise
TypeError
(
'
MemDeviceInterface only connects to MemChannel
'
)
raise
TypeError
(
"
MemDeviceInterface only connects to MemChannel
"
)
super
().
connect
(
c
)
...
...
@@ -48,7 +50,7 @@ class MemChannel(base.Channel):
def
host_if
(
self
)
->
MemHostInterface
:
return
self
.
a
def
dev_if
(
self
)
->
MemDeviceInterface
:
return
self
.
b
...
...
@@ -57,17 +59,19 @@ class MemSimpleDevice(base.Component):
def
__init__
(
self
,
s
:
base
.
System
):
super
().
__init__
(
s
)
self
.
_mem_if
:
MemDeviceInterface
=
MemDeviceInterface
(
c
=
self
)
self
.
_addr
=
0xe000000000000000
super
().
add_if
(
self
.
_mem_if
)
self
.
_addr
=
0xE000000000000000
self
.
_size
=
1024
*
1024
*
1024
# 1GB
self
.
_as_id
=
0
def
interfaces
(
self
)
->
list
[
base
.
Interface
]:
return
[
self
.
_mem_if
]
def
add_if
(
self
,
interface
:
MemDeviceInterface
)
->
None
:
utils_base
.
has_expected_type
(
obj
=
interface
,
expected_type
=
MemDeviceInterface
)
assert
self
.
_mem_if
is
None
utils_base
.
has_expected_type
(
interface
,
MemDeviceInterface
)
if
self
.
_mem_if
:
raise
Exception
(
f
"you overwrite MemDeviceInterface._mem_if (
{
self
.
_mem_if
.
id
()
}
->
{
interface
.
id
()
}
) "
)
self
.
_mem_if
=
interface
super
().
add_if
(
self
.
_mem_if
)
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
...
...
@@ -76,8 +80,16 @@ class MemSimpleDevice(base.Component):
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
@
classmethod
def
fromJSON
(
cls
,
system
:
base
.
System
,
json_obj
:
dict
)
->
MemSimpleDevice
:
instance
=
super
().
fromJSON
(
system
,
json_obj
)
mem_if_id
=
int
(
utils_base
.
get_json_attr_top
(
json_obj
,
"mem_if"
))
addr
=
utils_base
.
get_json_attr_top
(
json_obj
,
"addr"
)
size
=
utils_base
.
get_json_attr_top
(
json_obj
,
"size"
)
as_id
=
utils_base
.
get_json_attr_top
(
json_obj
,
"as_id"
)
instance
.
mem_if
=
system
.
get_inf
(
mem_if_id
)
instance
.
addr
=
addr
instance
.
size
=
size
instance
.
as_id
=
as_id
return
instance
experiments/simbricks/orchestration/system/nic.py
View file @
3bbc0c04
...
...
@@ -20,28 +20,65 @@
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from
__future__
import
annotations
from
simbricks.orchestration.system
import
base
from
simbricks.orchestration.system
import
pcie
from
simbricks.orchestration.system
import
eth
from
simbricks.orchestration.utils
import
base
as
utils_base
class
SimplePCIeNIC
(
pcie
.
PCIeSimpleDevice
,
eth
.
EthSimpleNIC
):
class
SimplePCIeNIC
(
base
.
Component
):
def
__init__
(
self
,
s
:
base
.
System
)
->
None
:
super
().
__init__
(
s
)
def
interfaces
(
self
)
->
list
[
base
.
Interface
]:
return
[
self
.
_pci_if
,
self
.
_eth_if
]
self
.
_ip
:
str
|
None
=
None
self
.
_eth_if
:
eth
.
EthInterface
=
eth
.
EthInterface
(
self
)
super
().
add_if
(
self
.
_eth_if
)
self
.
_pci_if
:
pcie
.
PCIeDeviceInterface
=
pcie
.
PCIeDeviceInterface
(
self
)
super
().
add_if
(
self
.
_pci_if
)
def
add_if
(
self
,
interface
:
eth
.
EthInterface
|
pcie
.
PCIeDeviceInterface
)
->
None
:
match
interface
:
case
eth
.
EthInterface
():
eth
.
EthSimpleNIC
.
add_if
(
self
,
interface
=
interface
)
if
hasattr
(
self
,
"_eth_if"
)
and
self
.
_eth_if
:
print
(
interface
)
print
(
self
.
_eth_if
)
raise
Exception
(
f
"you overwrite SimplePCIeNIC._eth_if (
{
self
.
_eth_if
.
id
()
}
->
{
interface
.
id
()
}
) "
)
self
.
_eth_if
=
interface
case
pcie
.
PCIeDeviceInterface
():
pcie
.
PCIeSimpleDevice
.
add_if
(
self
,
interface
=
interface
)
if
hasattr
(
self
,
"_pci_if"
)
and
self
.
_pci_if
:
raise
Exception
(
f
"you overwrite SimplePCIeNIC._pci_if. (
{
self
.
_pci_if
.
id
()
}
->
{
interface
.
id
()
}
)"
)
self
.
_pci_if
=
interface
case
_
:
raise
Exception
(
f
"interface must have type EthInterface or PCIeDeviceInterface but has type
{
type
(
interface
)
}
"
)
super
().
add_if
(
interface
)
def
add_ipv4
(
self
,
ip
:
str
)
->
None
:
assert
self
.
_ip
is
None
self
.
_ip
=
ip
def
toJSON
(
self
)
->
dict
:
json_obj
=
super
().
toJSON
()
json_obj
[
"ip"
]
=
self
.
_ip
json_obj
[
"eth_if"
]
=
self
.
_eth_if
.
id
()
json_obj
[
"pci_if"
]
=
self
.
_pci_if
.
id
()
return
json_obj
@
classmethod
def
fromJSON
(
cls
,
system
:
base
.
System
,
json_obj
:
dict
)
->
SimplePCIeNIC
:
instance
=
super
().
fromJSON
(
system
,
json_obj
)
instance
.
_ip
=
utils_base
.
get_json_attr_top
(
json_obj
,
"ip"
)
eth_inf_id
=
int
(
utils_base
.
get_json_attr_top
(
json_obj
,
"eth_if"
))
instance
.
_eth_if
=
system
.
get_inf
(
eth_inf_id
)
inf_id
=
int
(
utils_base
.
get_json_attr_top
(
json_obj
,
"pci_if"
))
instance
.
_pci_if
=
system
.
get_inf
(
inf_id
)
return
instance
class
IntelI40eNIC
(
SimplePCIeNIC
):
...
...
experiments/simbricks/orchestration/system/pcie.py
View file @
3bbc0c04
...
...
@@ -20,6 +20,8 @@
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from
__future__
import
annotations
from
simbricks.orchestration.system
import
base
from
simbricks.orchestration.utils
import
base
as
utils_base
...
...
@@ -57,19 +59,25 @@ class PCIeSimpleDevice(base.Component):
def
__init__
(
self
,
s
:
base
.
System
):
super
().
__init__
(
s
)
self
.
_pci_if
:
PCIeDeviceInterface
=
PCIeDeviceInterface
(
self
)
def
interfaces
(
self
)
->
list
[
base
.
Interface
]:
return
[
self
.
_pci_if
]
super
().
add_if
(
self
.
_pci_if
)
def
add_if
(
self
,
interface
:
PCIeDeviceInterface
)
->
None
:
raise
Exception
(
"PCIeSimpleDevice already has PCI device interface"
)
utils_base
.
has_expected_type
(
interface
,
PCIeDeviceInterface
)
if
self
.
_pci_if
:
raise
Exception
(
f
"you overwrite PCIeSimpleDevice._pci_if. (
{
self
.
_pci_if
.
id
()
}
->
{
interface
.
id
()
}
)"
)
self
.
_pci_if
=
interface
super
().
add_if
(
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
@
classmethod
def
fromJSON
(
cls
,
system
:
base
.
System
,
json_obj
:
dict
)
->
PCIeSimpleDevice
:
instance
=
super
().
fromJSON
(
system
=
system
,
json_obj
=
json_obj
)
inf_id
=
int
(
utils_base
.
get_json_attr_top
(
json_obj
,
"pci_if"
))
instance
.
_pci_if
=
system
.
get_inf
(
inf_id
)
return
instance
experiments/simbricks/orchestration/utils/base.py
View file @
3bbc0c04
...
...
@@ -22,6 +22,7 @@
import
abc
import
itertools
import
importlib
class
IdObj
(
abc
.
ABC
):
...
...
@@ -37,11 +38,13 @@ class IdObj(abc.ABC):
json_obj
=
{}
json_obj
[
"id"
]
=
self
.
_id
return
json_obj
@
staticmethod
def
fromJSON
(
json_obj
):
# TODO
pass
@
classmethod
def
fromJSON
(
cls
,
json_obj
):
instance
=
cls
.
__new__
(
cls
)
instance
.
_id
=
get_json_attr_top
(
json_obj
,
"id"
)
return
instance
def
check_type
(
obj
,
expected_type
)
->
bool
:
"""
...
...
@@ -57,9 +60,41 @@ 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
}
"
)
raise
Exception
(
f
"obj of type
{
type
(
obj
)
}
no attribute called
{
attr
}
"
)
def
get_json_attr_top_or_none
(
json_obj
:
dict
,
attr
:
str
)
->
dict
|
None
:
if
attr
in
json_obj
:
return
json_obj
[
attr
]
return
None
def
has_json_attr_top
(
json_obj
:
dict
,
attr
:
str
)
->
None
:
if
not
attr
in
json_obj
:
raise
Exception
(
f
"
{
json_obj
}
does not contain key
{
attr
}
"
)
def
get_json_attr_top
(
json_obj
:
dict
,
attr
:
str
)
->
dict
:
has_json_attr_top
(
json_obj
,
attr
)
return
json_obj
[
attr
]
def
get_cls_from_type_module
(
type_name
:
str
,
module_name
:
str
):
# Import the module
module
=
importlib
.
import_module
(
module_name
)
# Get the class from the module
cls
=
getattr
(
module
,
type_name
)
return
cls
def
get_cls_by_json
(
json_obj
:
dict
):
type_name
=
get_json_attr_top
(
json_obj
,
"type"
)
module_name
=
get_json_attr_top
(
json_obj
,
"module"
)
return
get_cls_from_type_module
(
type_name
,
module_name
)
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