├── .gitignore ├── .merlin ├── .travis.yml ├── CHANGES.md ├── LICENSE ├── Makefile ├── README.md ├── VERSION ├── docs └── jitsu.jpg ├── jitsu-libvirt.opam ├── jitsu-libxl.opam ├── jitsu-xapi.opam ├── jitsu.install ├── lib_test ├── test.ml └── test_options.ml ├── opam ├── scripts ├── add_vif.c ├── fast-vif-bridge └── libvirt_config_example.xml └── src ├── .gitignore ├── backends.mli ├── dns_helpers.ml ├── irmin_backend.ml ├── jitsu.ml ├── jitsu.mli ├── libvirt_backend.ml ├── libxl_backend.ml ├── main.ml ├── options.ml ├── rumprun.ml ├── synjitsu.ml ├── synjitsu.mli ├── vm_backends.ml ├── vm_state.ml ├── vm_stop_mode.ml ├── xapi_backend.ml └── xenstore.ml /.gitignore: -------------------------------------------------------------------------------- 1 | *.cmi 2 | *.cmx 3 | *.o 4 | *.swp 5 | jitsu 6 | *.tmp 7 | -------------------------------------------------------------------------------- /.merlin: -------------------------------------------------------------------------------- 1 | PKG libvirt 2 | PKG lwt 3 | PKG dns 4 | PKG dns.lwt 5 | PKG cmdliner 6 | PKG ezxmlm 7 | PKG ipaddr 8 | PKG cstruct 9 | PKG conduit 10 | PKG vchan 11 | PKG irmin 12 | PKG xenstore 13 | PKG xenstore_transport 14 | PKG xenlight 15 | PKG uuidm 16 | PKG xen-api-client 17 | PKG alcotest 18 | EXT lwt 19 | S src/** 20 | S lib_test/** 21 | B bin 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | install: wget https://raw.githubusercontent.com/ocaml/ocaml-travisci-skeleton/master/.travis-opam.sh 3 | script: bash -ex .travis-opam.sh 4 | sudo: required 5 | env: 6 | global: 7 | - ALCOTEST_SHOW_ERRORS=1 8 | - PACKAGE=jitsu 9 | - UBUNTU_TRUSTY=1 10 | matrix: 11 | - OCAML_VERSION=4.02 12 | - OCAML_VERSION=4.01 13 | - OCAML_VERSION=4.01 DEPOPTS="xen-api-client xenctrl libvirt" 14 | - OCAML_VERSION=4.02 DEPOPTS="xen-api-client xenctrl libvirt" 15 | - OCAML_VERSION=4.01 DEPOPTS="libvirt" 16 | - OCAML_VERSION=4.01 DEPOPTS="xenctrl" 17 | - OCAML_VERSION=4.01 DEPOPTS="xen-api-client" 18 | - OCAML_VERSION=4.02 DEPOPTS="libvirt" 19 | - OCAML_VERSION=4.02 DEPOPTS="xenctrl" 20 | - OCAML_VERSION=4.02 DEPOPTS="xen-api-client" 21 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | 0.3.0 (2015-11-11) 2 | 3 | - Support modular backends. Only available backends are compiled in by default. 4 | - Support xenctrl > 0.9.26 5 | - Support xen-api-client > 0.9.8 6 | - Add virtual packages for jitsu-libvirt, jitsu-libxl, jitsu-xapi 7 | - Update README with new installation instructions 8 | 9 | 0.2.1 (2015-15-19) 10 | 11 | - Add/fix support for multiple DNS entries per VM 12 | - Update storage backend to support latest Irmin API (0.10.0) 13 | - Add VERSION file to track version in builds and releases 14 | - Update README with links to paper and recent blog posts 15 | 16 | 0.2 (2015-17-08) 17 | 18 | General: 19 | - Add support for rumprun unikernels in libxl backend (rumprun_config option) 20 | - New configuration syntax with key/value pairs 21 | - VMs are now destroyed by default (was suspend, can be changed with -m) 22 | - Support for waiting for a key in Xenstore before sending DNS reply (wait_for_key option) 23 | - Support for setting fixed response delay per domain (response_delay option, overrides -d) 24 | - Support more than one DNS name per VM 25 | 26 | Storage: 27 | - All storage functionality moved to separate storage module 28 | - Irmin in-memory storage backend to store internal state 29 | - Add --persistdb parameter to persist Irmin db to disk 30 | 31 | Synjitsu: 32 | - Add --synjitsu parameter to connect to Synjitsu 33 | - Support for optionally updating synjitsu with the MAC address of newly booted unikernels 34 | - Support for enabling/disabling synjitsu per domain (use_synjitsu option) 35 | 36 | VM backends: 37 | - All VM management moved to backend modules that implement backends.mli 38 | - Libvirt support now in separate module 39 | - Add experimental XAPI backend support (from Masoud Koleini @koleini) 40 | - Add experimental libxl backend support (from Dave Scott @djs55) 41 | - Add disk support in libxl backend 42 | - Add support for multiple network interfaces and configuration scripts in libxl backend 43 | 44 | Tests: 45 | - Test framework based on alcotest added, but needs more tests 46 | - Implemented tests for options.ml 47 | 48 | Bugfixes: 49 | - Destroyed domains can now be restarted (fixes #8) 50 | 51 | Packaging: 52 | - Removed version number from opam file in dev repo 53 | - libvirt-dev, libvirt-bin added as depext in Debian and Ubuntu 54 | - conduit, vchan, xen-api-client added as opam dependencies 55 | - Update to ocaml-dns 0.15.3 56 | - Enable Travis on Github repository 57 | 58 | 0.1 59 | - First public release 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (* ISC License 2 | * 3 | * Copyright (c) 2014-2015 Magnus Skjegstad 4 | * 5 | * Permission to use, copy, modify, and distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | *) 17 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY=all detect_backends test install clean 2 | 3 | INCLUDE= 4 | OPT=-linkpkg -g 5 | OCAMLOPT=ocamlopt -w A-4-44 6 | 7 | PWD=$(shell pwd) 8 | SRC=$(PWD)/src 9 | BIN=$(PWD)/bin 10 | INSTALLDIR=/usr/local/bin 11 | VERSION=$(shell cat VERSION) 12 | VERSION_ML=$(SRC)/jitsu_version.ml 13 | 14 | MAIN_FILE=main.ml 15 | MAIN_FILE_PREFIX=$(addprefix $(SRC)/,$(MAIN_FILE)) 16 | 17 | # Available backends detected by configure 18 | HAS_LIBVIRT=$(shell ocamlfind query libvirt > /dev/null && echo 1 || echo 0) 19 | HAS_XAPI=$(shell ocamlfind query xen-api-client > /dev/null && echo 1 || echo 0) 20 | HAS_XL=$(shell ocamlfind query xenctrl > /dev/null && echo 1 || echo 0) 21 | 22 | # Configure backends 23 | ifeq ($(HAS_LIBVIRT), 1) 24 | BACKENDS+=libvirt: 25 | BACKEND_FILES += libvirt_backend.ml 26 | BACKEND_PKG := $(strip $(BACKEND_PKG),libvirt) 27 | endif 28 | ifeq ($(HAS_XAPI), 1) 29 | BACKENDS+=xen-api-client: 30 | BACKEND_FILES += xapi_backend.ml 31 | BACKEND_PKG := $(strip $(BACKEND_PKG),xen-api-client,xen-api-client.lwt) 32 | endif 33 | ifeq ($(HAS_XL), 1) 34 | BACKENDS+=xenctrl: 35 | BACKEND_FILES += libxl_backend.ml 36 | BACKEND_PKG := $(strip $(BACKEND_PKG),xenlight,xentoollog) 37 | endif 38 | 39 | BASE_FILES=vm_stop_mode.ml vm_state.ml xenstore.ml backends.mli vm_backends.ml options.ml rumprun.ml $(BACKEND_FILES) dns_helpers.ml irmin_backend.ml synjitsu.mli synjitsu.ml jitsu.mli jitsu.ml 40 | BASE_PKG=-package lwt.syntax,lwt,dns.lwt,cmdliner,ezxmlm,ipaddr,str,conduit,conduit.lwt-unix,irmin.unix,xenstore,xenstore_transport,xenstore_transport.lwt,uuidm$(BACKEND_PKG) 41 | BASE_FILES_PREFIX=$(addprefix $(SRC)/,$(BASE_FILES)) 42 | 43 | TEST_SRC=$(PWD)/lib_test 44 | TEST_FILES=test_options.ml 45 | TEST_FILES_PREFIX=$(addprefix $(TEST_SRC)/,$(TEST_FILES)) 46 | TEST_MAIN_FILE=test.ml 47 | TEST_MAIN_FILE_PREFIX=$(addprefix $(TEST_SRC)/,$(TEST_MAIN_FILE)) 48 | TEST_PKG=$(BASE_PKG),alcotest 49 | TEST_INCLUDE=-I $(SRC) 50 | 51 | all: $(BIN)/jitsu 52 | 53 | $(VERSION_ML): VERSION 54 | @echo 'let current="$(VERSION)"' > $(VERSION_ML) 55 | @echo 'Version $(VERSION)' 56 | 57 | $(BIN)/jitsu: $(BASE_FILES_PREFIX) $(MAIN_FILE_PREFIX) $(VERSION_ML) 58 | @[ "$(BACKENDS)" == "" ] && \ 59 | echo "Warning: No VM backends found. Install xenctrl, xen-api-client or libvirt with opam to add a backend." || \ 60 | echo 'Detected backends: $(subst :, ,$(BACKENDS))' 61 | mkdir -p $(BIN) 62 | cd $(SRC) ; ocamlfind $(OCAMLOPT) $(INCLUDE) $(BASE_PKG) $(OPT) $(VERSION_ML) $(BASE_FILES) $(MAIN_FILE) -o $(BIN)/jitsu -syntax camlp4o 63 | 64 | $(BIN)/test: $(BIN)/jitsu $(TEST_FILES_PREFIX) $(TEST_MAIN_FILE_PREFIX) 65 | cd $(TEST_SRC) ; ocamlfind $(OCAMLOPT) $(TEST_INCLUDE) $(TEST_PKG) $(OPT) $(BASE_FILES_PREFIX) $(TEST_FILES) $(TEST_MAIN_FILE) -o $(BIN)/test -syntax camlp4o 66 | 67 | test: $(BIN)/test 68 | @echo "Running tests..." 69 | $(BIN)/test 70 | 71 | install: $(BIN)/jitsu 72 | @echo "Installing jitsu $(VERSION) in $(INSTALLDIR)..." 73 | install -s $(BIN)/jitsu $(INSTALLDIR)/jitsu 74 | 75 | clean: 76 | cd $(SRC) ; rm -f $(addsuffix .cmi,$(basename $(BASE_FILES))) $(addsuffix .cmx,$(basename $(BASE_FILES))) $(addsuffix .o,$(basename $(BASE_FILES))) 77 | cd $(SRC) ; rm -f $(addsuffix .cmi,$(basename $(MAIN_FILE))) $(addsuffix .cmx,$(basename $(MAIN_FILE))) $(addsuffix .o,$(basename $(MAIN_FILE))) 78 | cd $(SRC) ; rm -f jitsu *~ tags 79 | cd $(SRC) ; rm -f $(addsuffix .cmi,$(basename $(VERSION_ML))) $(addsuffix .cmx,$(basename $(VERSION_ML))) $(addsuffix .o,$(basename $(VERSION_ML))) 80 | cd $(BIN) ; rm -f jitsu test 81 | cd $(TEST_SRC) ; rm -f $(addsuffix .cmi,$(basename $(TEST_FILES))) $(addsuffix .cmx,$(basename $(TEST_FILES))) $(addsuffix .o,$(basename $(TEST_FILES))) 82 | cd $(TEST_SRC) ; rm -f $(addsuffix .cmi,$(basename $(TEST_MAIN_FILE))) $(addsuffix .cmx,$(basename $(TEST_MAIN_FILE))) $(addsuffix .o,$(basename $(TEST_MAIN_FILE))) 83 | rm -rf _tests 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Just-In-Time Summoning of Unikernels # 2 | 3 | *Jitsu is experimental software. See [LICENSE](#license) for conditions.* 4 | 5 | Jitsu is a forwarding DNS server that automatically boots [unikernels](http://wiki.xenproject.org/wiki/Unikernels) on demand. When a DNS query is received, Jitsu first checks for a local unikernel that is mapped to the requested domain. If a unikernel is found, the unikernel is started and its IP is returned to the client. Otherwise, the request is forwarded to the next DNS server. If no DNS requests are received for the unikernel within a given timeout period it is automatically stopped. 6 | 7 | ![](docs/jitsu.jpg) 8 | 9 | This version of Jitsu has been tested with [MirageOS](https://mirage.io) and [Rumprun](https://github.com/rumpkernel/rumprun) unikernels. 10 | 11 | Jitsu supports several backends to manage the unikernel VMs. Currently [libvirt](https://libvirt.org), [XAPI](http://wiki.xenproject.org/wiki/XAPI) and [libxenlight](http://wiki.xen.org/wiki/Choice_of_Toolstacks#Libxenlight_.28libxl.29) are supported. Metadata and internal state is stored in [Irmin](https://github.com/mirage/irmin) and the DNS server is implemented on top of [ocaml-dns](https://github.com/mirage/ocaml-dns). 12 | 13 | - Latest release: https://github.com/mirage/jitsu/releases 14 | - Bugtracker: https://github.com/mirage/jitsu/issues 15 | - Development version: https://github.com/mirage/jitsu 16 | 17 | [![Build Status](https://travis-ci.org/mirage/jitsu.svg)](https://travis-ci.org/mirage/jitsu) 18 | 19 | ## Further reading ## 20 | - [Just-in-Time Summoning of Unikernels (v0.2)](http://www.skjegstad.com/blog/2015/08/17/jitsu-v02/). A more detailed description of how Jitsu works, highlighting some of the new features in v0.2. 21 | - [Jitsu: Just-In-Time Summoning of Unikernels](https://www.usenix.org/system/files/conference/nsdi15/nsdi15-paper-madhavapeddy.pdf) (by A. Madhavapeddy et al). Research paper describing the first version of Jitsu and how we used it to boot unikernel services in milliseconds on ARM-based [Cubieboards](https://en.wikipedia.org/wiki/Cubieboard). 22 | - [Towards Heroku for Unikernels: Part 2 - Self Scaling Systems](http://amirchaudhry.com/heroku-for-unikernels-pt2/). Blog post by Amir Chaudhry describing how tools like Jitsu and unikernels can be used to build demand driven clouds. 23 | - [A unikernel experiment: A VM for every URL](http://www.skjegstad.com/blog/2015/03/25/mirageos-vm-per-url-experiment/). Experimenting with running a separate unikernel per URL. 24 | 25 | #### Overview #### 26 | 27 | - [Installing Jitsu](#installing-jitsu) 28 | - [Getting started](#getting-started) 29 | - [Examples](#examples) 30 | - [MirageOS web server](#mirageos-web-server) 31 | - [nginx in rumprun](#nginx-in-rumprun) 32 | - [Linux VMs in Virtualbox](#linux-vms-in-virtualbox) 33 | - [Command line options](#options) 34 | - [License](#license) 35 | 36 | ## Installing Jitsu ## 37 | 38 | The latest release of Jitsu is available in [`opam`](https://opam.ocaml.org). To install Jitsu, run: 39 | 40 | ``` 41 | $ opam install jitsu 42 | ``` 43 | 44 | When Jitsu is installed it will look for available backends that can be used to start unikernels (or processes). The backends currently supported are `xenctrl` (libxl), `libvirt` and `xen-api-client` (xapi). If a new backend is installed `opam` will reinstall Jitsu to add support for it. 45 | 46 | The virtual packages `jitsu-libvirt`, `jitsu-xapi` and `jitsu-libxl` can be used to force Jitsu to be installed with a specific backend. 47 | 48 | To add a backend, either use the virtual package: 49 | 50 | ``` 51 | $ opam install jitsu-libxl 52 | ``` 53 | 54 | Or install the backend directly with `opam`: 55 | 56 | ``` 57 | $ opam install jitsu 58 | $ opam depext xenctrl # install external dependencies, optional 59 | $ opam install xenctrl 60 | ``` 61 | 62 | To install the latest development version of Jitsu, you can pin Jitsu to the current master branch on Github. This version is *unstable* and changes frequently. 63 | 64 | ``` 65 | $ opam pin add jitsu --dev 66 | $ opam install jitsu 67 | ``` 68 | 69 | If the installation succeeds you should now be able to start Jitsu. If you ran into problems and are using OS X, see below for additional troubleshooting tips. 70 | 71 | #### OS X troubleshooting #### 72 | To install the OCaml libvirt bindings on OS X we have to set CPPFLAGS first (due to this [bug](https://github.com/ocaml/opam-repository/issues/2621)). This step can be skipped on other platforms. 73 | 74 | ``` 75 | $ CPPFLAGS="-Wno-error=tautological-compare -Wno-error=unused-function" \ 76 | opam install libvirt 77 | ``` 78 | 79 | You should now be able to install Jitsu as usual. 80 | 81 | ## Getting started ## 82 | 83 | Jitsu is initially launched with a list of unikernels, their configurations and a set of parameters that define 84 | 85 | - how to connect to the virtualization backend 86 | - how the DNS server should be configured 87 | - how the unikernels should be managed 88 | 89 | A minimal Jitsu configuration could look like this: 90 | 91 | ``` 92 | $ sudo ./jitsu -c xen:/// \ 93 | dns=www.openmirage.org,\ 94 | ip=192.168.0.22,\ 95 | name=mirage-www 96 | ``` 97 | 98 | The command above connects to a local Xen-server (from dom0) through libvirt (the default) and starts the DNS server. Requests for www.openmirage.org will be redirected to the Xen-VM called "mirage-www" with IP 192.168.0.22. If "mirage-www" is not running, Jitsu will start it automatically before responding to the DNS request. 99 | 100 | Each unikernel is configured using a set of key/value pairs separated by commas. The parameters that are supported depends on which virtualization backend (libvirt, xapi or libxl) is used to control the unikernels. See [below](#options) or run `./jitsu --help` for a complete set of options. 101 | 102 | ## Examples ## 103 | 104 | ### MirageOS web server ### 105 | For this example you need a working MirageOS unikernel with a static IP address and access to dom0 on a Xen server with `libxl` installed. You can also install Xen in Virtualbox, as described [here](http://www.skjegstad.com/blog/2015/01/19/mirageos-xen-virtualbox/) or use one of the [Mirage Vagrant VMs](https://github.com/mirage/mirage-vagrant-vms). An example unikernel that displays the unikernel boot time can be found [here](https://github.com/MagnusS/mirage-stats-demo) (a live version is running [here](http://www.jitsu.v0.no)). Follow the instructions in the README to configure the network settings. After building the unikernel you should have a binary file that can be booted in Xen, usually `mirage-www.xen`. You can also check the generated .xl file and locate the `kernel=` parameter to find the file. 106 | 107 | We should now be able to start Jitsu to manage the unikernel: 108 | 109 | ``` 110 | $ sudo jitsu -x libxl \ 111 | dns=www.example.org,\ 112 | ip=10.0.0.1,\ 113 | kernel=mirage-www.xen,\ 114 | memory=64000,\ 115 | name=www,\ 116 | nic=br0 117 | ``` 118 | 119 | This command boots the unikernel when `www.example.org` is resolved. The IP 10.0.0.1 is returned to clients that resolve the domain and the booted unikernel is in `mirage-www.xen`. The VM is given 64MB of memory and access to a network bridge at `br0`. 120 | 121 | If everything worked, Jitsu should now be running a DNS server on localhost. To verify that the domain is automatically started you can run `host` to resolve the domain: 122 | 123 | ``` 124 | host www.example.org 127.0.0.1 125 | Using domain server: 126 | Name: 127.0.0.1 127 | Address: 127.0.0.1#53 128 | Aliases: 129 | 130 | www.example.org has address 10.0.0.1 131 | ``` 132 | 133 | After running `host` you should be able to open the web page on 10.0.0.1 (or telnet to port 80) and ping the IP. 134 | 135 | The unikernel is automatically destroyed after the DNS cache entry expires. This timeout can be set with the `--ttl` parameter. See `jitsu --help` for a full list of available parameters and options that can be passed to the `libxl` backend. 136 | 137 | ### nginx in rumprun ### 138 | 139 | [Rumprun unikernels](https://github.com/rumpkernel/wiki/wiki/Tutorial%3A-Getting-Started) can also be managed by Jitsu, but currently only with the `libxl` backend. Prior to running Jitsu, the [rumprun](https://github.com/rumpkernel/rumprun) tool must be used to generate a JSON configuration file that is passed to Jitsu using the `rumprun_config` parameter. 140 | 141 | A tutorial for building a unikernel that hosts a static web page in QEMU is available [here](https://github.com/rumpkernel/wiki/wiki/Tutorial%3A-Serve-a-static-website-as-a-Unikernel). To get a Xen unikernel, follow the instructions, but run `rumpbake` with the `xen_pv` parameter instead of `hw_virtio`. After baking the Xen unikernel it must be started once with `rumprun` to obtain the configuration files. To run the Nginx unikernel from the tutorial in Xen you could (depending on your configuration) use a command similar to this: 142 | 143 | ``` 144 | sudo rumprun -T tmp xen -M 64 -i \ 145 | -b images/stubetc.iso,/etc -b images/data.iso,/data \ 146 | -I mynet,xenif,bridge=br0 -W mynet,inet,static,10.0.0.1/24,10.0.1.1 \ 147 | -- nginx.bin -c /data/conf/nginx.conf 148 | ``` 149 | 150 | The command above will boot a rumprun unikernel that mounts two disks (stubetc.iso and data.iso), connect it to the network bridge `br0` and give it the IP 10.0.0.1. The `-T` parameter saves the generated configuration files in the `tmp` directory. You can verify that the unikernel booted correctly by running `sudo xl list`. You can also attach to the console with `sudo xl console [name of unikernel]`. To stop the unikernel, use `sudo xl destroy [name of unikernel]`. 151 | 152 | If the unikernel booted correctly we should now be able to use the file `tmp/json.conf` to boot it with Jitsu. 153 | 154 | ``` 155 | jitsu -x libxl dns=www.example.org,\ 156 | memory=64000,\ 157 | ip=10.0.0.1,\ 158 | name=rumprun,\ 159 | kernel=nginx.bin,\ 160 | disk=images/stubetc.iso@xvda,\ 161 | disk=images/data.iso@xvdb,\ 162 | nic=br0,\ 163 | rumprun_config=tmp/json.cfg 164 | ``` 165 | 166 | Verify that the unikernel boots in Jitsu by running `host www.example.org 127.0.0.1`. An nginx web server should now be running in a rumprun unikernel on IP 10.0.0.1. 167 | 168 | Note that rumprun unikernels currently have to wait for the disk images to be configured by Xen. When the disks are mounted as ISO files (as in this example) the total boot time can be more than a second. An alternative is to use `losetup` to create loopback devices that map to the ISO files. The `-d` parameter can also be used to delay the DNS response to compensate for this. See `jitsu --help` for a full list of available options. 169 | 170 | ### Linux VMs in Virtualbox ### 171 | Jitsu can be used to control VMs in Virtualbox with libvirt. Note that how well this will work depends on how quickly the VM is able to respond to requests after resuming from suspend (see also the `-d` parameter for how to delay the DNS response). 172 | 173 | First, install libvirt and use virsh to display a list of available VMs. Example output: 174 | 175 | ``` 176 | $ virsh list --all 177 | Welcome to virsh, the virtualization interactive terminal. 178 | 179 | Type: 'help' for help with commands 180 | 'quit' to quit 181 | 182 | virsh # list --all 183 | Id Name State 184 | ---------------------------------------------------- 185 | 2 Ubuntu running 186 | ``` 187 | 188 | If virsh is unable to connect to Virtualbox, you may have to adjust the connection URI (`-c [uri]`). The default connection URI for Virtualbox is vbox:///session - see [this page](https://libvirt.org/remote.html) for more details. In OS X you may have to set the socket manually, which can be done with 'vbox:///session?socket=path-to-socket'. Remember to use the same connection URI for Jitsu below. 189 | 190 | You should now be able to start Jitsu. Use '-m suspend' to set it to suspend the VM on inactivity. Example output: 191 | 192 | ``` 193 | $ sudo ./jitsu dns=www.example.com,ip=127.0.0.1,name=Ubuntu -m suspend -c vbox:///session 194 | Connecting to vbox:///session... 195 | Adding domain 'www.example.com' for VM 'Ubuntu' with ip 127.0.0.1 196 | Adding SOA 'example.com' with ttl=60 197 | Adding A PTR for 'www.example.com' with ttl=60 and ip=127.0.0.1 198 | Starting server on 127.0.0.1:53... 199 | ``` 200 | 201 | To test that Jitsu works, try to resolve the domain with host: 202 | 203 | ``` 204 | $ host www.example.com 127.0.0.1 205 | Using domain server: 206 | Name: 127.0.0.1 207 | Address: 127.0.0.1#53 208 | Aliases: 209 | 210 | www.example.com has address 127.0.0.1 211 | ``` 212 | 213 | The domain should now be running. 214 | 215 | ``` 216 | $ virsh dominfo Ubuntu 217 | Id: 2 218 | Name: Ubuntu 219 | UUID: 6e696eb7-09f4-484c-981b-8d34efa0304d 220 | OS Type: hvm 221 | State: running 222 | CPU(s): 3 223 | Max memory: 2147483648 KiB 224 | Used memory: 3166208 KiB 225 | Persistent: yes 226 | Managed save: unknown 227 | ``` 228 | 229 | After 2 minutes without DNS requests, Jitsu will suspend the domain automatically. This timeout can be adjusted with the --ttl parameter. Jitsu terminates the VM after 2 x DNS TTL seconds has expired without new requests. 230 | 231 | ## Options ## 232 | ``` 233 | -b ADDR, --bind=ADDR (absent=127.0.0.1) 234 | Bind local DNS server to interface with this IP 235 | 236 | -c CONNECT, --connect=CONNECT (absent=xen:///) 237 | Libvirt and Xapi connection string (e.g. xen+ssh://x.x.x.x/system 238 | or vbox:///session) 239 | 240 | -d SECONDS, --delay=SECONDS (absent=0.1) 241 | Time to wait in seconds before responding to a DNS query after the 242 | local VM has started. This delay gives the VM time to open up the 243 | necessary TCP ports etc. Setting this value too low can result in 244 | long delays on the first TCP request to the VM. 245 | 246 | -f ADDR, --forwarder=ADDR 247 | IP address of DNS server queries should be forwarded to if no local 248 | match is found. Defaults to system default (/etc/resolv.conf) if 249 | not specified. Set to 0.0.0.0 to disable forwarding. 250 | 251 | --help[=FMT] (default=pager) 252 | Show this help in format FMT (pager, plain or groff). 253 | 254 | -l PORT, --listen=PORT (absent=53) 255 | UDP port to listen for DNS queries 256 | 257 | -m MODE, --mode=MODE (absent=destroy) 258 | How to stop running VMs after timeout. Valid options are suspend, 259 | destroy and shutdown. Suspended VMs are generally faster to resume, 260 | but require resources to store state. Note that MirageOS 261 | suspend/resume is currently not supported on ARM. 262 | 263 | -p PORT, --port=PORT (absent=53) 264 | UDP port to forward DNS queries to 265 | 266 | --persistdb=path 267 | Store the Irmin database in the specified path. The default is to 268 | store the database in memory only. Note that modifying this 269 | database while Jitsu is running is currently unsupported and may 270 | crash Jitsu or have other unexpected results. 271 | 272 | --synjitsu=UUID 273 | UUID of a running Synjitsu compatible unikernel. When specified, 274 | Jitsu will attempt to connect to a Synjitsu unikernel over Vchan on 275 | port 'synjitsu' and send notifications with updates on MAC- and 276 | IP-addresses of booted unikernels. This allows Synjitsu to send 277 | gratuitous ARP on behalf of booting unikernels and to cache 278 | incoming SYN packets until they are ready to receive them. This 279 | feature is experimental and requires a patched MirageOS TCP/IP 280 | stack. 281 | 282 | -t SECONDS, --ttl=SECONDS (absent=60) 283 | DNS TTL in seconds. The TTL determines how long the clients may 284 | cache our DNS response. VMs are terminated after no DNS requests 285 | have been received for TTL*2 seconds. 286 | 287 | --version 288 | Show version information. 289 | 290 | -x BACKEND, --backend=BACKEND (absent=libvirt) 291 | Which backend to use. Currently libvirt, xapi and libxl are 292 | supported. Xapi and libxl are less tested and should be considered 293 | experimental. 294 | 295 | COMMON CONFIGURATION 296 | response_delay 297 | Override default DNS query response delay for this unikernel. See 298 | also -d. 299 | 300 | wait_for_key 301 | Wait for this key to appear in Xenstore before responding to the 302 | DNS query. Sleeps for [response_delay] after the key appears. The 303 | key should be relative to /local/domain/[domid]/. 304 | 305 | use_synjitsu 306 | Enable Synjitsu for this domain if not 0 or absent (requires 307 | Synjitsu support enabled) 308 | 309 | LIBVIRT CONFIGURATION 310 | name 311 | Name of VM defined in libvirt (ignored if uuid is set) 312 | 313 | uuid 314 | UUID of VM defined in libvirt (required, but optional if name is 315 | set) 316 | 317 | dns DNS name (required) 318 | 319 | ip IP to return in DNS reply (required) 320 | 321 | XAPI CONFIGURATION 322 | name 323 | Name of VM defined in Xapi (ignored if uuid is set) 324 | 325 | uuid 326 | UUID of VM defined in Xapi (optional if name is set) 327 | 328 | dns DNS name (required) 329 | 330 | ip IP to return in DNS reply (required) 331 | 332 | LIBXL CONFIGURATION 333 | name 334 | Name of created VM (required) 335 | 336 | dns DNS name (required) 337 | 338 | ip IP to return in DNS reply (required) 339 | 340 | kernel 341 | VM kernel file name (required) 342 | 343 | memory 344 | VM memory in bytes (required) 345 | 346 | cmdline 347 | Extra parameters passed to kernel (optional) 348 | 349 | nic Network device (br0, eth0 etc). Can be set more than once to 350 | configure multiple NICs (optional) 351 | 352 | script 353 | Virtual interface (VIF) configuration script. Can be set more than 354 | once to specify a VIF script per network device (optional) 355 | 356 | disk 357 | Disk to connect to the Xen VM. Format '[dom0 358 | device/file]@[hdX/xvdX/sdX etc]'. Can be set more than once to 359 | configure multiple disks (optional) 360 | 361 | rumprun_config 362 | Path to file with rumprun unikernel JSON config (optional) 363 | ``` 364 | 365 | ## License ## 366 | ``` 367 | Copyright (c) 2014-2015 Magnus Skjegstad and contributors. 368 | 369 | Permission to use, copy, modify, and distribute this software for any 370 | purpose with or without fee is hereby granted, provided that the above 371 | copyright notice and this permission notice appear in all copies. 372 | 373 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 374 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 375 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 376 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 377 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 378 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 379 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 380 | ``` 381 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.3.0 2 | -------------------------------------------------------------------------------- /docs/jitsu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirage/jitsu/6be8a950d831a6055b7611747497bd418f4ff1ba/docs/jitsu.jpg -------------------------------------------------------------------------------- /jitsu-libvirt.opam: -------------------------------------------------------------------------------- 1 | opam-version: "1.2" 2 | maintainer: "Magnus Skjegstad " 3 | authors: "Magnus Skjegstad " 4 | homepage: "https://github.com/mirage/jitsu" 5 | bug-reports: "https://github.com/mirage/jitsu/issues/" 6 | dev-repo: "https://github.com/mirage/jitsu.git" 7 | license: "ISC" 8 | 9 | depends: [ "jitsu" 10 | "libvirt" ] 11 | -------------------------------------------------------------------------------- /jitsu-libxl.opam: -------------------------------------------------------------------------------- 1 | opam-version: "1.2" 2 | maintainer: "Magnus Skjegstad " 3 | authors: "Magnus Skjegstad " 4 | homepage: "https://github.com/mirage/jitsu" 5 | bug-reports: "https://github.com/mirage/jitsu/issues/" 6 | dev-repo: "https://github.com/mirage/jitsu.git" 7 | license: "ISC" 8 | 9 | depends: [ "jitsu" 10 | "xenctrl" ] 11 | 12 | -------------------------------------------------------------------------------- /jitsu-xapi.opam: -------------------------------------------------------------------------------- 1 | opam-version: "1.2" 2 | maintainer: "Magnus Skjegstad " 3 | authors: "Magnus Skjegstad " 4 | homepage: "https://github.com/mirage/jitsu" 5 | bug-reports: "https://github.com/mirage/jitsu/issues/" 6 | dev-repo: "https://github.com/mirage/jitsu.git" 7 | license: "ISC" 8 | 9 | depends: [ "jitsu" 10 | "xen-api-client" ] 11 | 12 | -------------------------------------------------------------------------------- /jitsu.install: -------------------------------------------------------------------------------- 1 | bin: [ "bin/jitsu" ] 2 | -------------------------------------------------------------------------------- /lib_test/test.ml: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2015 Magnus Skjegstad 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | *) 16 | 17 | let () = 18 | Alcotest.run ~and_exit:true "Test options" Test_options.test_options 19 | -------------------------------------------------------------------------------- /lib_test/test_options.ml: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2015 Magnus Skjegstad 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | *) 16 | 17 | let hashtbl = 18 | let t = Hashtbl.create 15 in 19 | Hashtbl.add t "int" "100"; 20 | Hashtbl.add t "not_int" "xxx"; 21 | Hashtbl.add t "string" "hello world"; 22 | Hashtbl.add t "dns_name" "www.example.org"; 23 | Hashtbl.add t "str_list" "val1"; 24 | Hashtbl.add t "str_list" "val2"; 25 | Hashtbl.add t "str_list" "val3"; 26 | Hashtbl.add t "str_list" "val4"; 27 | Hashtbl.add t "tuple_str_list" "left1"; 28 | Hashtbl.add t "tuple_str_list" "left2:"; 29 | Hashtbl.add t "tuple_str_list" "left3:r"; 30 | Hashtbl.add t "tuple_str_list" "left4:right4"; 31 | Hashtbl.add t "tuple_str_list" ":right5"; 32 | Hashtbl.add t "tuple_str_list" "l:r"; 33 | Hashtbl.add t "tuple_str_list" ":"; 34 | Hashtbl.add t "tuple_str_list" ""; 35 | Hashtbl.add t "bool" "0"; 36 | Hashtbl.add t "bool_list" "true"; 37 | Hashtbl.add t "bool_list" "false"; 38 | Hashtbl.add t "bool_list" "0"; 39 | Hashtbl.add t "bool_list" "1"; 40 | t 41 | 42 | let test_get_int () = 43 | match (Options.get_int hashtbl "int") with 44 | | `Ok i -> Alcotest.(check int) "int" 100 i 45 | | `Error e -> Alcotest.fail (Options.string_of_error e) 46 | 47 | let test_get_int_str () = 48 | match (Options.get_int hashtbl "not_int") with 49 | | `Ok _ -> Alcotest.fail "get_int succeeded for string value" 50 | | `Error _ -> () 51 | 52 | let test_get_str () = 53 | match (Options.get_str hashtbl "string") with 54 | | `Ok s -> Alcotest.(check string) "string" "hello world" s 55 | | `Error e -> Alcotest.fail (Options.string_of_error e) 56 | 57 | let test_get_str_list () = 58 | let expected = ["val1";"val2";"val3";"val4"] in 59 | match (Options.get_str_list hashtbl "str_list") with 60 | | `Ok s -> Alcotest.(check (list string)) "string list" expected s 61 | | `Error e -> Alcotest.fail (Options.string_of_error e) 62 | 63 | let test_get_bool () = 64 | match (Options.get_bool hashtbl "bool") with 65 | | `Ok s -> if not s = false then Alcotest.fail "expected false" 66 | | `Error e -> Alcotest.fail (Options.string_of_error e) 67 | 68 | let test_get_bool_list () = 69 | let expected = [ true ; false ; false ; true ] in 70 | match (Options.get_bool_list hashtbl "bool_list") with 71 | | `Ok s -> let _ = List.map2 (fun a b -> 72 | if not a=b then 73 | Alcotest.fail (Printf.sprintf "Bool lists are not equal. Expected %B, got %B" a b) 74 | else 75 | ()) expected s in 76 | () 77 | | `Error e -> Alcotest.fail (Options.string_of_error e) 78 | 79 | let test_get_dns_name () = 80 | match (Options.get_dns_name hashtbl "dns_name") with 81 | | `Ok i -> Alcotest.(check string) "dns_name" "www.example.org" (Dns.Name.to_string i) 82 | | `Error e -> Alcotest.fail (Options.string_of_error e) 83 | 84 | 85 | let test_get_str_tuple_list () = 86 | let is_eq a b = (* compare string option *) 87 | match a,b with 88 | | Some a, Some b -> String.compare a b = 0 89 | | None, None -> true 90 | | _ -> false 91 | in 92 | let is_eq_tup a b = (* compare (string option * string option) *) 93 | let a_l,a_r = a in 94 | let b_l,b_r = b in 95 | (is_eq a_l b_l) && (is_eq a_r b_r) 96 | in 97 | let opt_s a = (* string option to string *) 98 | match a with 99 | | Some s -> (Printf.sprintf "Some '%s'" s) 100 | | None -> "None" 101 | in 102 | let t_s t = (* (string option * string option) to string *) 103 | let left, right = t in 104 | Printf.sprintf "(%s, %s)" (opt_s left) (opt_s right) 105 | in 106 | let expected = [ (Some "left1", None) ; 107 | (Some "left2", None) ; 108 | (Some "left3", Some "r") ; 109 | (Some "left4", Some "right4") ; 110 | (None, Some "right5") ; 111 | (Some "l", Some "r") ; 112 | (None, None) ; 113 | (None, None) ] in 114 | match (Options.get_str_tuple_list hashtbl "tuple_str_list" ~sep:':' ()) with 115 | | `Ok s -> let _ = List.map2 (fun a b -> 116 | if not (is_eq_tup a b) then 117 | Alcotest.fail (Printf.sprintf "Tuple lists are not equal. Expected %s, got %s" (t_s a) (t_s b)) 118 | else 119 | ()) expected s in 120 | () 121 | | `Error e -> Alcotest.fail (Options.string_of_error e) 122 | 123 | (* Run it *) 124 | let test_options = 125 | ["Test options", 126 | [ "get_int on int", `Quick, test_get_int ; 127 | "get_int on string", `Quick, test_get_int_str ; 128 | "get_str", `Quick, test_get_str ; 129 | "get_str_list", `Quick, test_get_str_list ; 130 | "get_bool", `Quick, test_get_bool ; 131 | "get_bool_list", `Quick, test_get_bool_list ; 132 | "get_dns_name", `Quick, test_get_dns_name ; 133 | "get_str_tuple_list", `Quick, test_get_str_tuple_list ; 134 | ] 135 | ] 136 | -------------------------------------------------------------------------------- /opam: -------------------------------------------------------------------------------- 1 | opam-version: "1.2" 2 | maintainer: "Magnus Skjegstad " 3 | authors: "Magnus Skjegstad " 4 | homepage: "https://github.com/mirage/jitsu" 5 | bug-reports: "https://github.com/mirage/jitsu/issues/" 6 | dev-repo: "https://github.com/mirage/jitsu.git" 7 | license: "ISC" 8 | 9 | build: [ 10 | [make] 11 | ] 12 | 13 | build-test: [ 14 | [make "test"] 15 | ] 16 | 17 | depends: [ "ocamlfind" 18 | "lwt" 19 | "dns" { >= "0.15.3" } 20 | "xenstore" 21 | "xenstore_transport" 22 | "cmdliner" 23 | "ipaddr" 24 | "ezxmlm" 25 | "conduit" 26 | "vchan" 27 | "uuidm" 28 | "irmin-unix" 29 | "irmin" { >= "0.10.0" } 30 | "git" 31 | "alcotest" ] 32 | 33 | depopts: [ 34 | "xenctrl" 35 | "xen-api-client" 36 | "libvirt" 37 | ] 38 | 39 | conflicts: [ 40 | "xenctrl" { < "0.9.29" } 41 | "xen-api-client" { < "0.9.10" } 42 | ] 43 | 44 | -------------------------------------------------------------------------------- /scripts/add_vif.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | extern unsigned int if_nametoindex (const char *__ifname); 15 | extern char *if_indextoname (unsigned int __ifindex, char *__ifname); 16 | 17 | int br_socket_fd = -1; 18 | 19 | static int 20 | br_init(void) 21 | { 22 | if ((br_socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) 23 | return errno; 24 | return 0; 25 | } 26 | 27 | static int 28 | br_add_interface(const char *bridge, const char *dev) 29 | { 30 | struct ifreq ifr; 31 | int err; 32 | int ifindex = if_nametoindex(dev); 33 | 34 | if (ifindex == 0) 35 | return ENODEV; 36 | 37 | strncpy(ifr.ifr_name, bridge, IFNAMSIZ); 38 | #ifdef SIOCBRADDIF 39 | ifr.ifr_ifindex = ifindex; 40 | err = ioctl(br_socket_fd, SIOCBRADDIF, &ifr); 41 | if (err < 0) 42 | #endif 43 | { 44 | unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 }; 45 | 46 | ifr.ifr_data = (char *) args; 47 | err = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr); 48 | } 49 | 50 | return err < 0 ? errno : 0; 51 | } 52 | 53 | static int chflags(char *dev, __u32 flags, __u32 mask) 54 | { 55 | struct ifreq ifr; 56 | int fd; 57 | int err; 58 | 59 | strncpy(ifr.ifr_name, dev, IFNAMSIZ); 60 | fd = br_socket_fd; 61 | if (fd < 0) 62 | return -1; 63 | err = ioctl(fd, SIOCGIFFLAGS, &ifr); 64 | if (err) { 65 | perror("SIOCGIFFLAGS"); 66 | close(fd); 67 | return -1; 68 | } 69 | if ((ifr.ifr_flags^flags)&mask) { 70 | ifr.ifr_flags &= ~mask; 71 | ifr.ifr_flags |= mask&flags; 72 | err = ioctl(fd, SIOCSIFFLAGS, &ifr); 73 | if (err) 74 | perror("SIOCSIFFLAGS"); 75 | } 76 | close(fd); 77 | return err; 78 | 79 | } 80 | 81 | int 82 | main(int argc, char **argv) 83 | { 84 | char *hotplug_vif = getenv("vif"); 85 | 86 | if (!hotplug_vif) 87 | errx(1, "vif not defined"); 88 | 89 | if(br_socket_fd == -1) { 90 | br_init(); 91 | } 92 | br_add_interface("br0", hotplug_vif); 93 | __u32 mask=0; 94 | __u32 flags=0; 95 | mask |= IFF_UP; 96 | flags |= IFF_UP; 97 | chflags(hotplug_vif, flags, mask); 98 | return 0; 99 | } 100 | -------------------------------------------------------------------------------- /scripts/fast-vif-bridge: -------------------------------------------------------------------------------- 1 | #!/bin/dash 2 | # 3 | # Faster implementation of /etc/xen/scripts/vif-bridge without dependencies. See the original script for 4 | # usage. 5 | 6 | # Uncomment to log start and stop times (for benchmarking) 7 | #date "+%H:%M:%S.%N fast-vif-bridge START $vif $1 pid $$" >> /var/log/vif-bridge.log 8 | #fun_done () { 9 | # date "+%H:%M:%S.%N fast-vif-bridge EXIT $vif $1 pid $$" >> /var/log/vif-bridge.log 10 | #} 11 | #trap fun_done EXIT 12 | 13 | bridge=br0 14 | mtu=1500 # MTU should match the MTU of $bridge 15 | command=$1 16 | 17 | case "$command" in 18 | online) 19 | ip link set dev ${vif} down 20 | ip link set dev ${vif} address fe:ff:ff:ff:ff:ff || true 21 | ip address flush dev ${vif} 22 | 23 | ip link set dev ${vif} mtu ${mtu} 24 | 25 | brctl addif ${bridge} ${vif} # note, no checks to see if it is already on bridge 26 | ip link set dev ${vif} up 27 | ;; 28 | 29 | offline) 30 | brctl delif $bridge $vif 2>/dev/null || true 31 | ifconfig $vif down 2>/dev/null || true 32 | ;; 33 | 34 | add) 35 | ip link set dev ${vif} down 36 | ip link set dev ${vif} address fe:ff:ff:ff:ff:ff || true 37 | ip address flush dev ${vif} 38 | 39 | ip link set dev ${vif} mtu ${mtu} 40 | 41 | brctl addif ${bridge} ${vif} # note, no checks to see if it is already on bridge 42 | ip link set dev ${vif} up 43 | ;; 44 | esac 45 | 46 | -------------------------------------------------------------------------------- /scripts/libvirt_config_example.xml: -------------------------------------------------------------------------------- 1 | 2 | static 3 | 4 | 32000 5 | 32000 6 | 1 7 | 8 | linux 9 | 10 | mir-static.xen 11 | 12 | 13 | 14 | destroy 15 | restart 16 | preserve 17 | 18 | 19 | 20 | 21 | 22 |