Skip to content

Commit

Permalink
Merge pull request #26 from oskardotglobal/rewrite
Browse files Browse the repository at this point in the history
Creating and running the VM via quickemu
  • Loading branch information
oskardotglobal authored Oct 9, 2023
2 parents cd5c0f1 + 00b814a commit d2bc015
Show file tree
Hide file tree
Showing 6 changed files with 325 additions and 25 deletions.
110 changes: 110 additions & 0 deletions scripts/install_quickemu
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env python3

import platform
import os
import shutil
import sys


def _(c: str):
"""Execute the command `c` and print it"""
print("> " + c)
os.system(c)


def clone_repo():
if os.path.exists(os.path.expanduser("~/.local/share/quickemu")):
print("📦 quickemu is already installed. Updating...")
update_quickemu()
return

print("📦 Cloning quickemu...")

_("git clone --filter=blob:none https://github.com/quickemu-project/quickemu ~/.local/share/quickemu")
_("mkdir -p ~/.local/bin")
_("ln -s ~/.local/share/quickemu/quickemu ~/.local/bin/quickemu")
_("ln -s ~/.local/share/quickemu/macrecovery ~/.local/bin/macrecovery")
_("ln -s ~/.local/share/quickemu/quickget ~/.local/bin/quickget")
_("ln -s ~/.local/share/quickemu/windowskey ~/.local/bin/windowskey")

print("Installation complete.")
print("⚠️ Make sure ~/.local/bin is in your PATH.")


def update_quickemu():
print("📦 Updating quickemu...")

_("cd ~/.local/share/quickemu")
_("git pull")

print("Update complete.")
print("⚠️ Make sure ~/.local/bin is in your PATH.")


def install_fedora():
print("📦 Installing dependencies...")

_("sudo dnf install qemu bash coreutils edk2-tools grep jq lsb procps python3 genisoimage usbutils"
+ " util-linux sed spice-gtk-tools swtpm wget xdg-user-dirs xrandr unzip socat -y")

clone_repo()

sys.exit(0)


def install_deb():
print("📦 Installing dependencies...")

_("sudo apt update")
_("sudo apt install qemu bash coreutils ovmf grep jq lsb-base procps python3 genisoimage usbutils"
+ " util-linux sed spice-client-gtk libtss2-tcti-swtpm0 wget xdg-user-dirs zsync unzip socat -y")

clone_repo()

sys.exit(0)


def install_ubuntu():
print("⚠️ Adding ppa...")

_("sudo apt-add-repository ppa:flexiondotorg/quickemu")
_("sudo apt update")
_("sudo apt install quickemu -y")

sys.exit(0)


if __name__ == "__main__":
print("⚠️ This script requires elevated privileges (sudo). You will be asked for your password.")

os_release = platform.freedesktop_os_release()

distro_id = os_release.get("ID_LIKE")
distro_id_like = os_release.get("ID")

if not distro_id and not distro_id_like:
print("❌ Couldn't fetch distro, is os-release installed?")

if distro_id == "ubuntu" \
or distro_id_like == "ubuntu":
install_ubuntu()
elif distro_id == "debian" \
or distro_id_like == "debian" \
or shutil.which("apt"):
install_deb()
elif distro_id == "fedora" \
or distro_id_like == "fedora" \
or shutil.which("dnf"):
install_fedora()
else:
if distro_id:
print("❌ Unsupported distro: ", distro_id)
elif distro_id_like:
print("❌ Unsupported distro: ", distro_id_like)
else:
print("❌ Unsupported distro. Couldn't fetch data from os-release and couldn't find dnf or apt on PATH.")

sys.exit(1)

print("❌ Unsupported platform.")
sys.exit(1)
46 changes: 40 additions & 6 deletions winapps-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use clap::Command;
use winapps::RemoteClient;
use winapps::freerdp::freerdp_back::Freerdp;
use winapps::quickemu::{create_vm, kill_vm, start_vm};
use winapps::RemoteClient;

