|
| 1 | +# @summary Create/start the cluster of Lima VMs |
| 2 | +# @param name |
| 3 | +# Cluster name |
| 4 | +# @param clusters |
| 5 | +# Hash of all defined clusters. Populated from Hiera usually. |
| 6 | +# @param target |
| 7 | +# The host to run the limactl on |
| 8 | +plan lima::cluster::start ( |
| 9 | + String[1] $name, |
| 10 | + Optional[Hash] $clusters = undef, |
| 11 | + TargetSpec $target = 'localhost', |
| 12 | +) { |
| 13 | + $cluster = run_plan('lima::clusters', 'clusters' => $clusters, 'name' => $name) |
| 14 | + $tgt = get_target($target) |
| 15 | + |
| 16 | + $cluster_config = $cluster['nodes'].map |$node| { |
| 17 | + $n = $node ? { |
| 18 | + Hash => $node, |
| 19 | + String => { 'name' => $node }, |
| 20 | + default => {}, |
| 21 | + } |
| 22 | + |
| 23 | + # Use per-node configs first. Use cluster-wide configs otherwise. |
| 24 | + # Look for explicit config hash first then template then url. |
| 25 | + $cfg = [ |
| 26 | + [$n['config'], 'config'], |
| 27 | + [$n['template'], 'template'], |
| 28 | + [$n['url'], 'url'], |
| 29 | + [$cluster['config'], 'config'], |
| 30 | + [$cluster['template'], 'template'], |
| 31 | + [$cluster['url'], 'url'], |
| 32 | + ].filter |$x| { $x[0] } # Delete undefined options |
| 33 | + |
| 34 | + unless $cfg.count >= 1 { |
| 35 | + fail("Node ${n['name']} has no config/template/url defined in the cluster configuration") |
| 36 | + } |
| 37 | + |
| 38 | + # Use first defined option ($cfg[0]) |
| 39 | + ({ 'name' => $n['name'], $cfg[0][1] => $cfg[0][0] }) |
| 40 | + } |
| 41 | + |
| 42 | + $defined_nodes = $cluster_config.map |$node| { $node['name'] } |
| 43 | + out::verbose("Defined nodes: ${defined_nodes}") |
| 44 | + |
| 45 | + # Collect and set the target's facts |
| 46 | + if empty(facts($tgt)) { |
| 47 | + without_default_logging() || { |
| 48 | + run_plan('facts', $tgt, '_catch_errors' => true) |
| 49 | + } |
| 50 | + } |
| 51 | + $cpus = facts($tgt).get('processors.count') |
| 52 | + $start_threads = if $cpus < 4 { 1 } else { $cpus / 2 } # Assume every VM can consume up to 200% of a CPU core on start |
| 53 | + |
| 54 | + # Get existing VMs |
| 55 | + $list_res = without_default_logging() || { |
| 56 | + run_task( |
| 57 | + 'lima::list', |
| 58 | + $tgt, |
| 59 | + { names => $defined_nodes }, |
| 60 | + ) |
| 61 | + } |
| 62 | + $lima_config = $list_res.find($target).value['list'] |
| 63 | + |
| 64 | + # Create missing nodes |
| 65 | + $missing_nodes = $defined_nodes - $lima_config.map |$x| { $x['name'] } |
| 66 | + out::verbose("Nodes to create: ${missing_nodes}") |
| 67 | + |
| 68 | + # `limactl start` cannot create multiple images in parallel |
| 69 | + # See https://github.com/lima-vm/lima/issues/1354 |
| 70 | + # So creating VMs sequentially.. |
| 71 | + $create_res = $missing_nodes.map |$node| { |
| 72 | + run_task( |
| 73 | + 'lima::start', |
| 74 | + $tgt, |
| 75 | + "Create VM ${node}", |
| 76 | + 'name' => $node, |
| 77 | + 'template' => $cluster['template'], |
| 78 | + 'config' => $cluster['config'], |
| 79 | + 'url' => $cluster['url'], |
| 80 | + ) |
| 81 | + } |
| 82 | + |
| 83 | + # Start existing but non-running nodes |
| 84 | + $stopped_nodes = $lima_config |
| 85 | + .filter |$x| { $x['status'] == 'Stopped' } |
| 86 | + .map |$x| { $x['name'] } |
| 87 | + out::verbose("Nodes to start (${start_threads} nodes per batch): ${stopped_nodes}") |
| 88 | + |
| 89 | + # Run in batches of $start_threads VMs in parallel |
| 90 | + $start_res = $stopped_nodes.slice($start_threads).map |$batch| { |
| 91 | + $batch.parallelize |$node| { |
| 92 | + run_task( |
| 93 | + 'lima::start', |
| 94 | + $tgt, |
| 95 | + "Start VM ${node}", |
| 96 | + 'name' => $node, |
| 97 | + ) |
| 98 | + } |
| 99 | + } |
| 100 | + |
| 101 | + return flatten($create_res + $start_res) |
| 102 | +} |
0 commit comments