package albatross
Albatross - orchestrate and manage MirageOS unikernels with Solo5
Install
Dune Dependency
Authors
Maintainers
Sources
albatross-v1.2.0.tbz
sha256=1b9159e5d01840baf8979386c3fab7dffc36b717f0ff75bc4d1f6fe4ce1cb413
sha512=b94838ea09fb41b502475ab8a94d2c66a30f3b1d580c528b729419752673cb21fc03fba272e60c7bfed4fb721fbfb244bdfbd71208991c3355de56110939a919
doc/src/albatross.cli/albatross_cli.ml.html
Source file albatross_cli.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 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
(* (c) 2018 Hannes Mehnert, all rights reserved *) open Astring open Vmm_core open Lwt.Infix let process = Metrics.field ~doc:"name of the process" "vm" Metrics.String let init_influx name data = match data with | None -> () | Some (ip, port) -> Logs.info (fun m -> m "stats connecting to %a:%d" Ipaddr.V4.pp ip port); Metrics.enable_all (); Metrics_lwt.init_periodic (fun () -> Lwt_unix.sleep 10.); Metrics_lwt.periodically (Metrics_rusage.rusage_src ~tags:[]); Metrics_lwt.periodically (Metrics_rusage.kinfo_mem_src ~tags:[]); let get_cache, reporter = Metrics.cache_reporter () in Metrics.set_reporter reporter; let fd = ref None in let rec report () = let send () = (match !fd with | Some _ -> Lwt.return_unit | None -> let addr = Lwt_unix.ADDR_INET (Ipaddr_unix.V4.to_inet_addr ip, port) in Vmm_lwt.connect Lwt_unix.PF_INET addr >|= function | None -> Logs.err (fun m -> m "connection failure to stats") | Some fd' -> fd := Some fd') >>= fun () -> match !fd with | None -> Lwt.return_unit | Some socket -> let tag = process name in let datas = Metrics.SM.fold (fun src (, data) acc -> let name = Metrics.Src.name src in Metrics_influx.encode_line_protocol (tag :: tags) data name :: acc) (get_cache ()) [] in let datas = String.concat ~sep:"" datas in Vmm_lwt.write_raw socket (Bytes.unsafe_of_string datas) >|= function | Ok () -> () | Error `Exception -> Logs.warn (fun m -> m "error on stats write"); fd := None and sleep () = Lwt_unix.sleep 10. in Lwt.join [ send () ; sleep () ] >>= report in Lwt.async report type exit_status = | Success | Local_authentication_failed | Remote_authentication_failed | Communication_failed | Connect_failed | Remote_command_failed | Cli_failed | Internal_error let output_result ((hdr, reply) as wire) = match reply with | `Success s -> Logs.app (fun m -> m "%a" Vmm_commands.pp_wire wire); let write_to_file name compressed data = let filename = let ts = Ptime.to_rfc3339 (Ptime_clock.now ()) in Fpath.(v (Filename.get_temp_dir_name ()) / Name.to_string name + ts) in let write data = match Bos.OS.File.write filename data with | Ok () -> Logs.app (fun m -> m "dumped image to %a" Fpath.pp filename) | Error (`Msg e) -> Logs.err (fun m -> m "failed to write image: %s" e) in if compressed then match Vmm_compress.uncompress (Cstruct.to_string data) with | Ok blob -> write blob | Error () -> Logs.err (fun m -> m "failed to uncompress image") else write (Cstruct.to_string data) in begin match s with | `Unikernel_image (compressed, image) -> let name = hdr.Vmm_commands.name in write_to_file name compressed image | `Old_unikernels vms -> List.iter (fun (name, cfg) -> if Cstruct.len cfg.Unikernel.image > 0 then write_to_file name cfg.Unikernel.compressed cfg.Unikernel.image) vms | _ -> () end; Ok () | `Data _ -> Logs.app (fun m -> m "%a" Vmm_commands.pp_wire wire); Ok () | `Failure _ -> Logs.warn (fun m -> m "%a" Vmm_commands.pp_wire wire); Error Remote_command_failed | `Command _ -> Logs.err (fun m -> m "received unexpected command %a" Vmm_commands.pp_wire wire); Error Internal_error let setup_log style_renderer level = Fmt_tty.setup_std_outputs ?style_renderer (); Logs.set_level level; Logs.set_reporter (Logs_fmt.reporter ~dst:Format.std_formatter ()) let create_vm force image cpuid memory argv block_devices bridges compression restart_on_fail exit_codes = let open Rresult.R.Infix in let img_file = Fpath.v image in Bos.OS.File.read img_file >>= fun image -> Vmm_unix.manifest_devices_match ~bridges ~block_devices img_file >>| fun () -> let image, compressed = match compression with | 0 -> Cstruct.of_string image, false | level -> let img = Vmm_compress.compress ~level image in Cstruct.of_string img, true and argv = match argv with [] -> None | xs -> Some xs and fail_behaviour = let exits = match exit_codes with [] -> None | xs -> Some (IS.of_list xs) in if restart_on_fail then `Restart exits else `Quit in let config = { Unikernel.typ = `Solo5 ; compressed ; image ; fail_behaviour ; cpuid ; memory ; block_devices ; bridges ; argv } in if force then `Unikernel_force_create config else `Unikernel_create config let policy vms memory cpus block bridges = let bridges = String.Set.of_list bridges and cpuids = IS.of_list cpus in Policy.{ vms ; cpuids ; memory ; block ; bridges } open Cmdliner let setup_log = Term.(const setup_log $ Fmt_cli.style_renderer () $ Logs_cli.level ()) let ip_port : (Ipaddr.V4.t * int) Arg.converter = let default_port = 8094 in let parse s = match match String.cut ~sep:":" s with | None -> Ok (s, default_port) | Some (ip, port) -> match int_of_string port with | exception Failure _ -> Error "non-numeric port" | port -> Ok (ip, port) with | Error msg -> `Error msg | Ok (ip, port) -> match Ipaddr.V4.of_string ip with | Ok ip -> `Ok (ip, port) | Error `Msg msg -> `Error msg in parse, fun ppf (ip, port) -> Format.fprintf ppf "%a:%d" Ipaddr.V4.pp ip port let influx = let doc = "IP address and port (default: 8094) to report metrics to in influx line protocol" in Arg.(value & opt (some ip_port) None & info [ "influx" ] ~doc ~docv:"INFLUXHOST[:PORT]") let host_port : (string * int) Arg.converter = let parse s = match String.cut ~sep:":" s with | None -> `Error "broken: no port specified" | Some (hostname, port) -> try `Ok (hostname, int_of_string port) with Not_found -> `Error "failed to parse port" in parse, fun ppf (h, p) -> Format.fprintf ppf "%s:%d" h p let vm_c = let parse s = match Name.of_string s with | Error (`Msg msg) -> `Error msg | Ok name -> `Ok name in (parse, Name.pp) let bridge_tap_c = let parse s = match Astring.String.cut ~sep:":" s with | None -> `Error "broken, format is bridge:tap" | Some (bridge, tap) -> `Ok (bridge, tap) in (parse, fun ppf (bridge, tap) -> Format.fprintf ppf "%s:%s" bridge tap) let bridge_taps = let doc = "Bridge and tap device names" in Arg.(value & opt_all bridge_tap_c [] & info [ "bridge" ] ~doc) let pid_req1 = let doc = "Process id" in Arg.(required & pos 1 (some int) None & info [] ~doc ~docv:"PID") let vmm_dev_req0 = let doc = "VMM device name" in Arg.(required & pos 0 (some string) None & info [] ~doc ~docv:"VMMDEV") let opt_vm_name = let doc = "name of virtual machine." in Arg.(value & opt vm_c Name.root & info [ "n" ; "name"] ~doc) let compress_level default = let doc = "Compression level (0 - 9), a higher value results in smaller data, but uses more CPU " in Arg.(value & opt int default & info [ "compression-level" ] ~doc) let force = let doc = "force VM creation." in Arg.(value & flag & info [ "f" ; "force" ] ~doc) let cpus = let doc = "CPUids to allow" in Arg.(value & opt_all int [] & info [ "cpu" ] ~doc) let vms = let doc = "Number of VMs to allow" in Arg.(required & pos 1 (some int) None & info [] ~doc ~docv:"VMS") let image = let doc = "File of virtual machine image." in Arg.(required & pos 1 (some file) None & info [] ~doc ~docv:"IMAGE") let vm_name = let doc = "Name virtual machine." in Arg.(required & pos 0 (some vm_c) None & info [] ~doc ~docv:"VM") let block_name = let doc = "Name of block device." in Arg.(required & pos 0 (some vm_c) None & info [] ~doc ~docv:"BLOCK") let block_size = let doc = "Block size in MB." in Arg.(required & pos 1 (some int) None & info [] ~doc ~docv:"SIZE") let opt_block_name = let doc = "Name of block device." in Arg.(value & opt vm_c Name.root & info [ "name" ] ~doc) let opt_block_size = let doc = "Block storage to allow in MB" in Arg.(value & opt (some int) None & info [ "size" ] ~doc) let mem = let doc = "Memory to allow in MB" in Arg.(value & opt int 512 & info [ "mem" ] ~doc) let bridge = let doc = "Bridges to allow" in Arg.(value & opt_all string [] & info [ "bridge" ] ~doc) let cpu = let doc = "CPUid to use" in Arg.(value & opt int 0 & info [ "cpu" ] ~doc) let vm_mem = let doc = "Assigned memory in MB" in Arg.(value & opt int 32 & info [ "mem" ] ~doc) let args = let doc = "Boot arguments" in Arg.(value & opt_all string [] & info [ "arg" ] ~doc) let colon_separated_c = let parse s = match Astring.String.cut ~sep:":" s with | None -> `Ok (s, None) | Some (a, b) -> `Ok (a, Some b) in (parse, fun ppf (a, b) -> Fmt.pf ppf "%s:%s" a (match b with None -> a | Some b -> b)) let block = let doc = "Block device name (block or name:block-device-name)" in Arg.(value & opt_all colon_separated_c [] & info [ "block" ] ~doc) let net = let doc = "Network device names (bridge or name:bridge)" in Arg.(value & opt_all colon_separated_c [] & info [ "net" ] ~doc) let restart_on_fail = let doc = "Restart on fail" in Arg.(value & flag & info [ "restart-on-fail" ] ~doc) let exit_code = let doc = "Exit code to restart on" in Arg.(value & opt_all int [] & info [ "exit-code" ] ~doc) let timestamp_c = let parse s = match Ptime.of_rfc3339 s with | Ok (t, _, _) -> `Ok t | Error _ -> (* let's try to add T00:00:00-00:00 *) match Ptime.of_rfc3339 (s ^ "T00:00:00-00:00") with | Ok (t, _, _) -> `Ok t | Error _ -> `Error "couldn't parse timestamp" in (parse, Ptime.pp_rfc3339 ()) let since = let doc = "Receive data since a specified timestamp (RFC 3339 encoded)" in Arg.(value & opt (some timestamp_c) None & info [ "since" ] ~doc) let count = let doc = "Receive N data records" in Arg.(value & opt int 20 & info [ "count" ] ~doc) let since_count since count = match since with | None -> `Count count | Some since -> `Since since let version = Fmt.strf "version v1.2.0 protocol version %a" Vmm_commands.pp_version Vmm_commands.current let default_tmpdir = match Lazy.force Vmm_unix.uname with | FreeBSD -> "/var/run/albatross" | Linux -> "/run/albatross" let tmpdir = let doc = "Albatross temporary directory" in Arg.(value & opt dir default_tmpdir & info [ "tmpdir" ] ~doc) let set_tmpdir path = match Fpath.of_string path with | Ok path -> Vmm_core.set_tmpdir path | Error `Msg m -> invalid_arg m let default_dbdir = match Lazy.force Vmm_unix.uname with | Vmm_unix.FreeBSD -> "/var/db/albatross" | Linux -> "/var/lib/albatross" let dbdir = let doc = "Albatross database directory" in Arg.(value & opt dir default_dbdir & info [ "dbdir" ] ~doc) let set_dbdir path = match Fpath.of_string path with | Ok path -> Vmm_unix.set_dbdir path | Error `Msg m -> invalid_arg m let enable_stats = let doc = "Connect to albatross-stats to report statistics" in Arg.(value & flag & info [ "enable-stats" ] ~doc) let retry_connections = let doc = "Number of retries when connecting to other daemons (log, console, stats etc). 0 aborts after one failure, -1 is unlimited retries." in Arg.(value & opt int 2 & info [ "retry-connections" ] ~doc) let systemd_socket_activation = match Lazy.force Vmm_unix.uname with | FreeBSD -> Term.const false | Linux -> let doc = "Pass this flag when systemd socket activation is being used" in Arg.(value & flag & info [ "systemd-socket-activation" ] ~doc) let exit_status = function | Ok () -> Ok Success | Error e -> Ok e (* exit status already in use: - 0 success - 2 OCaml exception - 124 "cli error" - 125 "internal error" - 126 (bash) command invoked cannot execute - 127 (bash) command not found - 255 OCaml abort *) let local_authentication_failed = 119 let remote_authentication_failed = 120 let communication_failed = 121 let connect_failed = 122 let remote_command_failed = 123 let exit_status_to_int = function | Success -> 0 | Local_authentication_failed -> local_authentication_failed | Remote_authentication_failed -> remote_authentication_failed | Communication_failed -> communication_failed | Connect_failed -> connect_failed | Remote_command_failed -> remote_command_failed | Cli_failed -> Term.exit_status_cli_error | Internal_error -> Term.exit_status_internal_error let exits = Term.exit_info ~doc:"on communication (read or write) failure" communication_failed :: Term.exit_info ~doc:"on connection failure" connect_failed :: Term.exit_info ~doc:"on remote command execution failure" remote_command_failed :: Term.default_exits let auth_exits = [ Term.exit_info ~doc:"on local authentication failure \ (certificate not accepted by remote)" local_authentication_failed ; Term.exit_info ~doc:"on remote authentication failure \ (couldn't validate trust anchor)" remote_authentication_failed ]
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>