package albatross
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Albatross - orchestrate and manage MirageOS unikernels with Solo5
Install
dune-project
Dependency
Authors
Maintainers
Sources
albatross-2.6.0.tbz
sha256=95335cd203ba8f4b47a0fa2135ae2adc677c5a09a9e85bf729800eeb78f79de6
sha512=5661030612576a2941f57935cf9ceaf04b859e58cd6e70cc1372a9491b85ddaa17e3773c27df5c072fc166533f66ee0663fd52b2e1c4451f1e119dda26ebbac9
doc/src/albatross/vmm_resources.ml.html
Source file vmm_resources.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315(* (c) 2017, 2018 Hannes Mehnert, all rights reserved *) open Vmm_core let ( let* ) = Result.bind type t = { policies : Policy.t Vmm_trie.t ; block_devices : (int * bool) Vmm_trie.t ; unikernels : Unikernel.t Vmm_trie.t ; } let pp ppf t = Vmm_trie.fold Name.root_path t.policies (fun id p () -> Fmt.pf ppf "policy %a: %a@." Name.pp id Policy.pp p) () ; Vmm_trie.fold Name.root_path t.block_devices (fun id (size, used) () -> Fmt.pf ppf "block device %a: %d MB (used %B)@." Name.pp id size used) () ; Vmm_trie.fold Name.root_path t.unikernels (fun id unikernel () -> Fmt.pf ppf "unikernel %a: %a@." Name.pp id Unikernel.pp_config unikernel.Unikernel.config) () let empty = { policies = Vmm_trie.empty ; block_devices = Vmm_trie.empty ; unikernels = Vmm_trie.empty } let policy_metrics = let open Metrics in let doc = "Albatross resource policies" in let data policy = Data.v [ uint "maximum unikernels" policy.Policy.unikernels ; uint "maximum memory" policy.Policy.memory ; uint "maximum block" (match policy.Policy.block with None -> 0 | Some x -> x) ] in let tag = Tags.string "domain" in Src.v ~doc ~tags:Tags.[tag] ~data "albatross-policies" let no_policy = Policy.{ unikernels = 0 ; cpuids = IS.empty ; memory = 0 ; block = None ; bridges = String_set.empty } (* we should confirm the following invariant: Unikernel or Block have no siblings *) let block_usage t path = Vmm_trie.fold path t.block_devices (fun _ (size, act) (active, inactive) -> if act then active + size, inactive else active, inactive + size) (0, 0) let total_block_usage t path = let act, inact = block_usage t path in act + inact let unikernel_usage t path = Vmm_trie.fold path t.unikernels (fun _ unikernel (unikernels, memory) -> (succ unikernels, memory + unikernel.Unikernel.config.Unikernel.memory)) (0, 0) let unikernel_metrics = let open Metrics in let doc = "Albatross unikernels" in let data (t, path) = let unikernels, memory = unikernel_usage t path and act, inact = block_usage t path in Data.v [ uint "attached used block" act ; uint "unattached used block" inact ; uint "total used block" (act + inact) ; uint "running unikernels" unikernels ; uint "used memory" memory ] in let tag = Tags.string "domain" in Src.v ~doc ~tags:Tags.[tag] ~data "albatross-unikernels" let report_unikernels t name = let rec doit path = let str = if Name.is_root_path path then ":" else Name.path_to_string path in Metrics.add unikernel_metrics (fun x -> x str) (fun d -> d (t, path)); if Name.is_root_path path then () else doit (Name.parent_path path) in doit (Name.path name) let find_unikernel t name = Vmm_trie.find name t.unikernels let find_policy t path = Vmm_trie.find (Vmm_core.Name.create_of_path path) t.policies let find_block t name = Vmm_trie.find name t.block_devices let set_block_usage t name active = match Vmm_trie.find name t with | None -> invalid_arg ("block device " ^ Name.to_string name ^ " not in trie") | Some (size, curr) -> if curr = active then invalid_arg ("block device " ^ Name.to_string name ^ " already in state " ^ (if curr then "active" else "inactive")) else fst (Vmm_trie.insert name (size, active) t) let use_blocks t name unikernel active = match unikernel.Unikernel.config.Unikernel.block_devices with | [] -> t | blocks -> let block_names = List.map (fun (bd, dev, _sector_size) -> let bd = match dev with None -> bd | Some b -> b in Name.block_name name bd) blocks in List.fold_left (fun t' n -> set_block_usage t' n active) t block_names let remove_unikernel t name = match find_unikernel t name with | None -> Error (`Msg "unknown unikernel") | Some unikernel -> let block_devices = use_blocks t.block_devices name unikernel false in let unikernels = Vmm_trie.remove name t.unikernels in let t' = { t with block_devices ; unikernels } in report_unikernels t' name; Ok t' let remove_policy t path = match find_policy t path with | None -> Error (`Msg "unknown policy") | Some _ -> let policies = Vmm_trie.remove (Vmm_core.Name.create_of_path path) t.policies in Metrics.add policy_metrics (fun x -> x (Name.path_to_string path)) (fun d -> d no_policy); Ok { t with policies } let remove_block t name = match find_block t name with | None -> Error (`Msg (Fmt.str "unknown block device %s" (Name.to_string name))) | Some (_, active) -> if active then Error (`Msg (Fmt.str "block device %s in use" (Name.to_string name))) else let block_devices = Vmm_trie.remove name t.block_devices in let t' = { t with block_devices } in report_unikernels t' name; Ok t' let bridge_allowed set s = String_set.mem s set let check_policy (p : Policy.t) (running_unikernels, used_memory) (unikernel : Unikernel.config) = if succ running_unikernels > p.Policy.unikernels then Error (`Msg (Fmt.str "maximum amount of unikernels (%d) reached" p.Policy.unikernels)) else if unikernel.Unikernel.memory > p.Policy.memory - used_memory then Error (`Msg (Fmt.str "maximum allowed memory (%d, used %d) would be exceeded (requesting %d)" p.Policy.memory used_memory unikernel.Unikernel.memory)) else if not (IS.mem unikernel.Unikernel.cpuid p.Policy.cpuids) then Error (`Msg (Fmt.str "CPUid %u is not allowed by policy" unikernel.Unikernel.cpuid)) else match List.partition (bridge_allowed p.Policy.bridges) (Unikernel.bridges unikernel) with | _, [] -> Ok () | _, disallowed -> Error (`Msg (Fmt.str "bridges %a not allowed by policy" Fmt.(list ~sep:(any ", ") string) disallowed)) let check_unikernel t name unikernel = let policy_ok = let path = Name.path name in match find_policy t path with | None -> Ok () | Some p -> let used = unikernel_usage t path in check_policy p used unikernel and block_ok = List.fold_left (fun r (block, dev, _sector_size) -> let* () = r in let bl = match dev with Some b -> b | None -> block in let block_name = Name.block_name name bl in match find_block t block_name with | None -> Error (`Msg (Fmt.str "block device %s not found" (Name.to_string block_name))) | Some (_, active) -> if active then Error (`Msg (Fmt.str "block device %s already in use" (Name.to_string block_name))) else Ok ()) (Ok ()) unikernel.block_devices and unikernel_ok = match find_unikernel t name with | None -> Ok () | Some _ -> Error (`Msg "unikernel with same name already exists") in let* () = policy_ok in let* () = block_ok in unikernel_ok let insert_unikernel t name unikernel = let unikernels, old = Vmm_trie.insert name unikernel t.unikernels in (match old with None -> () | Some _ -> invalid_arg ("unikernel " ^ Name.to_string name ^ " already exists in trie")) ; let block_devices = use_blocks t.block_devices name unikernel true in let t' = { t with unikernels ; block_devices } in report_unikernels t' name; t' let check_block t name size = let block_ok = match find_block t name with | Some _ -> Error (`Msg (Fmt.str "block device with name %a already exists" Name.pp name)) | None -> Ok () and policy_ok = let path = Name.path name in match find_policy t path with | None -> Ok () | Some p -> let used = total_block_usage t path in match p.Policy.block with | None -> Error (`Msg "no block devices are allowed by policy") | Some limit -> if size <= limit - used then Ok () else Error (`Msg (Fmt.str "block device policy limit of %d MB (used %d MB) would be exceeded by the request (%d MB)" limit used size)) in let* () = block_ok in policy_ok let insert_block t name size = let* () = check_block t name size in let block_devices = fst (Vmm_trie.insert name (size, false) t.block_devices) in let t' = { t with block_devices } in report_unikernels t' name; Ok t' let reserve_block t name size = let* () = check_block t name size in let block_devices = fst (Vmm_trie.insert name (size, true) t.block_devices) in Ok { t with block_devices } let commit_block t name = match Vmm_trie.find name t.block_devices with | None -> Error (`Msg ("block device " ^ Name.to_string name ^ " not in trie")) | Some (size, curr) -> if not curr then Error (`Msg ("block device " ^ Name.to_string name ^ " already in state inactive")) else let block_devices = fst (Vmm_trie.insert name (size, false) t.block_devices) in Ok { t with block_devices } let check_policies_above t path sub = let rec go prefix = if Name.is_root_path prefix then Ok () else let* () = match find_policy t prefix with | None -> Ok () | Some super -> Policy.is_smaller ~super ~sub in go (Name.parent_path prefix) in go (Name.parent_path path) let check_policies_below t path super = Vmm_trie.fold path t.policies (fun name policy res -> let* () = res in if Name.is_root name then res else Policy.is_smaller ~super ~sub:policy) (Ok ()) let check_unikernels t path p = let (unikernels, used_memory) = unikernel_usage t path and block = total_block_usage t path in let bridges, cpuids = Vmm_trie.fold path t.unikernels (fun _ unikernel (bridges, cpuids) -> let config = unikernel.Unikernel.config in (String_set.(union (of_list (Unikernel.bridges config)) bridges), IS.add config.Unikernel.cpuid cpuids)) (String_set.empty, IS.empty) in let policy_block = match p.Policy.block with None -> 0 | Some x -> x in if not (IS.subset cpuids p.Policy.cpuids) then Error (`Msg (Fmt.str "policy allows CPUids %a, which is not a superset of %a" Fmt.(list ~sep:(any ", ") int) (IS.elements p.Policy.cpuids) Fmt.(list ~sep:(any ", ") int) (IS.elements cpuids))) else if not (String_set.subset bridges p.Policy.bridges) then Error (`Msg (Fmt.str "policy allows bridges %a, which is not a superset of %a" Fmt.(list ~sep:(any ", ") string) (String_set.elements p.Policy.bridges) Fmt.(list ~sep:(any ", ") string) (String_set.elements bridges))) else if unikernels > p.Policy.unikernels then Error (`Msg (Fmt.str "unikernel would exceed running unikernel limit set by policy to %d, running %d" p.Policy.unikernels unikernels)) else if used_memory > p.Policy.memory then Error (`Msg (Fmt.str "unikernel would exceed running memory limit set by policy to %d MB, used %d MB" p.Policy.memory used_memory)) else if block > policy_block then Error (`Msg (Fmt.str "unikernel would exceed running block storage limit set by policy to %d MB, used %d MB" policy_block block)) else Ok () let insert_policy t path p = let* () = check_policies_above t path p in let* () = check_policies_below t path p in let* () = check_unikernels t path p in let policies = fst (Vmm_trie.insert (Vmm_core.Name.create_of_path path) p t.policies) in Metrics.add policy_metrics (fun x -> x (Name.path_to_string path)) (fun d -> d p); Ok { t with policies }
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>