Commit 5f654613 authored by David's avatar David

Only a bit of work

parent 1f724dca
......@@ -59,6 +59,11 @@ object Main extends App {
networkMountPath = "10.10.220.92:/mnt/OldTank/backupTesting"
)
//TODO: need to do one host backup actor at a time, because reasons
//Need to make that configurable, so it will do the right thing. I wonder if there's a way to handle that
// I don't want it to be a singleton actor, I just only want to run one HostBackupActor at a time
//Execute and wait for termination/completion?
val hostBackupActor = system.actorOf(HostBackupActor.props(smallerHostBackups.head, backupConfig))
//TODO: complete the entire system backup by rclone'ing into the cloud
......
package is.kow.backupcoordinator.actors
import akka.actor.{Actor, ActorLogging, ActorRef, Props, ReceiveTimeout, Terminated}
import is.kow.backupcoordinator.actors.HostBackupActor.EstablishSSHSession
import is.kow.backupcoordinator.actors.SSHCommandActor.{ExecuteCommand, ExecutionCompleted}
import is.kow.backupcoordinator.actors.HostBackupActor.{BackupCompleted, EstablishSSHSession}
import is.kow.backupcoordinator.actors.SSHCommandActor.{ExecuteAsScript, ExecuteCommand, ExecutionCompleted}
import is.kow.backupcoordinator.actors.SSHConnectionActor.Connect
import is.kow.backupcoordinator.{BackupConfiguration, HostBackup}
import net.schmizz.sshj.SSHClient
......@@ -14,6 +14,7 @@ object HostBackupActor {
case class Timeout(kind: String)
case class BackupCompleted(hostBackup: HostBackup)
}
class HostBackupActor(hostBackup: HostBackup, backupConfiguration: BackupConfiguration, statusActor: Option[ActorRef] = None) extends Actor with ActorLogging {
......@@ -120,17 +121,29 @@ class HostBackupActor(hostBackup: HostBackup, backupConfiguration: BackupConfigu
log.error("Pre-backup failed!")
//TODO: need to clean up hard
case ExecutionCompleted(cmd, stdOut, stdErr, status) =>
context.unwatch(cmdActor)
//Completed the call to do pre-backup commands
log.info(s"Pre-Backup command complete! Command Processed ($status): $cmd -- $stdOut | $stdErr")
//Can now execute the actual backup command
doBackup(client, None, backupPaths, postBackup)
}
def awaitingPostBackup(client: SSHClient, cmdActor: ActorRef): Receive = {
case t@Terminated(`cmdActor`) =>
log.error("Post Backup Failed!")
//TODO: RUH ROH
case ExecutionCompleted(cmd, stdOut, stdErr, status) =>
context.unwatch(cmdActor)
log.info(s"Post backup command complete! Command Processed ($status): $cmd -- $stdOut | $stdErr")
doBackup(client, None, List.empty[String], None) //everything should be done now
}
def awaitingBackupDirectory(client: SSHClient, cmdActor: ActorRef, backupPaths: List[String], postBackup: Option[String]): Receive = {
case t@Terminated(`cmdActor`) =>
log.error("Directory backup failed!")
//TODO: need to clean up hard
//TODO: need to clean up hard or do we just bail?
case ExecutionCompleted(cmd, stdOut, stdErr, status) =>
context.unwatch(cmdActor)
//A backup directory is completed!
log.info(s"Directory Backup ${backupPaths.head}: Completed")
log.info(s"BACKUP RESULT: \n$stdOut")
......@@ -140,11 +153,14 @@ class HostBackupActor(hostBackup: HostBackup, backupConfiguration: BackupConfigu
def awaitingUnmount(client: SSHClient, cmdActor: ActorRef): Receive = {
case t@Terminated(`cmdActor`) =>
log.error("unmount failed!")
//TODO: need to clean up hard
//TODO: need to clean up hard or retry, because this is literally the last step!
case ExecutionCompleted(cmd, stdOut, stdErr, status) =>
context.unwatch(cmdActor)
log.info("ALL DONE, closing down")
//Done with this, now we can close our ssh connection
client.close() //Boom!
context.parent ! BackupCompleted(hostBackup)
context.stop(self)
}
......@@ -152,7 +168,8 @@ class HostBackupActor(hostBackup: HostBackup, backupConfiguration: BackupConfigu
if (preBackup.nonEmpty) {
//Do the pre-backup commands, and become awaitingPreBackup
val preBackupCmd = context.actorOf(SSHCommandActor.props(client))
preBackupCmd ! ExecuteCommand(preBackup.get) //TODO: need to do this by dumping it into a shell script, and then executing it
context.watch(preBackupCmd)
preBackupCmd ! ExecuteAsScript(preBackup.get)
//TODO: what's a reasonable time for stopping? Should have some kind of tick to indicate processing
context.become(awaitingPreBackup(client, preBackupCmd, backupPaths, postBackup))
} else if (backupPaths.nonEmpty) {
......@@ -177,16 +194,20 @@ class HostBackupActor(hostBackup: HostBackup, backupConfiguration: BackupConfigu
//backup command created
val backupDirectoryActor = context.actorOf(SSHCommandActor.props(client))
context.watch(backupDirectoryActor)
backupDirectoryActor ! ExecuteCommand(backupCmd)
context.become(awaitingBackupDirectory(client, backupDirectoryActor, backupPaths, postBackup))
} else if (postBackup.nonEmpty) {
log.error("TODO Post backup stuff isn't actually ever run")
//Backup paths should be empty at this stage
doBackup(client, None, backupPaths, None)
val postBackupCmd = context.actorOf(SSHCommandActor.props(client))
context.watch(postBackupCmd)
postBackupCmd ! ExecuteAsScript(postBackup.get)
context.become(awaitingPostBackup(client, postBackupCmd))
} else {
//All done doing the backup, step five!
val cmd = "umount /mnt/auto-backup"
val actor = context.actorOf(SSHCommandActor.props(client))
context.watch(actor)
actor ! ExecuteCommand(cmd)
context.become(awaitingUnmount(client, actor))
}
......
package is.kow.backupcoordinator.actors
import akka.actor.{Actor, ActorLogging, ActorRef, Props}
import is.kow.backupcoordinator.{BackupConfiguration, HostBackup}
object HostListActor {
def props(
hostBackups: List[HostBackup],
backupConfiguration: BackupConfiguration,
statusActor: Option[ActorRef] = None): Props = Props(new HostListActor(hostBackups, backupConfiguration, statusActor))
}
class HostListActor(
hostBackups: List[HostBackup],
backupConfiguration: BackupConfiguration,
statusActor: Option[ActorRef]
) extends Actor with ActorLogging {
override def preStart(): Unit = {
self ! hostBackups
}
def receive = {
case hosts:List[HostBackup] =>
//create the actor, become waiting on it's completion thing, and
}
}
......@@ -79,12 +79,32 @@ class SSHCommandActor(ssh: SSHClient) extends Actor with ActorLogging {
writer.close()
}
remoteFile.close()
sftp.close()
//Execute the remote file
val command = ExecuteCommand(fullPath)
//TODO: Have to become something else to pay attention to the result coming back
//Could receive a successful execution, or a failure, and then we report back
val command = ExecuteCommand(fullPath, e.environment)
val replyTo = sender()
log.debug(s"Executing script -- $fullPath")
executeCommand(command).onComplete {
case Success(ec) =>
//New SFTP, and delete the file
val sftp2 = ssh.newSFTPClient()
sftp2.rm(fullPath)
sftp2.close()
//Send the completed message back to the sender and stop myself
log.debug(s"Sending $ec to $replyTo")
replyTo ! ec
log.debug(s"STOPPING MYSELF: $self")
context.stop(self) //this sends a message, should work fine
case Failure(throwable) =>
log.error("COMMAND EXECUTION FAILED!!!!")
//I think I just need to die, and throw the exception, which should allow my supervisor
// to do something about it
throw throwable
}
case e: ExecuteCommand =>
val replyTo = sender()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment