github.com/Cloud-Foundations/Dominator@v0.3.4/imagepublishers/amipublisher/prepareUnpackers.go (about) 1 package amipublisher 2 3 import ( 4 "errors" 5 "strconv" 6 "time" 7 8 uclient "github.com/Cloud-Foundations/Dominator/imageunpacker/client" 9 "github.com/Cloud-Foundations/Dominator/lib/awsutil" 10 "github.com/Cloud-Foundations/Dominator/lib/constants" 11 "github.com/Cloud-Foundations/Dominator/lib/log" 12 "github.com/Cloud-Foundations/Dominator/lib/srpc" 13 "github.com/aws/aws-sdk-go/aws" 14 "github.com/aws/aws-sdk-go/service/ec2" 15 ) 16 17 func prepareUnpackers(streamName string, targets awsutil.TargetList, 18 skipList awsutil.TargetList, name string, logger log.Logger) error { 19 resultsChannel := make(chan error, 1) 20 numTargets, err := awsutil.ForEachTarget(targets, skipList, 21 func(awsService *ec2.EC2, account, region string, logger log.Logger) { 22 err := prepareUnpacker(awsService, streamName, name, logger) 23 if err != nil { 24 logger.Println(err) 25 } 26 resultsChannel <- err 27 }, 28 logger) 29 // Collect results. 30 firstError := err 31 for i := 0; i < numTargets; i++ { 32 err := <-resultsChannel 33 if err != nil && firstError == nil { 34 firstError = err 35 } 36 } 37 return firstError 38 } 39 40 func prepareUnpacker(awsService *ec2.EC2, streamName string, name string, 41 logger log.Logger) error { 42 _, srpcClient, err := getWorkingUnpacker(awsService, name, logger) 43 if err != nil { 44 return err 45 } 46 defer srpcClient.Close() 47 if streamName == "" { 48 return nil 49 } 50 logger.Println("preparing unpacker") 51 err = uclient.PrepareForUnpack(srpcClient, streamName, true, false) 52 if err != nil { 53 return err 54 } 55 logger.Println("prepared unpacker") 56 return nil 57 } 58 59 func getWorkingUnpacker(awsService *ec2.EC2, name string, logger log.Logger) ( 60 *ec2.Instance, *srpc.Client, error) { 61 unpackerInstances, err := getInstances(awsService, name) 62 if err != nil { 63 return nil, nil, err 64 } 65 if len(unpackerInstances) < 1 { 66 return nil, nil, errors.New("no ImageUnpacker instances found") 67 } 68 unpackerInstance, err := getRunningInstance(awsService, unpackerInstances, 69 logger) 70 if err != nil { 71 return nil, nil, err 72 } 73 if unpackerInstance == nil { 74 return nil, nil, errors.New("no running ImageUnpacker instances found") 75 } 76 launchTime := aws.TimeValue(unpackerInstance.LaunchTime) 77 if launchTime.After(time.Now()) { 78 launchTime = time.Now() 79 } 80 address := *unpackerInstance.PrivateIpAddress + ":" + 81 strconv.Itoa(constants.ImageUnpackerPortNumber) 82 logger.Printf("discovered unpacker: %s at %s, connecting...\n", 83 *unpackerInstance.InstanceId, address) 84 retryUntil := launchTime.Add(time.Minute * 10) 85 if time.Until(retryUntil) < time.Minute { 86 // Give at least one minute grace in case unpacker restarts. 87 retryUntil = time.Now().Add(time.Minute) 88 } 89 srpcClient, err := connectToUnpacker(address, retryUntil, logger) 90 if err != nil { 91 return nil, nil, err 92 } 93 return unpackerInstance, srpcClient, nil 94 } 95 96 func connectToUnpacker(address string, retryUntil time.Time, 97 logger log.Logger) (*srpc.Client, error) { 98 for { 99 srpcClient, err := srpc.DialHTTP("tcp", address, time.Second*10) 100 if err == nil { 101 logger.Printf("connected: %s\n", address) 102 return srpcClient, nil 103 } 104 if time.Now().After(retryUntil) { 105 return nil, errors.New("timed out waiting for unpacker to start") 106 } 107 time.Sleep(time.Second * 5) 108 } 109 }