Mercurial > hg > Members > anatofuz > ie-virsh
changeset 19:d37203a877d9
add xml parse/writer
author | AnaTofuZ <k198584@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 03 Nov 2020 11:10:24 +0900 |
parents | 9b24d6767a2f |
children | da4858f4658d |
files | Cargo.lock Cargo.toml src/command.rs src/lib.rs src/main.rs src/xml.rs |
diffstat | 6 files changed, 255 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/Cargo.lock Mon Nov 02 18:59:52 2020 +0900 +++ b/Cargo.lock Tue Nov 03 11:10:24 2020 +0900 @@ -68,6 +68,17 @@ ] [[package]] +name = "getrandom" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] name = "hashbrown" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -98,6 +109,9 @@ "clap", "libc", "nix", + "quick-xml", + "rand", + "uuid", ] [[package]] @@ -123,6 +137,12 @@ checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743" [[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] name = "nix" version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -141,6 +161,12 @@ checksum = "2ac6fe3538f701e339953a3ebbe4f39941aababa8a3f6964635b24ab526daeac" [[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -174,6 +200,15 @@ ] [[package]] +name = "quick-xml" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26aab6b48e2590e4a64d1ed808749ba06257882b461d01ca71baeb747074a6dd" +dependencies = [ + "memchr", +] + +[[package]] name = "quote" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -183,6 +218,47 @@ ] [[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + +[[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -236,6 +312,15 @@ checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] +name = "uuid" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" +dependencies = [ + "rand", +] + +[[package]] name = "vec_map" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -248,6 +333,12 @@ checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" [[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index"
--- a/Cargo.toml Mon Nov 02 18:59:52 2020 +0900 +++ b/Cargo.toml Tue Nov 03 11:10:24 2020 +0900 @@ -10,6 +10,9 @@ nix = "0.19.0" libc = "0.2.77" clap = "3.0.0-beta.2" +quick-xml = "0.20.0" +uuid = { version = "0.8", features = ["v4"] } +rand = "0.7" [profile.release] codegen-units = 1
--- a/src/command.rs Mon Nov 02 18:59:52 2020 +0900 +++ b/src/command.rs Tue Nov 03 11:10:24 2020 +0900 @@ -1,4 +1,5 @@ use super::virsh; +use super::xml; pub fn list(user_name: &'static str) { let (ldump_msg, vm_list_strs) = virsh::get_vm_list(user_name); @@ -9,6 +10,10 @@ } } +pub fn define(user_name: &'static str, vm_name: String) { + xml::generate(); +} + pub fn start(user_name: &'static str, vm_name: String) { virsh::command_require_vm_name(get_vm_name(user_name, &vm_name), "start"); } @@ -41,6 +46,13 @@ exec_cmd_from_name_or_id(user_name, &vm_name, "undefine") } +pub fn domiflist(user_name: &'static str, vm_name: String) { + exec_cmd_from_name_or_id(user_name, &vm_name, "domiflist") +} + +pub fn dominfo(user_name: &'static str, vm_name: String) { + exec_cmd_from_name_or_id(user_name, &vm_name, "dominfo") +} fn exec_cmd_from_name_or_id(user_name: &'static str, name_or_id: &str, command: &str) { if name_or_id.parse::<u8>().is_ok() {
--- a/src/lib.rs Mon Nov 02 18:59:52 2020 +0900 +++ b/src/lib.rs Tue Nov 03 11:10:24 2020 +0900 @@ -1,3 +1,4 @@ pub mod command; pub mod user; pub mod virsh; +pub mod xml;
--- a/src/main.rs Mon Nov 02 18:59:52 2020 +0900 +++ b/src/main.rs Tue Nov 03 11:10:24 2020 +0900 @@ -21,6 +21,8 @@ VNCDisplay(VNCDisplay), DumpXML(DumpXML), DefineGDB(DefineGDB), + DomIfList(DomIfList), + DomInfo(DomInfo), } /// define the domain in which the gdb port is opened from the template XML file @@ -87,6 +89,18 @@ name: String, } +/// list all domain virtual interfaces +#[derive(Clap)] +struct DomIfList { + name: String, +} + +/// domain information +#[derive(Clap)] +struct DomInfo { + name: String, +} + fn main() { let opts: Opts = Opts::parse(); @@ -143,9 +157,16 @@ command::undefine(user_name, arg.name); } + SubCommand::DomIfList(arg) => { + user::set_root_id(); + command::domiflist(user_name, arg.name); + } + + SubCommand::DomInfo(arg) => { + user::set_root_id(); + command::dominfo(user_name, arg.name); + } + _ => {} } - - //set_root_id(); - //list_command(user_name); -} \ No newline at end of file +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xml.rs Tue Nov 03 11:10:24 2020 +0900 @@ -0,0 +1,123 @@ +use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event}; +use quick_xml::{Reader, Writer}; +use rand::Rng; +use std::fs::File; +use std::io::{BufReader, BufWriter, Error, ErrorKind}; +use std::path::Path; +use uuid::Uuid; + +const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz\ + 0123456789)(*&^%$#@!~"; + +const PASSWORD_LEN: usize = 30; + +const DOMAIN_XMLNS_QEMU: (&str, &str) = + ("xmlns:qemu", "http://libvirt.org/schemas/domain/qemu/1.0"); + +const IE_VIRSH_TEMPLATE_VM_NAME: &[u8; 17] = b"ie-virsh-template"; +const VNC_XML_TAG: &[u8; 8] = b"graphics"; + +const ROOT_START_TAG: &[u8; 6] = b"domain"; + +const QEMU_COMMAND_LINE_TAG: &[u8; 16] = b"qemu:commandline"; +const QEMU_ARG_TAG: &[u8; 8] = b"qemu:arg"; + +pub fn generate() -> Result<(), Error> { + let is_debug = true; + + let file = "./template.xml"; + let mut reader = Reader::from_reader(BufReader::new(get_xml_from_file(file)?)); + let mut writer = Writer::new(BufWriter::new(File::create("dump.xml").unwrap())); + let mut buf = Vec::new(); + loop { + match reader.read_event(&mut buf) { + Ok(Event::Start(ref e)) if e.name() == b"uuid" => { + writer + .write_event(Event::Start(e.clone())) + .expect("faild write event"); + reader + .read_event(&mut Vec::new()) + .expect("faild read event"); + let vm_uuid = Uuid::new_v4().to_string(); + let elem = BytesText::from_plain_str(&vm_uuid); + writer.write_event(Event::Text(elem)).unwrap(); + } + + Ok(Event::Start(ref e)) if (e.name() == ROOT_START_TAG && is_debug) => { + let mut elem = e.clone(); + elem.push_attribute(DOMAIN_XMLNS_QEMU); + writer.write_event(Event::Start(elem)).unwrap(); + + let qemu_command_line_start = BytesStart::borrowed_name(QEMU_COMMAND_LINE_TAG); + writer + .write_event(Event::Start(qemu_command_line_start)) + .unwrap(); + + for value in ["-S", "-gdb", "tcp"].iter() { + let mut qemu_elem = BytesStart::borrowed_name(QEMU_ARG_TAG); + let v: &str = &value; + qemu_elem.push_attribute(("value", v)); + writer.write_event(Event::Empty(qemu_elem)).unwrap(); + } + + let qemu_command_line_end = BytesEnd::borrowed(QEMU_COMMAND_LINE_TAG); + writer + .write_event(Event::End(qemu_command_line_end)) + .unwrap(); + } + + Ok(Event::Empty(ref e)) if e.name() == VNC_XML_TAG => { + let mut elem = e.clone(); + let pw: &str = &generate_pw(); + elem.push_attribute(("passwd", pw)); + writer.write_event(Event::Empty(elem)).ok(); + } + + Ok(Event::Empty(ref e)) if (e.name() == b"source") => { + let mut elem = e.clone(); + let is_qcow_file = elem + .attributes() + .find(|attr| attr.as_ref().unwrap().key == b"file"); + if is_qcow_file.is_some() { + elem.clear_attributes(); + elem.push_attribute(("file", "qcow")); + } + writer.write_event(Event::Empty(elem)).ok(); + } + + Ok(Event::Text(ref e)) if e.escaped() == IE_VIRSH_TEMPLATE_VM_NAME => { + let elem = BytesText::from_plain_str("anatofuz-vm"); + writer.write_event(Event::Text(elem)).unwrap(); + } + Ok(Event::Eof) => break, + // you can use either `e` or `&e` if you don't want to move the event + Ok(e) => assert!(writer.write_event(&e).is_ok()), + Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e), + } + buf.clear(); + } + Ok(()) +} + +fn get_xml_from_file(source: &str) -> Result<File, Error> { + let local_path = Path::new(source); + + if local_path.is_file() { + let file = File::open(local_path)?; + return Ok(file); + } + + Err(Error::new(ErrorKind::Other, "failed ...")) +} + +fn generate_pw() -> String { + let mut rng = rand::thread_rng(); + + (0..PASSWORD_LEN) + .map(|_| { + let idx = rng.gen_range(0, CHARSET.len()); + CHARSET[idx] as char + }) + .collect() +}