1
0
mirror of https://github.com/gryf/boxpy.git synced 2026-02-02 14:15:49 +01:00

16 Commits
1.6 ... 1.9.3

Author SHA1 Message Date
71bf5b6d99 Bump Fedora version, remove archived versions prior to 37 2023-12-05 11:54:05 +01:00
e73d5ce458 Update kuryr multinode setup example 2023-07-23 12:58:12 +02:00
d623114f69 Update example for wmaker 2023-07-23 12:54:09 +02:00
51f642bea0 Updated ubuntu devstack example 2023-07-23 12:39:18 +02:00
12df0e97df Updated fedora devstack example 2023-07-23 11:53:59 +02:00
5f0def3103 Bump distribution latest version.
Also, updated mapping for the Fedora images.
2023-07-05 15:58:56 +02:00
43eabb9947 Fix nasty bug for debian images 2023-07-04 18:48:18 +02:00
55416db13d Added --type switch for start command 2023-04-20 19:42:21 +02:00
86a5655025 Improve detecting VM Operating System. 2023-04-20 19:21:24 +02:00
259d11e409 Don't reset Debian Bookworm on first run.
Issue/glitch with kernel panic on first run seems to be fixed on Debian
Bookworm (12). Do not reset VM for that version (and hopefully
upcoming).
2023-04-20 17:01:57 +02:00
b2457d497e Add experimental Debian support.
Note, there is something weird with those images, as the will segfault
on the first run (I've checked that with latest Debian 11 images, maybe
it will change in the future), so there is forced reboot after certain
amount of time as a workaround.
2023-04-18 21:48:19 +02:00
15a6ecb540 Use predefined os types for vbox VMs.
It might have impact on how operating system inside VM is treated by
VirtualBox, so let's stick with proper distro for every OS. As an
outcome, it turns out, that for graphical side of the vm, for Linux OS
the vmsvga driver is recommended, as a little more amount of vram.
2023-04-18 21:39:56 +02:00
10543cb506 Don't create vm till it's still there during rebuild 2023-04-02 10:05:06 +02:00
1f1084f294 Readme update. 2023-02-26 19:20:11 +01:00
f5ed3d37ac readme update 2023-02-22 21:10:59 +01:00
1483f49461 Added debug info about ssh connection to the vm 2023-02-22 21:08:43 +01:00
7 changed files with 219 additions and 82 deletions

View File

@@ -2,8 +2,8 @@
box.py
======
Box.py is a simple automation tool meant to run Ubuntu, Fedora or Centos Stream
cloud images on top of VirtualBox.
Box.py is a simple automation tool meant to run Ubuntu, Fedora, Centos Stream
or Debian cloud images on top of VirtualBox.
What it does is simply download official cloud image, set up VM, tweak it up
and do the initial pre-configuration using generated config drive.
@@ -16,7 +16,7 @@ weird named options for ``vboxmanage`` ;P)
Requirements
------------
- Python >=3.7
- Python >=3.8
- `pyyaml`_
- `requests`_
@@ -24,7 +24,7 @@ Requirements
- Virtualbox (obviously)
- ``mkisofs`` or ``genisoimage`` command for generating ISO image
- ``wget`` command for fetching images
- ``sha256sum`` command for checksum check
- ``sha256sum`` and ``sha512sum`` commands for checksum check
- ``qemu-img`` from *qemu-utils* package command for converting between images
formats
@@ -39,7 +39,7 @@ your operating system, or by using virtualenv for Python requirements, i.e.:
$ python -m virtualenv .venv
$ . .venv/bin/activate
(.venv) $ pip install requirements.txt
(.venv) $ pip install -r requirements.txt
then you can issue:
@@ -55,25 +55,25 @@ or simply link it somewhere in the path:
$ chmod +x ~/bin/boxpy
and now you can issue some command. For example, to spin up a VM with Ubuntu
18.04 with one CPU, 1GB of memory and 6GB of disk:
20.04 with one CPU, 1GB of memory and 6GB of disk:
.. code:: shell-session
$ boxpy create --version 18.04 myvm
$ boxpy create --version 20.04 myvm
note, that Ubuntu is default distribution you don't need to specify
``--distro`` nor ``--version`` it will pick up latest LTS version. Now, let's
recreate it with 20.04:
recreate it with 22.04:
.. code:: shell-session
$ boxpy rebuild --version 20.04 myvm
$ boxpy rebuild --version 22.04 myvm
or recreate it with Fedora and add additional CPU:
.. code:: shell-session
$ boxpy rebuild --distro fedora --version 34 --cpu 2 myvm
$ boxpy rebuild --distro fedora --version 39 --cpu 2 myvm
now, let's connect to the VM using either ssh command, which is printed out at
as last ``boxpy`` output line, or simply by using ssh boxpy command:
@@ -91,13 +91,15 @@ use it ad-hoc, or place on your ``.bashrc`` or whatever:
Currently, following commands are available:
- ``list`` - for quickly listing all/running VMs
- ``info`` - to get summary about VM
- ``destroy`` - that is probably obvious one
- ``completion`` - as described above
- ``create`` - create new VM
- ``destroy`` - that is probably obvious one
- ``info`` - to get summary about VM
- ``list`` - for quickly listing all/running VMs
- ``rebuild`` - recreate specified VM
- ``ssh`` - connect to the VM using ssh
- ``completion`` - as described above
- ``start`` - stop the running VM
- ``stop`` - start stopped VM
All of the commands have a range of options, and can be examined by using
``--help`` option.

