Mercurial > hg > Members > anatofuz > ie-virsh
changeset 39:f667f3a4bbee
backing file cmd
author | AnaTofuZ <anatofuz@gmail.com> |
---|---|
date | Sun, 22 Nov 2020 15:47:37 +0900 |
parents | 6f1b90844b7f |
children | d3055f6c6fb7 |
files | src/command.rs src/main.rs src/virsh.rs src/xml.rs |
diffstat | 4 files changed, 81 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/src/command.rs Sun Nov 22 11:21:18 2020 +0900 +++ b/src/command.rs Sun Nov 22 15:47:37 2020 +0900 @@ -25,31 +25,47 @@ pub fn define(user: &user::User, vm_name: &str) { let vm_name = generate_vm_name(&user.name, &vm_name); - let vm_xml = xml::Builder::new(&user.name, &vm_name).finalize(); - if let Ok(xml_path) = vm_xml.generate() { - virsh::command_require_vm_name(xml_path, "define") + let builder = xml::Builder::new(&user.name, &vm_name).finalize(); + if let Ok(xml_path) = builder.generate() { + virsh::command_require_vm_name(&xml_path, "define") + } +} + +pub fn define_from_template(user: &user::User, vm_name: &str, template: &str) { + let vm_name = generate_vm_name(&user.name, &vm_name); + let template_path = match virsh::get_template_path(template) { + Some(path) => path, + None => { + println!("not found {}", template); + return; + } + }; + let builder = xml::Builder::new(&user.name, &vm_name) + .backing(&template_path) + .finalize(); + if let Ok(xml_path) = builder.generate() { + virsh::command_require_vm_name(&xml_path, "define") } } pub fn start(user_name: &str, vm_name: &str) { - virsh::command_require_vm_name(get_vm_name(user_name, vm_name), "start"); + virsh::command_require_vm_name(&get_vm_name(user_name, vm_name), "start"); } pub fn common(user_name: &str, vm_name: &str, command: &str) { exec_cmd_from_name_or_id(user_name, vm_name, command) } - pub fn dumpvncpasswd(_user_name: &str, _vm_name: &str) {} fn exec_cmd_from_name_or_id(user_name: &str, name_or_id: &str, command: &str) { if name_or_id.parse::<u8>().is_ok() { let vm_name_or_none = get_vm_name_from_id(user_name, &name_or_id); if let Some(vm_name) = vm_name_or_none { - return virsh::command_require_vm_name(vm_name, command); + return virsh::command_require_vm_name(&vm_name, command); } } - virsh::command_require_vm_name(get_vm_name(user_name, name_or_id), command); + virsh::command_require_vm_name(&get_vm_name(user_name, name_or_id), command); } fn get_vm_name_from_id(user_name: &str, arg_id: &str) -> Option<String> {
--- a/src/main.rs Sun Nov 22 11:21:18 2020 +0900 +++ b/src/main.rs Sun Nov 22 15:47:37 2020 +0900 @@ -40,6 +40,9 @@ #[derive(Clap)] struct Define { name: String, + /// A level of verbosity, and can be used multiple times + #[clap(short, long, parse(from_str))] + template: Option<String>, } /// domain information in XML @@ -132,6 +135,11 @@ gid, name: user_name, }; + + if let Some(template) = arg.template { + command::define_from_template(&user, &arg.name, &template); + return; + } command::define(&user, &arg.name); }
--- a/src/virsh.rs Sun Nov 22 11:21:18 2020 +0900 +++ b/src/virsh.rs Sun Nov 22 15:47:37 2020 +0900 @@ -2,10 +2,12 @@ use std::process::Command; use std::fs; +use std::path::Path; const TEMPLATE_DIR: &str = "/ie-ryukyu/kvm/images/templates/"; const TEMPLATE_SUFFIX: &str = "template-"; const TEMPLATE_FILE_EXTENSION: &str = ".qcow2"; +const QCOW2: &str = "qcow2"; pub struct ListDumpMsg { pub info_msg: String, @@ -55,7 +57,7 @@ ) } -pub fn command_require_vm_name(vm_name: String, operation: &str) { +pub fn command_require_vm_name(vm_name: &str, operation: &str) { let output = Command::new("virsh") .arg(operation) .arg(vm_name) @@ -65,3 +67,35 @@ io::stdout().write_all(&output.stdout).unwrap(); io::stderr().write_all(&output.stderr).unwrap(); } + +pub fn generate_qemu_from_template(vm_name: &str, template_path: &str) { + let vm_path = format!( + "{}{}{}{}", + TEMPLATE_DIR, TEMPLATE_SUFFIX, &vm_name, TEMPLATE_FILE_EXTENSION + ); + //$qemu-img create -F qcow2 -b ibm-master.qcow2 -f qcow2 ibm-02.qcow2 + let output = Command::new("qemu-img") + .arg("create") + .arg("-F") + .arg(QCOW2) + .arg("-b") + .arg(template_path) + .arg("-f") + .arg(QCOW2) + .arg(vm_path) + .output() + .unwrap_or_else(|_| panic!("failed to generate {}", &vm_name)); + io::stdout().write_all(&output.stdout).unwrap(); + io::stderr().write_all(&output.stderr).unwrap(); +} + +pub fn get_template_path(template_name: &str) -> Option<String> { + let template_path = format!( + "{}{}{}{}", + TEMPLATE_DIR, TEMPLATE_SUFFIX, &template_name, TEMPLATE_FILE_EXTENSION + ); + if Path::new(&template_path).exists() { + return Some(template_path); + } + None +}
--- a/src/xml.rs Sun Nov 22 11:21:18 2020 +0900 +++ b/src/xml.rs Sun Nov 22 15:47:37 2020 +0900 @@ -54,7 +54,8 @@ user_name: String, vm_name: String, debug_tcp_port: Option<u64>, - backing_file: Option<String>, + backing_file: String, + is_backing: bool, } pub struct GenerateVM { @@ -63,7 +64,8 @@ xml_path: String, vnc_password: String, debug_tcp_port: Option<u64>, - backing_file: Option<String>, + backing_file: String, + is_backing: bool, } impl Builder { @@ -72,7 +74,8 @@ user_name: user_name.to_string(), vm_name: vm_name.to_string(), debug_tcp_port: None, - backing_file: None, + backing_file: "".to_string(), + is_backing: false, } } @@ -81,12 +84,12 @@ self } - pub fn backing(&mut self, backing_file: Option<String>) -> &mut Builder { - self.backing_file = backing_file; + pub fn backing(&mut self, backing_file: &str) -> &mut Builder { + self.backing_file = backing_file.to_string(); self } - pub fn finalize(self) -> GenerateVM { + pub fn finalize(&self) -> GenerateVM { let year = self.user_name.chars().skip(1).take(2).collect::<String>(); let affilication = if year.parse::<u8>().is_ok() { // /etc/libvirt/qemu/e19/e195729 @@ -111,13 +114,16 @@ } let pw = generate_pw(); + + GenerateVM { vm_name: self.vm_name.clone(), qcow2_path, xml_path, vnc_password: pw, debug_tcp_port: self.debug_tcp_port, - backing_file: self.backing_file, + backing_file: self.backing_file.clone(), + is_backing: self.is_backing, } } } @@ -183,7 +189,7 @@ } // use template qcow2 - Ok(Event::End(ref e)) if ((e.name() == b"disk") && self.backing_file.is_some()) => { + Ok(Event::End(ref e)) if ((e.name() == b"disk") && self.is_backing) => { let mut backing_store_start = BytesStart::borrowed_name(b"backingStore"); backing_store_start.push_attribute(("type", "file")); backing_store_start.push_attribute(("index", "3")); @@ -199,7 +205,7 @@ writer.write(b"\n").unwrap(); let mut backing_sorce = BytesStart::borrowed_name(b"sorce"); - let backing_file: &str = self.backing_file.as_ref().unwrap(); + let backing_file: &str = &self.backing_file; backing_sorce.push_attribute(("file", backing_file)); writer.write_event(Event::Empty(backing_sorce)).unwrap(); writer.write(b"\n").unwrap();