Browse Source

Streamline node_js_user_service

master
Adrian Heine 8 years ago
parent
commit
2c7b5bd865
  1. 98
      src/symbols/systemd/node_js_user_service.rs

98
src/symbols/systemd/node_js_user_service.rs

@ -2,9 +2,8 @@ use std::error::Error;
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::fmt; use std::fmt;
use std::io; use std::io;
use std::fs;
use std::fs::{self, Metadata};
use std::process::Output; use std::process::Output;
use std::path::Path;
use std::thread::sleep; use std::thread::sleep;
use std::time::Duration; use std::time::Duration;
use std::ops::Deref; use std::ops::Deref;
@ -53,19 +52,16 @@ impl<E: Error> fmt::Display for NodeJsSystemdUserServiceError<E> {
} }
} }
pub struct NodeJsSystemdUserService<'a, P, C> where P: AsRef<str> + fmt::Display, C: Deref<Target=str> {
name: &'a str,
pub struct NodeJsSystemdUserService<'a, C> where C: Deref<Target=str> {
service_name: &'a str,
user_name: &'a str, user_name: &'a str,
path: P,
command_runner: &'a CommandRunner, command_runner: &'a CommandRunner,
file: FileSymbol<C, Cow<'a, str>>
file: FileSymbol<C, String>
} }
use std::borrow::Cow;
impl<'a> NodeJsSystemdUserService<'a, Cow<'a, str>, String> {
impl<'a> NodeJsSystemdUserService<'a, String> {
pub fn new(home: &'a str, user_name: &'a str, name: &'a str, path: &'a str, command_runner: &'a CommandRunner) -> Self { pub fn new(home: &'a str, user_name: &'a str, name: &'a str, path: &'a str, command_runner: &'a CommandRunner) -> Self {
let file_path: Cow<str> = Cow::from(String::from(home.trim_right()) + "/.config/systemd/user/" + name + ".service");
let file_path = format!("{}/.config/systemd/user/{}.service", home.trim_right(), name);
let content = format!("[Service] let content = format!("[Service]
ExecStartPre=rm /var/tmp/{1}-{2}.socket ExecStartPre=rm /var/tmp/{1}-{2}.socket
@ -81,21 +77,21 @@ Environment=PORT=/var/tmp/{1}-{2}.socket
[Install] [Install]
WantedBy=default.target WantedBy=default.target
", path, user_name, name); ", path, user_name, name);
NodeJsSystemdUserService { NodeJsSystemdUserService {
name: name,
service_name: name,
user_name: user_name, user_name: user_name,
path: file_path.clone(),
command_runner: command_runner, command_runner: command_runner,
file: FileSymbol::new(file_path, content) file: FileSymbol::new(file_path, content)
} }
} }
} }
impl<'a, P, C> NodeJsSystemdUserService<'a, P, C> where P: AsRef<str> + fmt::Display, C: Deref<Target=str> {
impl<'a, C> NodeJsSystemdUserService<'a, C> where C: Deref<Target=str> {
fn check_if_service(&self) -> Result<bool, Box<Error>> { fn check_if_service(&self) -> Result<bool, Box<Error>> {
loop { loop {
// Check if service is registered // Check if service is registered
let active_state = try!(self.command_runner.run_with_args("systemctl", &["--user", "show", "--property", "ActiveState", self.name]));
let active_state = try!(self.command_runner.run_with_args("systemctl", &["--user", "show", "--property", "ActiveState", self.service_name]));
if !active_state.status.success() { if !active_state.status.success() {
return Err(String::from_utf8(active_state.stderr).unwrap().trim_right().into()); return Err(String::from_utf8(active_state.stderr).unwrap().trim_right().into());
} }
@ -103,62 +99,60 @@ impl<'a, P, C> NodeJsSystemdUserService<'a, P, C> where P: AsRef<str> + fmt::Dis
match String::from_utf8(active_state.stdout).unwrap().trim_right() { match String::from_utf8(active_state.stdout).unwrap().trim_right() {
"ActiveState=activating" => sleep(Duration::from_millis(500)), "ActiveState=activating" => sleep(Duration::from_millis(500)),
"ActiveState=active" => return Ok(true), "ActiveState=active" => return Ok(true),
"ActiveState=failed" => return Err(Box::new(NodeJsSystemdUserServiceError::ActivationFailed(self.command_runner.run_with_args("journalctl", &["--user", &format!("--user-unit={}", self.name)])) as NodeJsSystemdUserServiceError<io::Error>)),
"ActiveState=failed" => return Err(Box::new(NodeJsSystemdUserServiceError::ActivationFailed(self.command_runner.run_with_args("journalctl", &["--user", &format!("--user-unit={}", self.service_name)])) as NodeJsSystemdUserServiceError<io::Error>)),
_ => return Ok(false) _ => return Ok(false)
} }
} }
} }
} }
impl<'a, P, C> Symbol for NodeJsSystemdUserService<'a, P, C> where P: AsRef<str> + fmt::Display, C: Deref<Target=str> {
fn target_reached(&self) -> Result<bool, Box<Error>> {
match self.file.target_reached() {
Ok(false) => return Ok(false),
Ok(true) => {},
Err(e) => return Err(Box::new(NodeJsSystemdUserServiceError::GenericError as NodeJsSystemdUserServiceError<io::Error>))
}
/*
if !(try!(self.file.target_reached())) {
return Ok(false)
}
*/
self.check_if_service()
}
fn execute(&self) -> Result<(), Box<Error>> {
match self.file.execute() {
Ok(_) => {},
Err(e) => return Err(e)
}
try!(self.command_runner.run_with_args("systemctl", &["--user", "enable", self.name]));
try!(self.command_runner.run_with_args("systemctl", &["--user", "start", self.name]));
if !(try!(self.check_if_service())) { return Err(Box::new(NodeJsSystemdUserServiceError::GenericError as NodeJsSystemdUserServiceError<io::Error>)); }
let file_name = format!("/var/tmp/{}-{}.socket", self.user_name, self.name);
// try!(self.command_runner.run_with_args("chmod", &["666", &file_name]));
fn wait_for_metadata(file_name: &str) -> Result<Metadata, Box<Error>> {
let result;
let mut tries = 5; let mut tries = 5;
loop { loop {
let metadata = fs::metadata(file_name.clone()); let metadata = fs::metadata(file_name.clone());
match metadata { match metadata {
Ok(metadata) => { Ok(metadata) => {
let mut perms = metadata.permissions();
perms.set_mode(0o666);
try!(fs::set_permissions(file_name, perms));
result = metadata;
break; break;
}, },
Err(e) => { Err(e) => {
if e.kind() == io::ErrorKind::NotFound {
if e.kind() != io::ErrorKind::NotFound {
return Err(Box::new(e));
}
}
}
tries -= 1; tries -= 1;
if tries == 0 { return Err("Gave up waiting for socket to appear".to_string().into()); }
if tries == 0 {
return Err("Gave up waiting for socket to appear".to_string().into());
}
sleep(Duration::from_millis(500)); sleep(Duration::from_millis(500));
} else {
return Err(Box::new(e));
} }
Ok(result)
} }
impl<'a, C> Symbol for NodeJsSystemdUserService<'a, C> where C: Deref<Target=str> {
fn target_reached(&self) -> Result<bool, Box<Error>> {
if !(try!(self.file.target_reached())) {
return Ok(false);
} }
self.check_if_service()
} }
fn execute(&self) -> Result<(), Box<Error>> {
try!(self.file.execute());
try!(self.command_runner.run_with_args("systemctl", &["--user", "enable", self.service_name]));
try!(self.command_runner.run_with_args("systemctl", &["--user", "start", self.service_name]));
if !(try!(self.check_if_service())) {
return Err(Box::new(NodeJsSystemdUserServiceError::GenericError as NodeJsSystemdUserServiceError<io::Error>));
}
let file_name = format!("/var/tmp/{}-{}.socket", self.user_name, self.service_name);
let metadata = try!(wait_for_metadata(&file_name));
let mut perms = metadata.permissions();
perms.set_mode(0o666);
try!(fs::set_permissions(file_name, perms));
Ok(()) Ok(())
} }
@ -169,8 +163,8 @@ impl<'a, P, C> Symbol for NodeJsSystemdUserService<'a, P, C> where P: AsRef<str>
} }
} }
impl<'a, P, C> fmt::Display for NodeJsSystemdUserService<'a, P, C> where P: AsRef<str> + fmt::Display, C: Deref<Target=str> {
impl<'a, C> fmt::Display for NodeJsSystemdUserService<'a, C> where C: Deref<Target=str> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error>{ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error>{
write!(f, "Systemd Node.js user service unit for {}", self.path)
write!(f, "Systemd Node.js user service unit for {}", self.service_name)
} }
} }
Loading…
Cancel
Save