From b232ceec3c151a3aa4abf27f82b5c5c2d12ac1a3 Mon Sep 17 00:00:00 2001 From: James Munnelly Date: Thu, 10 Sep 2015 09:41:27 +0100 Subject: [PATCH] Mount NFS directories into container. Use bootstrap script to first cd into correct working directory for transcode. String replace ffmpeg progress URL. --- Dockerfile | 3 + bootstrap.sh | 5 ++ executors/kubernetes/kubernetes_executor.go | 69 ++++++++++++++++----- main.go | 38 +++++++++++- 4 files changed, 96 insertions(+), 19 deletions(-) create mode 100755 bootstrap.sh diff --git a/Dockerfile b/Dockerfile index 641ed93..94db99e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,8 +13,11 @@ RUN mkdir /pms && \ cd / && \ rm -Rf /pms + WORKDIR /plexmediaserver +ADD bootstrap.sh . + ENV LD_LIBRARY_PATH "/plexmediaserver" ENTRYPOINT ["/plexmediaserver/Resources/Plex New Transcoder"] \ No newline at end of file diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..e9e9fb9 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +cd $1 + +/plexmediaserver/Resources/Plex\ New\ Transcoder "${@:2}" \ No newline at end of file diff --git a/executors/kubernetes/kubernetes_executor.go b/executors/kubernetes/kubernetes_executor.go index a0180b3..8ea385e 100644 --- a/executors/kubernetes/kubernetes_executor.go +++ b/executors/kubernetes/kubernetes_executor.go @@ -2,6 +2,8 @@ package kubernetes import ( "time" + "errors" + "fmt" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/client" @@ -15,7 +17,7 @@ import ( const podBasename = "plex-transcoder" const kubernetesHost = "10.20.40.254:8080" const kubernetesNamespace = "plex" -const dockerImage = "registry.marley.xyz/e720/plex-new-transcoder" +const dockerImage = "munnerz/plex-new-transcoder" type KubernetesExecutor struct { executors.AbstractExecutor @@ -30,25 +32,56 @@ type KubernetesExecutor struct { func (e *KubernetesExecutor) createPod() *api.Pod { return &api.Pod{ - TypeMeta: api.TypeMeta{ - Kind: "Pod", - }, - ObjectMeta: api.ObjectMeta{ - GenerateName: podBasename, - Namespace: e.Namespace, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyNever, - Containers: []api.Container{ - api.Container{ - Name: podBasename, - Image: e.Image, - Command: e.Job.Command, - Args: e.Job.Args, + TypeMeta: api.TypeMeta{ + Kind: "Pod", + }, + ObjectMeta: api.ObjectMeta{ + GenerateName: podBasename, + Namespace: e.Namespace, + }, + Spec: api.PodSpec{ + Volumes: []api.Volume{ + api.Volume{ + Name: "source-dir", + VolumeSource: api.VolumeSource { + NFS: &api.NFSVolumeSource { + Server: "10.12.14.16", + Path: "/tank/media", + ReadOnly: true, }, }, }, - } + api.Volume{ + Name: "transcode-dir", + VolumeSource: api.VolumeSource { + NFS: &api.NFSVolumeSource { + Server: "10.12.14.16", + Path: "/ssd/plex/Buffer", + }, + }, + }, + }, + RestartPolicy: api.RestartPolicyNever, + Containers: []api.Container{ + api.Container{ + Name: podBasename, + Image: e.Image, + Command: e.Job.Command, + Args: e.Job.Args, + VolumeMounts: []api.VolumeMount{ + api.VolumeMount{ + Name: "source-dir", + MountPath: "/tank/media", + }, + api.VolumeMount{ + Name: "transcode-dir", + MountPath: "/ssd/plex/Buffer", + }, + }, + }, + }, + }, + } } func (e *KubernetesExecutor) Start() error { @@ -112,6 +145,8 @@ func (e *KubernetesExecutor) WaitForState(targetState executors.ExecutorPhase) e switch podPhaseToExecutorPhase(pod.Status.Phase) { case targetState: break Loop + case executors.ExecutorFailed: + return errors.New(fmt.Sprintf("Pod failed whilst waiting for state: %s\nReason: %s", targetState, pod.Status.Reason)) default: break Switch } diff --git a/main.go b/main.go index f00910a..99ffc72 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,8 @@ import ( "os" "os/signal" "syscall" + "fmt" + "strings" log "github.com/Sirupsen/logrus" @@ -13,6 +15,12 @@ import ( _ "github.com/munnerz/plex-elastic-transcoder/executors/kubernetes" ) +const ( + cmdPath = "/plexmediaserver/bootstrap.sh" + logFilePath = "/var/log/plex/plex-elastic-transcoder.log" + plexServerURL = "10.12.14.16:32400" +) + var executor executors.Executor func signals() { @@ -39,16 +47,42 @@ func signals() { os.Exit(0) }() } + func main() { // Setup signals signals() + // Setup logs + fo, err := os.Create(logFilePath) + + if err != nil { + panic(fmt.Sprintf("Error opening log file: %s", err)) + } + + defer func() { + if err := fo.Close(); err != nil { + panic(fmt.Sprintf("Error closing file: %s", err)) + } + }() + + log.SetOutput(fo) + // Get the arguments passed to Plex New Transcoder args := os.Args[1:] + wd, _ := os.Getwd() + for i, arg := range args { + if arg == "-progressurl" { + // Change the progress URL to report to about the transcode + args[i + 1] = strings.Replace(args[i+1], "127.0.0.1:32400", plexServerURL, 1) + } + } + args = append([]string{wd}, args) + + log.Print("In WD: ", wd) log.Print("Dispatching job with args: ", args) job := executors.Job{ - Command: []string{"/Plex New Transcoder"}, + Command: []string{cmdPath}, Args: args, } @@ -56,7 +90,7 @@ func main() { log.Print("Created executor: ", executor) - err := executor.Start() + err = executor.Start() if err != nil { log.Fatal("Job start failed with error: ", err) }