Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file vmm_core.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445(* (c) 2017, 2018 Hannes Mehnert, all rights reserved *)letconn_metricskind=lets=ref(0,0)inletopenMetricsinletdoc="connection statistics"inletdata()=Data.v[int"active"(fst!s);int"total"(snd!s);]inlettags=Tags.string"kind"inletsrc=Src.v~doc~tags:Tags.[tags]~data"connections"in(funaction->(matchactionwith|`Open->s:=(succ(fst!s),succ(snd!s))|`Close->s:=(pred(fst!s),snd!s));Metrics.addsrc(funx->xkind)(fund->d()))openAstringlettmpdir=ref(Fpath.v"/nonexisting")letset_tmpdirpath=tmpdir:=pathtypeservice=[`Console|`Stats|`Vmmd]letsocket_patht=letpath=matchtwith|`Console->"console"|`Vmmd->"vmmd"|`Stats->"stat"inFpath.to_stringFpath.(!tmpdir/"util"/path+"sock")letpp_socketppft=letname=socket_pathtinFmt.pfppf"socket: %s"namemoduleI=structtypet=intletcompare:int->int->int=compareendmoduleIS=Set.Make(I)moduleIM=Map.Make(I)moduleName=structtypet=stringlistletroot=[]letis_rootx=x=[]letrecequalxy=matchx,ywith|[],[]->true|x::xs,y::ys->x=y&&equalxsys|_->falselet[@inlinealways]valid_labels=String.lengths<20&&String.lengths>0&&String.gets0<>'-'&&(* leading may not be '-' *)String.for_all(function|'a'..'z'|'A'..'Z'|'0'..'9'|'-'->true|_->false)s(* only LDH (letters, digits, hyphen)! *)letto_string=function|[]->"."|ids->String.concat~sep:"."idsletto_listx=xletdropx=matchList.revxwith|[]->[]|_::tl->List.revtlletdrop_front=function|[]->[]|_::tl->tlletappend_exnlblx=ifvalid_labellblthenx@[lbl]elseinvalid_arg"label not valid"letappendlblx=ifvalid_labellblthenOk(x@[lbl])elseError(`Msg"label not valid")letprependlblx=ifvalid_labellblthenOk(lbl::x)elseError(`Msg"label not valid")letconcatab=a@bletdomainid=matchList.revidwith|_::prefix->List.revprefix|[]->[]letimage_filename=letfile=to_stringnameinFpath.(!tmpdir/file+"img")letfifo_filename=letfile=to_stringnameinFpath.(!tmpdir/"fifo"/file)letblock_namevm_namedev=List.rev(dev::List.rev(domainvm_name))letof_stringstr=letid=String.cuts~sep:"."strinifList.for_allvalid_labelidthenOkidelseError(`Msg"invalid name")letof_listlabels=ifList.for_allvalid_labellabelsthenOklabelselseError(`Msg"invalid name")letdrop_super~super~sub=letrecgosupsub=matchsup,subwith|[],xs->Somexs|_,[]->None|x::xs,z::zs->ifString.equalxzthengoxszselseNoneingosupersubletis_sub~super~sub=matchdrop_super~super~subwithNone->false|Some_->trueletppppfids=Fmt.(pfppf"[vm: %a]"(list~sep:(unit".")string)ids)letmacnamebridge=(* deterministic mac address computation: VEB Kombinat Robotron prefix
vielen dank, liebe genossen! *)letprefix="\x00\x80\x41"andours=Digest.string(to_string(bridge::name))inMacaddr.of_octets_exn(prefix^String.take~min:3~max:3ours)endmodulePolicy=structletpp_isppfis=Fmt.pfppf"%a"Fmt.(list~sep:(unit",")int)(IS.elementsis)leteq_int(a:int)(b:int)=a=btypet={vms:int;cpuids:IS.t;memory:int;block:intoption;bridges:String.Set.t;}letequalp1p2=leteq_optab=matcha,bwith|None,None->true|Somea,Someb->eq_intab|_->falseineq_intp1.vmsp2.vms&&IS.equalp1.cpuidsp2.cpuids&&eq_intp1.memoryp2.memory&&eq_optp1.blockp2.block&&String.Set.equalp1.bridgesp2.bridgesletppppfres=Fmt.pfppf"policy: %d vms %a cpus %d MB memory %a MB block bridges: %a"res.vmspp_isres.cpuidsres.memoryFmt.(option~none:(unit"no")int)res.block(String.Set.pp~sep:Fmt.(unit", ")Fmt.string)res.bridgesendmoduleUnikernel=structtypetyp=[`Solo5]letpp_typppf=function|`Solo5->Fmt.pfppf"solo5"typefail_behaviour=[`Quit|`RestartofIS.toption]letpp_fail_behaviourppf=function|`Quit->Fmt.stringppf"quit"|`Restartcodes->Fmt.pfppf"restart %a"Fmt.(option~none:(unit"all except 1")(list~sep:(unit", ")int))(matchcodeswithNone->None|Somex->Some(IS.elementsx))typeconfig={typ:typ;compressed:bool;image:Cstruct.t;fail_behaviour:fail_behaviour;cpuid:int;memory:int;block_devices:(string*stringoption)list;bridges:(string*stringoption)list;argv:stringlistoption;}letbridges(vm:config)=List.map(fun(net,bri)->matchbriwithNone->net|Somes->s)vm.bridgesletpp_opt_listppfxs=Fmt.(list~sep:(unit", ")(pair~sep:(unit" -> ")stringstring))ppf(List.map(fun(a,b)->a,(matchbwithNone->a|Someb->b))xs)letpp_configppf(vm:config)=Fmt.pfppf"typ %a@ compression %B image %d bytes@ fail behaviour %a@ cpu %d@ %d MB memory@ block devices %a@ bridge %a@ argv %a"pp_typvm.typvm.compressed(Cstruct.lenvm.image)pp_fail_behaviourvm.fail_behaviourvm.cpuidvm.memorypp_opt_listvm.block_devicespp_opt_listvm.bridgesFmt.(option~none:(unit"no")(list~sep:(unit" ")string))vm.argvletrestart_handlerconfig=matchconfig.fail_behaviourwith`Quit->false|`Restart_->truetypet={config:config;cmd:Bos.Cmd.t;pid:int;taps:stringlist;digest:Cstruct.t;}letppppfvm=let`Hexhex_digest=Hex.of_cstructvm.digestinFmt.pfppf"pid %d@ taps %a (block %a) cmdline %a digest %s"vm.pidFmt.(list~sep:(unit", ")string)vm.tapspp_opt_listvm.config.block_devicesBos.Cmd.ppvm.cmdhex_digesttypeinfo={typ:typ;fail_behaviour:fail_behaviour;cpuid:int;memory:int;block_devices:(string*stringoption)list;bridges:(string*stringoption)list;argv:stringlistoption;digest:Cstruct.t;}letinfot=letcfg=t.configin{typ=cfg.typ;fail_behaviour=cfg.fail_behaviour;cpuid=cfg.cpuid;memory=cfg.memory;block_devices=cfg.block_devices;bridges=cfg.bridges;argv=cfg.argv;digest=t.digest}letpp_infoppf(info:info)=let`Hexhex_digest=Hex.of_cstructinfo.digestinFmt.pfppf"typ %a@ fail behaviour %a@ cpu %d@ %d MB memory@ block devices %a@ bridge %a@ argv %a@ digest %s"pp_typinfo.typpp_fail_behaviourinfo.fail_behaviourinfo.cpuidinfo.memorypp_opt_listinfo.block_devicespp_opt_listinfo.bridgesFmt.(option~none:(unit"no")(list~sep:(unit" ")string))info.argvhex_digestendmoduleStats=structtyperusage={utime:(int64*int);stime:(int64*int);maxrss:int64;ixrss:int64;idrss:int64;isrss:int64;minflt:int64;majflt:int64;nswap:int64;inblock:int64;outblock:int64;msgsnd:int64;msgrcv:int64;nsignals:int64;nvcsw:int64;nivcsw:int64;}letpp_rusageppfr=Fmt.pfppf"utime %Lu.%06d stime %Lu.%06d maxrss %Lu ixrss %Lu idrss %Lu isrss %Lu minflt %Lu majflt %Lu nswap %Lu inblock %Lu outblock %Lu msgsnd %Lu msgrcv %Lu signals %Lu nvcsw %Lu nivcsw %Lu"(fstr.utime)(sndr.utime)(fstr.stime)(sndr.stime)r.maxrssr.ixrssr.idrssr.isrssr.minfltr.majfltr.nswapr.inblockr.outblockr.msgsndr.msgrcvr.nsignalsr.nvcswr.nivcswletpp_rusage_memppfr=Fmt.pfppf"maxrss %Lu ixrss %Lu idrss %Lu isrss %Lu minflt %Lu majflt %Lu"r.maxrssr.ixrssr.idrssr.isrssr.minfltr.majflttypekinfo_mem={vsize:int64;rss:int64;tsize:int64;dsize:int64;ssize:int64;runtime:int64;cow:int;start:(int64*int);}letpp_kinfo_memppft=Fmt.pfppf"virtual-size %Lu rss %Lu text-size %Lu data-size %Lu stack-size %Lu runtime %Lu cow %u start %Lu.%06d"t.vsizet.rsst.tsizet.dsizet.ssizet.runtimet.cow(fstt.start)(sndt.start)typevmm=(string*int64)listletpp_vmmppfvmm=Fmt.(list~sep:(unit"@.")(pair~sep:(unit": ")stringint64))ppfvmmletpp_vmm_memppfvmm=Fmt.(list~sep:(unit"@.")(pair~sep:(unit": ")stringint64))ppf(List.filter(fun(k,_)->k="Resident memory"||k="Wired memory")vmm)typeifdata={bridge:string;flags:int32;send_length:int32;max_send_length:int32;send_drops:int32;mtu:int32;baudrate:int64;input_packets:int64;input_errors:int64;output_packets:int64;output_errors:int64;collisions:int64;input_bytes:int64;output_bytes:int64;input_mcast:int64;output_mcast:int64;input_dropped:int64;output_dropped:int64;}letpp_ifdatappfi=Fmt.pfppf"bridge %s flags %lX send_length %lu max_send_length %lu send_drops %lu mtu %lu baudrate %Lu input_packets %Lu input_errors %Lu output_packets %Lu output_errors %Lu collisions %Lu input_bytes %Lu output_bytes %Lu input_mcast %Lu output_mcast %Lu input_dropped %Lu output_dropped %Lu"i.bridgei.flagsi.send_lengthi.max_send_lengthi.send_dropsi.mtui.baudratei.input_packetsi.input_errorsi.output_packetsi.output_errorsi.collisionsi.input_bytesi.output_bytesi.input_mcasti.output_mcasti.input_droppedi.output_droppedtypet=rusage*kinfo_memoption*vmmoption*ifdatalistletppppf(ru,mem,vmm,ifs)=Fmt.pfppf"%a@.%a@.%a@.%a"pp_rusageruFmt.(option~none:(unit"no kinfo_mem stats")pp_kinfo_mem)memFmt.(option~none:(unit"no vmm stats")pp_vmm)vmmFmt.(list~sep:(unit"@.@.")pp_ifdata)ifsendtypeprocess_exit=[`Exitofint|`Signalofint|`Stopofint]letpp_process_exitppf=function|`Exitn->Fmt.pfppf"exit %d"n|`Signaln->Fmt.pfppf"signal %a (numeric %d)"Fmt.Dump.signalnn|`Stopn->Fmt.pfppf"stop %a (numeric %d)"Fmt.Dump.signalnnletshould_restart(config:Unikernel.config)name=function|(`Signal_|`Stop_)asr->(* signal 11 is if a kill -TERM was sent (i.e. our destroy) *)Logs.warn(funm->m"unikernel %a exited with signal %a"Name.ppnamepp_process_exitr);false|`Exiti->(* results (and default behaviour) -- solo5-exit allows an arbitrary int
from sysexits(3), bash tutorial (appendix E), OCaml runtime, solo5:
0 normal exit (i.e. teardown) -> restart
1 solo5 internal error (bad image, bad manifest) -> no restart, never
2 ocaml exceptions (out of memory et al) -> restart
60 61 62 (unused, not reserved) -> no restart, never
63 functoria-runtime help/version -> no restart, never
64 argument parse error - no restart, never
65 (sysexits, unused) data error
66 (sysexits, unused) noinput
67 (sysexits, unused) nouser
68 (sysexits, unused) nohost
69 (sysexits, unused) unavailable
70 (sysexits, unused) software
71 (sysexits, unused) oserr
72 (sysexits, unused) osfile
73 (sysexits, unused) cantcreat
74 (sysexits, unused) ioerr
75 (sysexits, unused) tempfail
76 (sysexits, unused) protocol
77 (sysexits, unused) noperm
78 (sysexits, unused) config
126 (bash, unused) command invoked cannot execute
127 (bash, unused) command not found
128+n (bash, unused) fatal error signal n
255 solo5-abort -> OCaml 4.10: fatal error (instead of 2) -> restart
opam exit codes:
1 False. Returned when a boolean return value is expected, e.g. when running with --check, or for queries like opam lint.
2 Bad command-line arguments, or command-line arguments pointing to an invalid context (e.g. file not following the expected format).
5 Not found. You requested something (package, version, repository, etc.) that couldn't be found.
10 Aborted. The operation required confirmation, which wasn't given.
15 Could not acquire the locks required for the operation.
20 There is no solution to the user request. This can be caused by asking to install two incompatible packages, for example.
30 Error in package definition, or other metadata files. Using --strict raises this error more often.
31 Package script error. Some package operations were unsuccessful. This may be an error in the packages or an incompatibility with your system. This can be a partial error.
40 Sync error. Could not fetch some remotes from the network. This can be a partial error.
50 Configuration error. Opam or system configuration doesn't allow operation, and needs fixing.
60 Solver failure. The solver failed to return a sound answer. It can be due to a broken external solver, or an error in solver configuration.
99 Internal error. Something went wrong, likely due to a bug in opam itself.
130 User interrupt. SIGINT was received, generally due to the user pressing Ctrl-C.
*)letopt_memi=matchconfig.Unikernel.fail_behaviourwith|`Quit->assertfalse|`RestartNone->true|`Restart(Somec)->IS.memicinmatchiwith|1->Logs.warn(funm->m"unikernel %a solo5 exit failure (1)"Name.ppname);false|60|61|62|63|64->Logs.warn(funm->m"unikernel %a exited %d, not restarting"Name.ppnamei);false|_whenopt_memi->Logs.info(funm->m"unikernel %a exited %d, restarting"Name.ppnamei);true|_->Logs.info(funm->m"unikernel %a exited %d, not restarting %a"Name.ppnameiUnikernel.pp_fail_behaviourconfig.fail_behaviour);false