fn cli() -> Command {
Command::new("winapps-cli")
Expand All @@ -10,27 +11,60 @@ fn cli() -> Command {
.allow_external_subcommands(true)
.subcommand(Command::new("check").about("Checks remote connection"))
.subcommand(Command::new("connect").about("Connects to remote"))
.subcommand(
Command::new("vm")
.about("Manage a windows 10 vm using quickemu")
.subcommand_required(true)
.arg_required_else_help(true)
.allow_external_subcommands(true)
.subcommand(Command::new("create").about("Create a windows 10 vm using quickget"))
.subcommand(Command::new("start").about("Start the vm"))
.subcommand(Command::new("kill").about("Kill the running VM")),
)
}

fn main() {
let cli = cli();
let matches = cli.clone().get_matches();

let client: &dyn RemoteClient = &Freerdp{};
let config = winapps::load_config(None);
let client: &dyn RemoteClient = &Freerdp {};

match matches.subcommand() {
Some(("check", _)) => {
println!("Checking remote connection");

let config = winapps::load_config(None);
client.check_depends(config);
}
Some(("connect", _)) => {
println!("Connecting to remote");

let config = winapps::load_config(None);
client.run_app(config, "explorer");
}

Some(("vm", command)) => {
match command.subcommand() {
Some(("create", _)) => {
println!("Creating windows 10 vm..");
create_vm(config);
}
Some(("start", _)) => {
println!("Starting vm..");
start_vm(config);
}

Some(("kill", _)) => {
println!("Killing vm..");
kill_vm(config);
}

Some((_, _)) => {
cli.about("Command not found, try existing ones!")
.print_help()
.expect("Couldn't print help");
}
_ => unreachable!(),
};
}

Some((_, _)) => {
cli.about("Command not found, try existing ones!")
.print_help()
Expand Down
1 change: 1 addition & 0 deletions winapps/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ edition = "2021"

[dependencies]
derive-new = "0.5.9"
home = "0.5.5"
serde = { version = "1.0.171", features = ["derive"] }
toml = "0.7.6"
11 changes: 6 additions & 5 deletions winapps/src/freerdp.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
pub mod freerdp_back {
use std::process::{Command, Stdio};

use crate::{RemoteClient, Config};
use crate::{Config, RemoteClient};

pub struct Freerdp {}

impl RemoteClient for Freerdp {
fn check_depends(&self, _config: Config) {

let mut xfreerdp = Command::new("xfreerdp");
xfreerdp.stdout(Stdio::null());
xfreerdp.args(["-h"]);
xfreerdp.spawn().expect("Freerdp execution failed! It needs to be installed!");
xfreerdp
.spawn()
.expect("Freerdp execution failed! It needs to be installed!");
println!("Freerdp found!");

println!("Checks success!");
}

fn run_app(&self, config: Config, _app: &str) {
fn run_app(&self, _config: Config, _app: &str) {
todo!()
}
}
Expand Down
93 changes: 79 additions & 14 deletions winapps/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
pub mod quickemu;

use derive_new::new;
use home::home_dir;
use serde::{Deserialize, Serialize};
use std::io::Write;
use std::path::PathBuf;
use std::{
env,
fs::{self, File},
Expand All @@ -21,6 +25,16 @@ pub struct Config {
host: HostConfig,
#[new(value = "RemoteConfig::new()")]
rdp: RemoteConfig,
#[new(value = "VmConfig::new()")]
vm: VmConfig,
}

#[derive(new, Debug, Deserialize, Serialize)]
pub struct VmConfig {
#[new(value = "\"windows-10\".to_string()")]
short_name: String,
#[new(value = "\"windows-10-22H2\".to_string()")]
name: String,
}

#[derive(new, Debug, Deserialize, Serialize)]
Expand All @@ -41,35 +55,86 @@ pub struct RemoteConfig {
password: String,
}

pub fn load_config(path: Option<&str>) -> Config {
let config = env::var("XDG_CONFIG_HOME").expect("Could not find the home path!");
let default = &format!("{}{}", config, "/winapps/");
let path = Path::new(path.unwrap_or(default));
let config = Config::new();
pub fn get_config_file(path: Option<&str>) -> PathBuf {
let default = match env::var("XDG_CONFIG_HOME") {
Ok(dir) => PathBuf::from(dir).join("winapps"),
Err(_) => {
println!("Couldn't read XDG_CONFIG_HOME, falling back to ~/.config");
home_dir()
.expect("Could not find the home path!")
.join(".config/winapps")
}
};

let path = Path::new(path.unwrap_or(default.to_str().unwrap()));

if !path.exists() {
println!("{:?} does not exist! Creating...", path.to_str());
println!("{:?} does not exist! Creating...", path);
fs::create_dir_all(path).expect("Failed to create directory");
}

let config_file = path.join("config.toml");
if !path.is_dir() {
panic!("Config directory {:?} is not a directory!", path);
}

path.join("config.toml")
}

if !config_file.exists() {
let mut config_file =
File::create(&config_file).expect("Failed to create configuration file");
pub fn load_config(path: Option<&str>) -> Config {
let config = Config::new();
let config_path = get_config_file(path);

let gen_config =
toml::to_string(&config).expect("Failed to generate default configuration");
write!(config_file, "{}", gen_config).expect("Failed to write configuration file");
if !config_path.exists() {
save_config(&config, path).expect("Failed to write default configuration");
return config;
}

let config_file = fs::read_to_string(config_file).expect("Failed to read configuration file");
let config_file = fs::read_to_string(config_path).expect("Failed to read configuration file");
let config: Config =
toml::from_str(config_file.as_str()).expect("Failed to parse the configuration");

config
}

pub fn save_config(config: &Config, path: Option<&str>) -> std::io::Result<()> {
let config_path = get_config_file(path);
let serialized_config = toml::to_string(&config).expect("Failed to serialize configuration");

let mut config_file = match config_path.exists() {
true => File::open(&config_path).expect("Failed to open configuration file"),
false => File::create(&config_path).expect("Failed to create configuration file"),
};

write!(config_file, "{}", serialized_config)
}

pub fn get_data_dir() -> PathBuf {
let data_dir = match env::var("XDG_DATA_HOME") {
Ok(dir) => PathBuf::from(dir).join("winapps"),
Err(_) => {
println!("Couldn't read XDG_DATA_HOME, falling back to ~/.local/share");
home_dir()
.expect("Could not find the home path!")
.join(".local/share/winapps")
}
};

if !data_dir.exists() {
let dir = data_dir.clone();
println!(
"Data directory {:?} does not exist! Creating...",
dir.to_str()
);
fs::create_dir_all(dir).expect("Failed to create directory");
}

if !data_dir.is_dir() {
panic!("Data directory {:?} is not a directory!", data_dir);
}

data_dir
}

pub fn add(left: usize, right: usize) -> usize {
left + right
}
Loading

0 comments on commit d2bc015

Please sign in to comment.