Skip to content

Commit

Permalink
Major reorganization
Browse files Browse the repository at this point in the history
Hooks are now separated off into their own modules.
This freed up considerable space in the main.rs file
and makes it easier to navigate around.
  • Loading branch information
cholcombe973 committed Mar 27, 2017
1 parent 16f7fb5 commit 22f2d4d
Show file tree
Hide file tree
Showing 12 changed files with 821 additions and 753 deletions.
85 changes: 48 additions & 37 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Expand Up @@ -10,13 +10,13 @@ gluster = "~0.7"
init-daemon = "*"
ipnetwork = "~0.12"
itertools = "*"
juju = "~0.5"
juju = "~0.6"
libc = "*"
libudev = "*"
nix = "*"
nix = "~0.8"
pnet = "~0.16"
rand = "~0.3"
regex = "*"
regex = "~0.1"
resolve = "~0.1"
rustc-serialize = "*"
serde = "^0.9"
Expand Down
Binary file modified hooks/main
Binary file not shown.
13 changes: 13 additions & 0 deletions src/hooks/brick_attached.rs
@@ -0,0 +1,13 @@
extern crate juju;

use std::path::PathBuf;
use super::super::initialize_storage;

pub fn brick_attached() -> Result<(), String> {
let brick_location = juju::storage_get_location().map_err(|e| e.to_string())?;
let brick_path = PathBuf::from(brick_location.trim());

// Format our bricks and mount them
initialize_storage(&brick_path)?;
Ok(())
}
4 changes: 4 additions & 0 deletions src/hooks/brick_detached.rs
@@ -0,0 +1,4 @@
pub fn brick_detached() -> Result<(), String> {
// TODO: Do nothing for now
return Ok(());
}
140 changes: 140 additions & 0 deletions src/hooks/config_changed.rs
@@ -0,0 +1,140 @@
extern crate gluster;
extern crate juju;

use std::fs::File;
use std::path::{Path, PathBuf};
use std::process::Command;

use gluster::volume::*;
use super::super::{create_sysctl, ephemeral_unmount, device_initialized, get_config_value,
get_glusterfs_version, initialize_storage, is_mounted};
use super::super::apt;
use super::super::block;
use super::super::upgrade;

pub fn config_changed() -> Result<(), String> {
// If either of these fail we fail the hook
check_for_new_devices()?;
check_for_upgrade()?;

// If this fails don't fail the hook
if let Err(err) = check_for_sysctl() {
log!(format!("Setting sysctl's failed with error: {}", err),
Error);
}
return Ok(());
}

fn check_for_new_devices() -> Result<(), String> {
log!("Checking for new devices", Info);
let config = juju::Config::new().map_err(|e| e.to_string())?;
if config.changed("brick_devices").map_err(|e| e.to_string())? {
// Get the changed list of brick devices and initialize each one
let brick_paths: Vec<PathBuf> = get_config_value("brick_devices")
.unwrap_or("".to_string())
.split(" ")
.map(|s| s.to_string())
.filter(|s| !s.is_empty())
.map(|s| PathBuf::from(s))
.collect();
// Check for any devices that are mounted and skip those. They're already taken care of
for brick in brick_paths {
if block::is_block_device(&brick).is_err() {
log!(format!("{:?} is not a block device. Skipping.", brick));
continue;
}
// If ephemeral-unmount is set and the directory is mounted we unmount it.
// Otherwise nothing happens
ephemeral_unmount()?; // TODO: Should this fail the hook or just skip?

let brick_filename = match brick.file_name() {
Some(name) => name,
None => {
log!(format!("Unable to determine filename for device: {:?}. Skipping",
brick),
Error);
continue;
}
};
let mount_path = format!("/mnt/{}", brick_filename.to_string_lossy());
log!(format!("Checking if {:?} is mounted", mount_path));
if Path::new(&mount_path).exists() {
match is_mounted(&mount_path) {
Ok(mounted) => {
if mounted {
log!(format!("{:?} is mounted. Skipping", brick), Error);
continue;
}
}
Err(_) => {}
};
}
if !device_initialized(&brick).map_err(|e| e.to_string())? {
log!(format!("Calling initialize_storage for {:?}", brick));
initialize_storage(&brick)?;
}
}
} else {
log!("No new devices found");
}
Ok(())
}

fn check_for_sysctl() -> Result<(), String> {
let config = juju::Config::new().map_err(|e| e.to_string())?;
if config.changed("sysctl").map_err(|e| e.to_string())? {
let config_path = Path::new("/etc/sysctl.d/50-gluster-charm.conf");
let mut sysctl_file = File::create(config_path).map_err(|e| e.to_string())?;
let sysctl_dict = juju::config_get("sysctl").map_err(|e| e.to_string())?;
create_sysctl(sysctl_dict, &mut sysctl_file)?;
// Reload sysctl's
let mut cmd = Command::new("sysctl");
cmd.arg("-p");
cmd.arg(&config_path.to_string_lossy().into_owned());
let output = cmd.output().map_err(|e| e.to_string())?;
if !output.status.success() {
return Err(String::from_utf8_lossy(&output.stderr).into_owned());
}
}
Ok(())
}

// If the config has changed this will initiated a rolling upgrade
fn check_for_upgrade() -> Result<(), String> {
let config = juju::Config::new().map_err(|e| e.to_string())?;
if !config.changed("source").map_err(|e| e.to_string())? {
// No upgrade requested
log!("No upgrade requested");
return Ok(());
}

log!("Getting current_version");
let current_version = get_glusterfs_version()?;

log!("Adding new source line");
let source = juju::config_get("source").map_err(|e| e.to_string())?;
apt::add_source(&source)?;
log!("Calling apt update");
apt::apt_update()?;

log!("Getting proposed_version");
let proposed_version = apt::get_candidate_package_version("glusterfs-server")?;

// Using semantic versioning if the new version is greater than we allow the upgrade
if proposed_version > current_version {
log!(format!("current_version: {}", current_version));
log!(format!("new_version: {}", proposed_version));
log!(format!("{} to {} is a valid upgrade path. Proceeding.",
current_version,
proposed_version));
return upgrade::roll_cluster(&proposed_version);
} else {
// Log a helpful error message
log!(format!("Invalid upgrade path from {} to {}. The new version needs to be \
greater than the old version",
current_version,
proposed_version),
Error);
return Ok(());
}
}
16 changes: 16 additions & 0 deletions src/hooks/fuse_relation_joined.rs
@@ -0,0 +1,16 @@
extern crate gluster;
extern crate juju;

use gluster::volume::volume_list;

pub fn fuse_relation_joined() -> Result<(), String> {
// Fuse clients only need one ip address and they can discover the rest
let public_addr = try!(juju::unit_get_public_addr().map_err(|e| e.to_string())).to_string();
let volumes = volume_list();
juju::relation_set("gluster-public-address", &public_addr).map_err(|e| e.to_string())?;
if let Some(vols) = volumes {
juju::relation_set("volumes", &vols.join(" ")).map_err(|e| e.to_string())?;
}

Ok(())
}

0 comments on commit 22f2d4d

Please sign in to comment.