001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005package org.anarres.qemu.exec;
006
007import java.util.HashMap;
008import java.util.List;
009import java.util.Map;
010import javax.annotation.Nonnegative;
011import javax.annotation.Nonnull;
012import org.anarres.qemu.exec.util.QEmuIdAllocator;
013import org.anarres.qemu.exec.vm.device.QEmuDevice;
014
015/**
016 * A device frontend, exposed to the guest operating system.
017 *
018 * To list the device types supported by your QEmu installation, run
019 * <code>qemu -device help</code>.
020 *
021 * To list the properties of a device, run
022 * <code>qemu -device &lt;devicetype&gt;,help</code>.
023 *
024 * @see QEmuDevice
025 * @author shevek
026 */
027public class QEmuDeviceOption extends AbstractQEmuOption {
028
029    public static final String PROP_ID = "id";
030    public static final String PROP_BUS = "bus";
031    public static final String PROP_ADDR = "addr";
032    private final String name;
033    private final Map<String, String> properties = new HashMap<String, String>();
034
035    public QEmuDeviceOption(@Nonnull String name) {
036        this.name = name;
037    }
038
039    @Nonnull
040    public QEmuDeviceOption withProperties(@Nonnull Map<String, String> properties) {
041        this.properties.putAll(properties);
042        return this;
043    }
044
045    @Nonnull
046    public QEmuDeviceOption withProperty(@Nonnull String key, @Nonnull String value) {
047        properties.put(key, value);
048        return this;
049    }
050
051    @Nonnull
052    public QEmuDeviceOption withProperty(@Nonnull String key) {
053        properties.put(key, null);
054        return this;
055    }
056
057    @Nonnull
058    public QEmuDeviceOption withId(@Nonnull String id) {
059        return withProperty(PROP_ID, id);
060    }
061
062    @Override
063    public void appendTo(List<? super String> line) {
064        StringBuilder buf = new StringBuilder(name);
065        appendTo(buf, properties);
066        add(line, "-device", buf);
067    }
068
069    public static class Pci extends QEmuDeviceOption {
070
071        // virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6
072        public Pci(@Nonnull String name) {
073            super(name);
074            withPciBus("pci.0");
075        }
076
077        @Override
078        public Pci withId(@Nonnull String id) {
079            super.withId(id);
080            return this;
081        }
082
083        @Nonnull
084        public Pci withPciBus(@Nonnull String bus) {
085            withProperty(PROP_BUS, bus);
086            return this;
087        }
088
089        @Nonnull
090        public Pci withPciAddress(@Nonnull String address) {
091            withProperty(PROP_ADDR, address);
092            return this;
093        }
094
095        @Nonnull
096        public Pci withPciAddress(@Nonnull QEmuIdAllocator allocator) {
097            withProperty(PROP_ADDR, allocator.newPciAddress());
098            return this;
099        }
100    }
101
102    public static class VirtioBalloon extends Pci {
103
104        public VirtioBalloon() {
105            super("virtio-balloon-pci");
106        }
107    }
108
109    public static class VirtioNet extends Pci {
110
111        // virtio-net-pci,netdev=hostnet0,id=net0,mac=fa:16:3e:13:ff:1f,bus=pci.0,addr=0x3
112        public static final String PROP_NETDEV = "netdev";
113        public static final String PROP_MAC = "mac";
114        public static final String PROP_BOOTINDEX = "bootindex";
115        public static final String PROP_ROMFILE = "romfile";
116        public static final String PROP_ROMBAR = "rombar";
117
118        public VirtioNet() {
119            super("virtio-net-pci");
120        }
121
122        @Nonnull
123        public VirtioNet withMac(@Nonnull String mac) {
124            withProperty(PROP_MAC, mac);
125            return this;
126        }
127
128        @Nonnull
129        public VirtioNet withBackend(@Nonnull QEmuNetdevOption backend) {
130            withProperty(PROP_NETDEV, backend.id);
131            return this;
132        }
133
134        @Nonnull
135        public VirtioNet withBootIndex(@Nonnegative int index) {
136            withProperty(PROP_BOOTINDEX, String.valueOf(index));
137            return this;
138        }
139
140        @Nonnull
141        public VirtioNet withBootIndex(@Nonnull QEmuIdAllocator allocator) {
142            return withBootIndex(allocator.newNetworkBootIndex());
143        }
144    }
145
146    /** Usually results in /dev/vda. */
147    public static class VirtioBlock extends Pci {
148        // virtio-blk-pci,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1
149
150        public static final String PROP_SCSI = "scsi";
151        public static final String PROP_DRIVE = "drive";
152        public static final String PROP_BOOTINDEX = "bootindex";
153
154        public VirtioBlock() {
155            super("virtio-blk-pci");
156        }
157
158        @Nonnull
159        public VirtioBlock withDrive(String id) {
160            withProperty(PROP_DRIVE, id);
161            return this;
162        }
163
164        @Nonnull
165        public VirtioBlock withDrive(@Nonnull QEmuDriveOption option) {
166            return withDrive(option.id);
167        }
168    }
169
170    public static class VirtioScsi extends Pci {
171
172        public VirtioScsi() {
173            super("virtio-scsi-pci");
174        }
175    }
176
177    public static class VirtioSerial extends Pci {
178
179        public static final String PROP_CHARDEV = "chardev";
180
181        public VirtioSerial() {
182            super("virtio-serial-pci");
183        }
184
185        @Override
186        public VirtioSerial withId(@Nonnull String id) {
187            super.withId(id);
188            return this;
189        }
190
191        @Nonnull
192        public VirtioSerial withChardev(String id) {
193            withProperty(PROP_CHARDEV, id);
194            return this;
195        }
196
197        @Nonnull
198        public VirtioSerial withChardev(@Nonnull QEmuChardevOption option) {
199            return withChardev(option.id);
200        }
201    }
202
203    public static class Piix3Usb extends Pci {
204
205        // piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2
206        public Piix3Usb() {
207            super("piix3-usb-uhci");
208            withId("usb");
209        }
210
211        @Override
212        public Piix3Usb withPciAddress(@Nonnull QEmuIdAllocator allocator) {
213            withProperty(PROP_ADDR, allocator.newPciAddresses(2, "."));
214            return this;
215        }
216    }
217
218    public static class Isa extends QEmuDeviceOption {
219
220        public Isa(String name) {
221            super(name);
222        }
223
224        @Override
225        public Isa withId(@Nonnull String id) {
226            super.withId(id);
227            return this;
228        }
229    }
230
231    public static class IsaSerial extends Isa {
232        // isa-serial,chardev=charserial0,id=serial0
233
234        public static final String PROP_CHARDEV = "chardev";
235
236        public IsaSerial() {
237            super("isa-serial");
238        }
239
240        @Override
241        public IsaSerial withId(@Nonnull String id) {
242            super.withId(id);
243            return this;
244        }
245
246        @Nonnull
247        public IsaSerial withChardev(String id) {
248            withProperty(PROP_CHARDEV, id);
249            return this;
250        }
251    }
252}