github.com/stackdocker/rkt@v0.10.1-0.20151109095037-1aa827478248/stage1/enter_kvm/enter_kvm.go (about) 1 // Copyright 2015 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "flag" 19 "fmt" 20 "os" 21 "os/exec" 22 "path/filepath" 23 "syscall" 24 25 "github.com/coreos/rkt/networking/netinfo" 26 "github.com/coreos/rkt/pkg/lock" 27 ) 28 29 const ( 30 kvmSettingsDir = "kvm" 31 kvmPrivateKeyFilename = "ssh_kvm_key" 32 // TODO: overwrite below default by environment value + generate .socket unit just before pod start 33 kvmSSHPort = "122" // hardcoded value in .socket file 34 ) 35 36 var ( 37 podPid string 38 appName string 39 ) 40 41 func init() { 42 flag.StringVar(&podPid, "pid", "", "podPID") 43 flag.StringVar(&appName, "appname", "", "application to use") 44 } 45 46 func getPodDefaultIP(workDir string) (string, error) { 47 // get pod lock 48 l, err := lock.NewLock(workDir, lock.Dir) 49 if err != nil { 50 return "", err 51 } 52 53 // get file descriptor for lock 54 fd, err := l.Fd() 55 if err != nil { 56 return "", err 57 } 58 59 // use this descriptor as method of reading pod network configuration 60 nets, err := netinfo.LoadAt(fd) 61 if err != nil { 62 return "", err 63 } 64 // kvm flavored container must have at first position default vm<->host network 65 if len(nets) == 0 { 66 return "", fmt.Errorf("Pod has no configured networks") 67 } 68 return nets[0].IP.String(), nil 69 } 70 71 func getAppexecArgs() []string { 72 // Documentation/devel/stage1-implementors-guide.md#arguments-1 73 // also from ../enter/enter.c 74 args := []string{ 75 "/appexec", 76 fmt.Sprintf("/opt/stage2/%s/rootfs", appName), 77 "/", // as in ../enter/enter.c - this should be app.WorkingDirectory 78 fmt.Sprintf("/rkt/env/%s", appName), 79 "0", // uid 80 "0", // gid 81 } 82 return append(args, flag.Args()...) 83 } 84 85 func execSSH() error { 86 workDir, err := os.Getwd() 87 if err != nil { 88 return fmt.Errorf("Cannot get working directory: %v", err) 89 } 90 91 podDefaultIP, err := getPodDefaultIP(workDir) 92 if err != nil { 93 return fmt.Errorf("Cannot load networking configuration: %v", err) 94 } 95 96 // escape from running pod directory into base directory 97 if err = os.Chdir("../../.."); err != nil { 98 return fmt.Errorf("Cannot change directory to rkt work directory: %v", err) 99 } 100 101 // find path to ssh binary 102 sshPath, err := exec.LookPath("ssh") 103 if err != nil { 104 return fmt.Errorf("Cannot find 'ssh' binary in PATH: %v", err) 105 } 106 107 // prepare args for ssh invocation 108 keyFile := filepath.Join(kvmSettingsDir, kvmPrivateKeyFilename) 109 args := []string{ 110 "ssh", 111 "-t", // use tty 112 "-i", keyFile, // use keyfile 113 "-l", "root", // login as user 114 "-p", kvmSSHPort, // port to connect 115 "-o", "StrictHostKeyChecking=no", // do not check changing host keys 116 "-o", "UserKnownHostsFile=/dev/null", // do not add host key to default knownhosts file 117 "-o", "LogLevel=quiet", // do not log minor informations 118 podDefaultIP, 119 } 120 args = append(args, getAppexecArgs()...) 121 122 // this should not return in case of success 123 err = syscall.Exec(sshPath, args, os.Environ()) 124 return fmt.Errorf("Cannot exec to ssh: %v", err) 125 } 126 127 func main() { 128 flag.Parse() 129 if appName == "" { 130 fmt.Fprintf(os.Stderr, "--appname not set to correct value\n") 131 os.Exit(1) 132 } 133 134 // execSSH should returns only with error 135 fmt.Fprintf(os.Stderr, "%v\n", execSSH()) 136 os.Exit(2) 137 }