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  }