176
box.py
View File

@@ -18,14 +18,15 @@ import requests
import yaml
__version__ = "1.3"
__version__ = "1.9.2"
CACHE_DIR = os.environ.get('XDG_CACHE_HOME', os.path.expanduser('~/.cache'))
CLOUD_IMAGE = "ci.iso"
FEDORA_RELEASE_MAP = {'32': '1.6', '33': '1.2', '34': '1.2'}
FEDORA_RELEASE_MAP = {'37': '1.7', '38': '1.6', '39': '1.5'}
DEBIAN_CODENAME_MAP = {'12': 'bookworm', '11': 'bullseye', '10': 'buster'}
TYPE_MAP = {'HardDisk': 'disk', 'DVD': 'dvd', 'Floppy': 'floppy'}
DISTRO_MAP = {'ubuntu': 'Ubuntu', 'fedora': 'Fedora',
'centos': 'Centos Stream'}
'centos': 'Centos Stream', 'debian': 'Debian'}
META_DATA_TPL = string.Template('''\
instance-id: $instance_id
local-hostname: $vmhostname
@@ -136,13 +137,37 @@ _boxpy() {
if [[ ${prev} == ${cmd} ]]; then
COMPREPLY=( $(compgen -W "bash" -- ${cur}) )
fi
;;
start)
items=(--type)
if [[ ${prev} == ${cmd} ]]; then
if [[ ${cmd} = "start" ]]; then
_vms_comp vms
else
COMPREPLY=( $(compgen -W "${items[*]}" -- ${cur}) )
fi
else
_get_excluded_items "${items[@]}"
COMPREPLY=( $(compgen -W "$result" -- ${cur}) )
case "${prev}" in
--type)
COMPREPLY=( $(compgen -W "gui headless sdl separate" \
-- ${cur}) )
;;
--*)
COMPREPLY=( )
;;
esac
fi
;;
create|rebuild)
items=(--cpus --disable-nested --disk-size --default-user --distro
--forwarding --image --key --memory --hostname --port --config
--version --type)
if [[ ${prev} == ${cmd} ]]; then
if [[ ${cmd} = "rebuild" ]]; then
if [[ ${cmd} = "rebuild" || ${cmd} == "start" ]]; then
_vms_comp vms
else
COMPREPLY=( $(compgen -W "${items[*]}" -- ${cur}) )
@@ -160,8 +185,8 @@ _boxpy() {
_ssh_identityfile
;;
--distro)
COMPREPLY=( $(compgen -W "ubuntu fedora centos" \
-- ${cur}) )
COMPREPLY=( $(compgen -W "ubuntu fedora centos
debian" -- ${cur}) )
;;
--type)
COMPREPLY=( $(compgen -W "gui headless sdl separate" \
@@ -194,11 +219,6 @@ _boxpy() {
_vms_comp runningvms
fi
;;
start)
if [[ ${prev} == ${cmd} ]]; then
_vms_comp vms
fi
;;
stop)
if [[ ${prev} == ${cmd} ]]; then
_vms_comp runningvms
@@ -585,6 +605,50 @@ class Config:
return source
class OsTypes:
def __init__(self, conf):
self._conf = conf
self._ostypes = []
self._gather_os_types()
def _gather_os_types(self):
out = Run(['vboxmanage', 'list', 'ostypes']).stdout
for line in out.split('\n'):
if not line.startswith('ID:'):
continue
self._ostypes.append(line.split(':')[1].strip())
def ubuntu(self):
lts = ''
major, minor = [int(x) for x in self._conf.version.split('.')]
if major % 2 == 0 and minor == 4:
lts = '_LTS'
name = "Ubuntu%s%s_64" % (major, lts)
if name not in self._ostypes:
return 'Ubuntu_64'
return name
def fedora(self):
return "Fedora_64"
def debian(self):
name = "Debian%s_64" % self._conf.version
if name not in self._ostypes:
return 'Debian_64'
return name
def get(self):
if not hasattr(self, self._conf.distro):
return "Linux_64"
return getattr(self, self._conf.distro)()
class VBoxManage:
"""
Class for dealing with vboxmanage commands
@@ -765,7 +829,11 @@ class VBoxManage:
'--acpi', 'on',
'--audio', 'none',
'--nic1', 'nat',
'--natpf1', f'boxpyssh,tcp,,{port},,22']
'--natpf1', f'boxpyssh,tcp,,{port},,22',
'--graphicscontroller', 'vmsvga',
'--vram', '16',
'--ostype', OsTypes(conf).get()]
for count, (hostport, vmport) in enumerate(conf.forwarding.items(),
start=1):
cmd.extend(['--natpf1', f'custom-pf-{count},tcp,,{hostport},'
@@ -914,6 +982,7 @@ class VBoxManage:
class Image:
URL = ""
IMG = ""
CHECKSUMTOOL = 'sha256sum'
def __init__(self, vbox, version, arch, release, fname=None):
self.vbox = vbox
@@ -964,7 +1033,7 @@ class Image:
return False
if os.path.exists(os.path.join(CACHE_DIR, self._img_fname)):
cmd = ['sha256sum', os.path.join(CACHE_DIR, self._img_fname)]
cmd = [self.CHECKSUMTOOL, os.path.join(CACHE_DIR, self._img_fname)]
calulated_sum = Run(cmd).stdout.split(' ')[0]
LOG.details('Checksum for image: %s, expected: %s', calulated_sum,
expected_sum)
@@ -1017,6 +1086,30 @@ class Ubuntu(Image):
return expected_sum
class Debian(Image):
URL = "https://cloud.debian.org/images/cloud/%s/daily/latest/%s"
IMG = "debian-%s-generic-%s-daily.qcow2"
CHECKSUMTOOL = 'sha512sum'
def __init__(self, vbox, version, arch, release, fname=None):
super().__init__(vbox, version, arch, release)
self._img_fname = self.IMG % (version, arch)
self._img_url = self.URL % (release, self._img_fname)
self._checksum_file = 'SHA512SUMS'
self._checksum_url = self.URL % (release, self._checksum_file)
def _get_checksum(self, fname):
expected_sum = None
Run(['wget', self._checksum_url, '-q', '-O', fname])
with open(fname) as fobj:
for line in fobj.readlines():
if self._img_fname in line:
expected_sum = line.split(' ')[0]
break
return expected_sum
class Fedora(Image):
URL = ("https://download.fedoraproject.org/pub/fedora/linux/releases/%s/"
"Cloud/%s/images/%s")
@@ -1110,18 +1203,25 @@ DISTROS = {'ubuntu': {'username': 'ubuntu',
'realname': 'fedora',
'img_class': Fedora,
'amd64': 'x86_64',
'default_version': '34'},
'default_version': '39'},
'centos': {'username': 'centos',
'realname': 'centos',
'img_class': CentosStream,
'amd64': 'x86_64',
'default_version': '8'}}
'default_version': '9'},
'debian': {'username': 'debian',
'realname': 'debian',
'img_class': Debian,
'amd64': 'amd64',
'default_version': '12'}}
def get_image_object(vbox, version, image='ubuntu', arch='amd64'):
release = None
if image == 'fedora':
release = FEDORA_RELEASE_MAP[version]
if image == 'debian':
release = DEBIAN_CODENAME_MAP[version]
return DISTROS[image]['img_class'](vbox, version, DISTROS[image]['amd64'],
release, DISTROS[image].get('image'))
@@ -1247,6 +1347,7 @@ def vmcreate(args, conf=None):
f'ssh://{username}@localhost:{vbox.vm_info["port"]}',
'sudo cloud-init status']
try:
counter = 0
while True:
out = Run(cmd)
LOG.debug('Out: %s', out.stdout)
@@ -1266,6 +1367,22 @@ def vmcreate(args, conf=None):
f'VM with ssh for user {username}. '
f'Check output in debug mode.')
time.sleep(3)
counter += 1
# TODO: there is something odd with debian cloud images prior
# to 12 (bookworm), as on first run system crashes. In that
# case after ~20 seconds there should already be panic, reset
# machine as a workaround. Remove this after debian 12
# stabilization later this year.
if (counter == 8 and conf.distro == 'debian'
and conf.version != '12'):
LOG.debug('Resetting `%s`, due to the issue with kernel '
'panic on Debian %s the first run', conf.name,
conf.version)
counter += 1
vbox.poweroff()
time.sleep(3)
vbox.poweron(args.type)
continue
LOG.info(' done')
@@ -1445,6 +1562,13 @@ def vmrebuild(args):
conf.disk_size = vbox.get_media_size(disk_path)
vmdestroy(args)
# Wait till VM is gone
while True:
vbox = VBoxManage(args.name)
if not vbox.get_vm_info():
break
vmcreate(args, conf)
return 0
@@ -1470,14 +1594,17 @@ def connect(args):
return 16
username = conf.username or DISTROS[conf.distro]["username"]
return Run(['ssh', '-o', 'StrictHostKeyChecking=no',
'-o', 'UserKnownHostsFile=/dev/null',
'-i', conf.ssh_key_path[:-4],
f'ssh://{username}'
f'@localhost:{conf.port}'], False).returncode
cmd = ['ssh', '-o', 'StrictHostKeyChecking=no',
'-o', 'UserKnownHostsFile=/dev/null',
'-i', conf.ssh_key_path[:-4],
f'ssh://{username}'
f'@localhost:{conf.port}']
LOG.debug('Connecting to vm `%s` using command:\n%s', args.name,
' '.join(cmd))
return Run(cmd, False).returncode
def _set_vmstate(name, state):
def _set_vmstate(name, state, guitype=None):
vbox = VBoxManage(name)
if not vbox.get_vm_info():
@@ -1493,13 +1620,13 @@ def _set_vmstate(name, state):
return
if state == "start":
vbox.poweron()
vbox.poweron(guitype)
else:
vbox.acpipowerbutton()
def vmstart(args):
_set_vmstate(args.name, 'start')
_set_vmstate(args.name, 'start', args.type)
def vmstop(args):
@@ -1614,6 +1741,9 @@ def main():
start = subparsers.add_parser('start', help='start VM')
start.add_argument('name', help='name or UUID of the VM')
start.add_argument('-t', '--type', default='headless',
help="VM run type, headless by default.",
choices=['gui', 'headless', 'sdl', 'separate'])
start.set_defaults(func=vmstart)
stop = subparsers.add_parser('stop', help='stop VM')

View File

@@ -1,9 +1,7 @@
# Note, that cloud init will fail, due to old cloudinit package, which module
# cc_keys_to_console doesn't recognize skipping option. Just ignore this error.
package_update: true
packages:
- bash-completion
- ctags-etags
- ctags
- git
- git-review
- htop
@@ -25,13 +23,13 @@ write_files:
disable_service n-vnc
disable_service dstat
runcmd:
- [su, -, fedora, -c, "git clone https://opendev.org/openstack/devstack ~/devstack"]
- [su, -, fedora, -c, "cp /tmp/local.conf /home/fedora/devstack/"]
- [su, -, fedora, -c, "echo 'export HOST_IP=10.0.2.15' >> .bashrc"]
- su - fedora -c "git clone https://opendev.org/openstack/devstack ~/devstack"
- su - fedora -c "cp /tmp/local.conf /home/fedora/devstack/"
- su - fedora -c "echo 'export HOST_IP=10.0.2.15' >> .bashrc"
boxpy_data:
key: vm
cpus: 2
memory: 4GB
disk_size: 10GB
distro: fedora
version: 34
version: 36

View File

@@ -7,7 +7,7 @@ packages:
- ipython3
- jq
- mc
- python-apsw
- python3-apsw
- python3-flake8
- python3-jedi
- python3-pip
@@ -26,17 +26,15 @@ write_files:
RABBIT_PASSWORD=$$ADMIN_PASSWORD
SERVICE_PASSWORD=$$ADMIN_PASSWORD
runcmd:
- [apt, purge, '-y', python3-pyasn1-modules]
- [apt, purge, '-y', python3-simplejson]
- [su, -, ubuntu, -c, "git clone https://github.com/gryf/vmstrap"]
- [su, -, ubuntu, -c, "vmstrap/bootstrap.sh -c"]
- [rm, -fr, /home/ubuntu/vmstrap]
- [su, -, ubuntu, -c, "cp /tmp/local.conf /home/ubuntu/devstack/"]
- [su, -, ubuntu, -c, "echo 'export HOST_IP=10.0.2.15' >> .bashrc"]
- apt purge -y python3-pyasn1-modules
- apt purge -y python3-simplejson
- su - ubuntu -c "git clone https://opendev.org/openstack/devstack ~/devstack"
- su - ubuntu -c "cp /tmp/local.conf /home/ubuntu/devstack/"
- su - ubuntu -c "echo 'export HOST_IP=10.0.2.15' >> .bashrc"
boxpy_data:
key: vm
cpus: 2
memory: 6GB
disk_size: 10GB
distro: ubuntu
version: 20.04
version: 22.04

View File

@@ -7,7 +7,7 @@ packages:
- ipython3
- jq
- mc
- python-apsw
- python3-apsw
- python3-flake8
- python3-jedi
- python3-pip
@@ -122,6 +122,7 @@ write_files:
# Vars
ADMIN_PASSWORD="secretadmin"
CONTAINER_ENGINE="crio"
DATABASE_PASSWORD="secretdatabase"
ETCD_USE_RAMDISK="True"
@@ -131,9 +132,10 @@ write_files:
KURYR_K8S_MULTI_WORKER_TESTS="True"
KURYR_K8S_OCTAVIA_MEMBER_MODE="L2"
KURYR_LB_ALGORITHM="SOURCE_IP_PORT"
KURYR_NEUTRON_DEFAULT_ROUTER="router1"
KURYR_NEUTRON_DEFAULT_ROUTER="kuryr-router"
KURYR_SG_DRIVER="policy"
KURYR_SUBNET_DRIVER="namespace"
KURYR_SUPPORT_POD_SECURITY="True"
LOGFILE="/opt/stack/logs/devstacklog.txt"
LOG_COLOR="False"
@@ -142,10 +144,11 @@ write_files:
OCTAVIA_AMP_IMAGE_NAME="test-only-amphora-x64-haproxy-ubuntu-bionic"
OCTAVIA_AMP_IMAGE_SIZE="3"
OVN_BRANCH="v20.06.2"
OVN_BRANCH="v21.06.0"
OVN_BUILD_FROM_SOURCE="True"
OVN_DBS_LOG_LEVEL="dbg"
OVN_L3_CREATE_PUBLIC_NETWORK="True"
OVS_BRANCH="a4b04276ab5934d087669ff2d191a23931335c87"
VAR_RUN_PATH="/usr/local/var/run"
@@ -167,23 +170,25 @@ write_files:
enable_plugin octavia-tempest-plugin https://opendev.org/openstack/octavia-tempest-plugin
enable_plugin ovn-octavia-provider https://opendev.org/openstack/ovn-octavia-provider
[[post-config|$OCTAVIA_CONF]]
[[post-config|$$OCTAVIA_CONF]]
[api_settings]
enabled_provider_drivers = amphora:'Octavia Amphora driver',ovn:'Octavia OVN driver'
runcmd:
- [apt, purge, '-y', python3-pyasn1-modules]
- [apt, purge, '-y', python3-simplejson]
- [su, -, ubuntu, -c, "git clone https://github.com/gryf/vmstrap"]
- [su, -, ubuntu, -c, "vmstrap/bootstrap.sh -c"]
- [rm, -fr, /home/ubuntu/vmstrap]
- [su, -, ubuntu, -c, "echo 'export HOST_IP=192.168.10.10' >> .bashrc"]
- [su, -, ubuntu, -c, "cp /tmp/local.conf /home/ubuntu/devstack/"]
- [systemctl, restart, systemd-networkd]
- systemctl stop systemd-resolved.service
- systemctl disable systemd-resolved.service
- echo "nameserver 1.1.1.1" > /etc/resolv.conf
- apt purge -y snapd
- apt purge -y python3-pyasn1-modules
- apt purge -y python3-simplejson
- su - ubuntu -c "git clone https://opendev.org/openstack/devstack"
- su - ubuntu -c "cp /tmp/local.conf /home/ubuntu/devstack/"
- su - ubuntu -c "echo 'export HOST_IP=192.168.10.10' >> .bashrc"
- systemctl restart systemd-networkd
boxpy_data:
key: vm
cpus: 4
memory: 16GB
disk_size: 50GB
version: 20.04
advanced:
nic2: intnet
version: 20.04

View File

@@ -7,7 +7,7 @@ packages:
- ipython3
- jq
- mc
- python-apsw
- python3-apsw
- python3-flake8
- python3-jedi
- python3-pip
@@ -79,6 +79,7 @@ write_files:
# Vars
ADMIN_PASSWORD="secretadmin"
CONTAINER_ENGINE="crio"
DATABASE_HOST="192.168.10.10"
DATABASE_PASSWORD="secretdatabase"
ENABLE_CHASSIS_AS_GW="False"
@@ -89,7 +90,7 @@ write_files:
KURYR_EP_DRIVER_OCTAVIA_PROVIDER="ovn"
KURYR_K8S_OCTAVIA_MEMBER_MODE="L2"
KURYR_LB_ALGORITHM="SOURCE_IP_PORT"
KURYR_NEUTRON_DEFAULT_ROUTER="router1"
KURYR_NEUTRON_DEFAULT_ROUTER="kuryr-router"
VAR_RUN_PATH="/usr/local/var/run"
KURYR_ENABLED_HANDLERS="vif,endpoints,service,namespace,pod_label,policy,kuryrnetworkpolicy,kuryrnetwork,kuryrport,kuryrloadbalancer"
@@ -97,10 +98,11 @@ write_files:
KURYR_SUBNET_DRIVER="namespace"
OVN_BRANCH="v20.06.2"
OVN_BRANCH="v21.06.0"
OVN_BUILD_FROM_SOURCE="True"
OVN_DBS_LOG_LEVEL="dbg"
OVN_L3_CREATE_PUBLIC_NETWORK="True"
OVS_BRANCH="a4b04276ab5934d087669ff2d191a23931335c87"
LIBVIRT_TYPE="qemu"
@@ -120,19 +122,21 @@ write_files:
enable_plugin devstack-plugin-container https://opendev.org/openstack/devstack-plugin-container
enable_plugin kuryr-kubernetes https://opendev.org/openstack/kuryr
runcmd:
- [apt, purge, '-y', python3-pyasn1-modules]
- [apt, purge, '-y', python3-simplejson]
- [su, -, ubuntu, -c, "git clone https://github.com/gryf/vmstrap"]
- [su, -, ubuntu, -c, "vmstrap/bootstrap.sh -c"]
- [rm, -fr, /home/ubuntu/vmstrap]
- [su, -, ubuntu, -c, "echo 'export HOST_IP=192.168.10.11' >> .bashrc"]
- [su, -, ubuntu, -c, "cp /tmp/local.conf /home/ubuntu/devstack/"]
- [systemctl, restart, systemd-networkd]
- systemctl stop systemd-resolved.service
- systemctl disable systemd-resolved.service
- echo "nameserver 1.1.1.1" > /etc/resolv.conf
- apt purge -y snapd
- apt purge -y python3-pyasn1-modules
- apt purge -y python3-simplejson
- su - ubuntu -c "git clone https://opendev.org/openstack/devstack"
- su - ubuntu -c "cp /tmp/local.conf /home/ubuntu/devstack/"
- su - ubuntu -c "echo 'export HOST_IP=192.168.10.11' >> .bashrc"
- systemctl restart systemd-networkd
boxpy_data:
key: vm
cpus: 4
memory: 16GB
disk_size: 50GB
version: 20.04
advanced:
nic2: intnet
version: 20.04

View File

@@ -29,10 +29,10 @@ packages:
- vim-nox
- xinit
runcmd:
- [su, -, ubuntu, -c, "git clone https://github.com/gryf/wmaker -b experimental"]
- [su, -, ubuntu, -c, "git clone https://github.com/gryf/vmstrap"]
- [su, -, ubuntu, -c, "vmstrap/bootstrap.sh -c"]
- [rm, -fr, /home/ubuntu/vmstrap]
- su - ubuntu -c "git clone https://github.com/gryf/wmaker -b experimental"
- su - ubuntu -c "git clone https://github.com/gryf/vmstrap"
- su - ubuntu -c "vmstrap/bootstrap.sh -c"
- rm -fr /home/ubuntu/vmstrap
boxpy_data:
key: vm
cpus: 4