13
13
from aiohttp import ClientResponseError
14
14
from aleph_message .models import ExecutableContent , ItemHash
15
15
from aleph_message .models .execution .environment import MachineResources
16
- from aleph_message .models .execution .volume import PersistentVolume
16
+ from aleph_message .models .execution .volume import MachineVolume , PersistentVolume
17
17
18
18
from aleph .vm .conf import settings
19
19
from aleph .vm .controllers .configuration import (
@@ -71,6 +71,7 @@ class HostVolume:
71
71
mount : str
72
72
path_on_host : Path
73
73
read_only : bool
74
+ size_mib : int | None
74
75
75
76
76
77
@dataclass
@@ -100,6 +101,35 @@ class AlephFirecrackerResources:
100
101
volumes : list [HostVolume ]
101
102
namespace : str
102
103
104
+ def get_disk_usage_delta (self ) -> int :
105
+ """Difference between the size requested and what is currently used on disk.
106
+
107
+ Count rootfs and volumes.
108
+ Used to calculate an estimate of space resource available for use.
109
+ Value in bytes and is negative"""
110
+
111
+ total_delta = 0
112
+ # Root fs
113
+ if hasattr (self .message_content , "rootfs" ):
114
+ volume = self .message_content .rootfs
115
+ used_size = self .rootfs_path .stat ().st_size if self .rootfs_path .exists () else 0
116
+ requested_size = int (volume .size_mib * 1024 * 1024 )
117
+ size_delta = used_size - requested_size
118
+ total_delta += size_delta
119
+
120
+ # Count each extra volume
121
+ for volume in self .volumes :
122
+ if not volume .size_mib :
123
+ # planned size not set on immutable volume
124
+ size_delta = 0
125
+ else :
126
+ used_size = volume .path_on_host .stat ().st_size if volume .path_on_host .exists () else 0
127
+ requested_size = int (volume .size_mib * 1024 * 1024 )
128
+
129
+ size_delta = used_size - requested_size
130
+ total_delta += size_delta
131
+ return total_delta
132
+
103
133
def __init__ (self , message_content : ExecutableContent , namespace : str ):
104
134
self .message_content = message_content
105
135
self .namespace = namespace
@@ -115,8 +145,9 @@ async def download_kernel(self):
115
145
async def download_volumes (self ):
116
146
volumes = []
117
147
# TODO: Download in parallel and prevent duplicated volume names
148
+ volume : MachineVolume
118
149
for i , volume in enumerate (self .message_content .volumes ):
119
- # only persistant volume has name and mount
150
+ # only persistent volume has name and mount
120
151
if isinstance (volume , PersistentVolume ):
121
152
if not volume .name :
122
153
volume .name = f"unamed_volume_{ i } "
@@ -127,6 +158,7 @@ async def download_volumes(self):
127
158
mount = volume .mount ,
128
159
path_on_host = (await get_volume_path (volume = volume , namespace = self .namespace )),
129
160
read_only = volume .is_read_only (),
161
+ size_mib = getattr (volume , "size_mib" , None ),
130
162
)
131
163
)
132
164
self .volumes = volumes
0 commit comments