1extern crate xdr_codec;
2extern crate byteorder;
3extern crate uuid;
4extern crate tokio_io;
5extern crate tokio_proto;
6extern crate tokio_service;
7extern crate tokio_core;
8extern crate tokio_uds;
9extern crate tokio_uds_proto;
10extern crate bytes;
11#[macro_use]
12extern crate futures;
13#[macro_use]
14extern crate log;
15extern crate env_logger;
16#[macro_use]
17extern crate bitflags;
18
19use xdr_codec::{Unpack};
20
21use byteorder::NetworkEndian;
22
23pub mod request;
24pub mod async;
25mod proto;
26use request::*;
27
28use std::io::Cursor;
29
30pub struct Libvirt<Io: ::std::io::Read+::std::io::Write> {
31 serial: u32,
32 stream: Io,
33}
34
35#[derive(Debug)]
37pub enum LibvirtError {
38 IoError(::std::io::Error),
40 XdrError(xdr_codec::Error),
42 Libvirt(request::virNetMessageError),
44}
45
46impl LibvirtError {
47 pub fn is_io(&self) -> bool {
48 if let &LibvirtError::IoError(_) = self {
49 true
50 } else {
51 false
52 }
53 }
54}
55
56impl ::std::convert::From<::std::io::Error> for LibvirtError {
57 fn from(e: ::std::io::Error) -> Self {
58 LibvirtError::IoError(e.into())
59 }
60}
61
62impl ::std::convert::From<xdr_codec::Error> for LibvirtError {
63 fn from(e: xdr_codec::Error) -> Self {
64 LibvirtError::XdrError(e)
65 }
66}
67
68impl ::std::convert::From<virNetMessageError> for LibvirtError {
69 fn from(e: virNetMessageError) -> Self {
70 LibvirtError::Libvirt(e)
71 }
72}
73
74impl ::std::fmt::Display for LibvirtError {
75 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
76 match self {
77 &LibvirtError::XdrError(ref e) => e.fmt(f),
78 &LibvirtError::IoError(ref e) => e.fmt(f),
79 &LibvirtError::Libvirt(ref vmsg) => vmsg.fmt(f),
80 }
81 }
82}
83
84impl ::std::error::Error for LibvirtError {
85 fn description(&self) -> &str {
86 match self {
87 &LibvirtError::XdrError(ref e) => e.description(),
88 &LibvirtError::IoError(ref e) => e.description(),
89 &LibvirtError::Libvirt(ref vmsg) => vmsg.description(),
90 }
91 }
92
93}
94
95impl ::std::fmt::Display for virNetMessageError {
96 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
97 match self.message {
98 Some(ref msg) => write!(f, "{}", &msg.0),
99 None => write!(f, "{:?}", self.message),
100 }
101 }
102}
103
104impl ::std::error::Error for virNetMessageError {
105 fn description(&self) -> &str {
106 match self.message {
107 Some(ref msg) => &msg.0,
108 None => panic!("virNetMessageError message absent"),
109 }
110 }
111}
112
113impl<Io> Libvirt<Io> where Io: ::std::io::Read+::std::io::Write {
114 pub fn new(stream: Io) -> Self {
115 Libvirt {
116 serial: 0,
117 stream: stream,
118 }
119 }
120
121 fn serial(&mut self) -> u32 {
122 let serial = self.serial;
123 self.serial += 1;
124 return serial;
125 }
126
127 fn write_packet<P: xdr_codec::Pack<Cursor<Vec<u8>>>>(&mut self, packet: P) -> xdr_codec::Result<usize> {
128 use std::io::Cursor;
129 use byteorder::WriteBytesExt;
130
131 let buf = Vec::new();
132 let (sz, buf) = {
133 let mut c = Cursor::new(buf);
134 let sz = try!(packet.pack(&mut c));
135 let inner = c.into_inner();
136 (sz, inner)
137 };
138 let len = sz + 4;
139 try!(self.stream.write_u32::<NetworkEndian>(len as u32));
140 try!(self.stream.write(&buf[0..sz]));
141 Ok(len as usize)
143 }
144
145 fn read_packet_reply<P: xdr_codec::Unpack<Cursor<Vec<u8>>>>(&mut self) -> Result<P, LibvirtError> {
170 use byteorder::{ReadBytesExt};
171
172 let mut len = try!(self.stream.read_u32::<NetworkEndian>());
173 len -= 4; let mut buf = vec![0;len as usize];
177 try!(self.stream.read_exact(&mut buf[0..len as usize]));
178 let mut cur = Cursor::new(buf);
179
180 let (header, _) = try!(virNetMessageHeader::unpack(&mut cur));
181
182 if header.status == virNetMessageStatus::VIR_NET_OK {
183 let (pkt, _) = try!(P::unpack(&mut cur));
184 return Ok(pkt);
185 }
186
187 let (err, _) = try!(virNetMessageError::unpack(&mut cur));
188 return Err(LibvirtError::from(err));
189 }
190
191 fn request<Req: xdr_codec::Pack<Cursor<Vec<u8>>>, Resp: xdr_codec::Unpack<Cursor<Vec<u8>>>>(&mut self, packet: Req) -> Result<Resp, LibvirtError> {
192 try!(self.write_packet(packet));
193 self.read_packet_reply()
194 }
195
196 fn make_request<T>(&mut self, procedure: request::remote_procedure, payload: T) -> request::LibvirtMessage<T> {
197 use std::default::Default;
198 let serial = self.serial();
199
200 LibvirtMessage {
201 header: request::virNetMessageHeader {
202 serial: serial,
203 proc_: procedure as i32,
204 ..Default::default()
205 },
206 payload: payload,
207 }
208 }
209
210 pub fn auth(&mut self) -> Result<AuthListResponse, LibvirtError> {
211 use request::remote_procedure::*;
212 let req = self.make_request(REMOTE_PROC_AUTH_LIST, AuthListRequest::new());
213 self.request(req)
214 }
215
216 pub fn open(&mut self) -> Result<ConnectOpenResponse, LibvirtError> {
217 use request::remote_procedure::*;
218 let req = self.make_request(REMOTE_PROC_CONNECT_OPEN, ConnectOpenRequest::new());
219 self.request(req)
220 }
221
222 pub fn version(&mut self) -> Result<(u32, u32, u32), LibvirtError> {
223 use request::remote_procedure::*;
224 let req = self.make_request(REMOTE_PROC_CONNECT_GET_LIB_VERSION, GetLibVersionRequest::new());
225
226 let pkt: GetLibVersionResponse = try!(self.request(req));
227
228 Ok(pkt.version())
229 }
230
231 pub fn list_defined_domains(&mut self) -> Result<Vec<String>, LibvirtError> {
232 use request::remote_procedure::*;
233 let req = self.make_request(REMOTE_PROC_CONNECT_LIST_DEFINED_DOMAINS, ListDefinedDomainsRequest::new());
234
235 let pkt: ListDefinedDomainsResponse = try!(self.request(req));
236 let names = pkt.get_domain_names();
237 Ok(names)
238 }
239
240 pub fn define(&mut self, xml: &str) -> Result<Domain, LibvirtError> {
241 use request::remote_procedure::*;
242 let req = self.make_request(REMOTE_PROC_DOMAIN_DEFINE_XML_FLAGS, DomainDefineXMLRequest::new(xml, 1));
243
244 let pkt: DomainDefineXMLResponse = try!(self.request(req));
245 let dom = pkt.get_domain();
246 Ok(dom)
247 }
248
249 pub fn undefine(&mut self, dom: Domain) -> Result<DomainUndefineResponse, LibvirtError> {
250 use request::remote_procedure::*;
251 let req = self.make_request(REMOTE_PROC_DOMAIN_UNDEFINE_FLAGS, DomainUndefineRequest::new(dom, 0));
252
253 self.request(req)
254 }
255
256 pub fn start(&mut self, dom: Domain) -> Result<Domain, LibvirtError> {
257 use request::remote_procedure::*;
258 let req = self.make_request(REMOTE_PROC_DOMAIN_CREATE_WITH_FLAGS, DomainCreateRequest::new(dom, DomainCreateFlags::DomainCreateFlags::empty()));
259
260 let pkt: DomainCreateResponse = try!(self.request(req));
261 let dom = pkt.get_domain();
262 Ok(dom)
263 }
264}
265#[cfg(test)]
266mod tests {
267 }