github.com/Cloud-Foundations/Dominator@v0.3.4/cmd/mdbd/loadHypervisor.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  	"time"
     7  
     8  	"github.com/Cloud-Foundations/Dominator/lib/constants"
     9  	"github.com/Cloud-Foundations/Dominator/lib/log"
    10  	"github.com/Cloud-Foundations/Dominator/lib/mdb"
    11  	"github.com/Cloud-Foundations/Dominator/lib/srpc"
    12  	proto "github.com/Cloud-Foundations/Dominator/proto/hypervisor"
    13  )
    14  
    15  var emptyTags = make(map[string]string)
    16  
    17  type hypervisorGeneratorType struct {
    18  	eventChannel chan<- struct{}
    19  	logger       log.DebugLogger
    20  	mutex        sync.Mutex
    21  	vms          map[string]*proto.VmInfo
    22  }
    23  
    24  func newHypervisorGenerator(params makeGeneratorParams) (generator, error) {
    25  	g := &hypervisorGeneratorType{
    26  		eventChannel: params.eventChannel,
    27  		logger:       params.logger,
    28  		vms:          make(map[string]*proto.VmInfo),
    29  	}
    30  	params.waitGroup.Add(1)
    31  	go g.daemon(params.waitGroup)
    32  	return g, nil
    33  }
    34  
    35  func (g *hypervisorGeneratorType) daemon(waitGroup *sync.WaitGroup) {
    36  	address := fmt.Sprintf(":%d", constants.HypervisorPortNumber)
    37  	for {
    38  		if err := g.getUpdates(address, waitGroup); err != nil {
    39  			g.logger.Println(err)
    40  			time.Sleep(time.Second)
    41  		}
    42  		waitGroup = nil
    43  	}
    44  }
    45  
    46  func (g *hypervisorGeneratorType) getUpdates(hypervisor string,
    47  	waitGroup *sync.WaitGroup) error {
    48  	client, err := srpc.DialHTTP("tcp", hypervisor, 0)
    49  	if err != nil {
    50  		return err
    51  	}
    52  	defer client.Close()
    53  	conn, err := client.Call("Hypervisor.GetUpdates")
    54  	if err != nil {
    55  		return err
    56  	}
    57  	defer conn.Close()
    58  	initialUpdate := true
    59  	for {
    60  		var update proto.Update
    61  		if err := conn.Decode(&update); err != nil {
    62  			return err
    63  		}
    64  		g.updateVMs(update.VMs, initialUpdate)
    65  		initialUpdate = false
    66  		if waitGroup != nil {
    67  			waitGroup.Done()
    68  			waitGroup = nil
    69  		}
    70  		select {
    71  		case g.eventChannel <- struct{}{}:
    72  		default:
    73  		}
    74  	}
    75  }
    76  
    77  func (g *hypervisorGeneratorType) Generate(unused_datacentre string,
    78  	logger log.DebugLogger) (*mdb.Mdb, error) {
    79  	var newMdb mdb.Mdb
    80  	g.mutex.Lock()
    81  	defer g.mutex.Unlock()
    82  	for ipAddr, vm := range g.vms {
    83  		if vm.State == proto.StateRunning {
    84  			tags := vm.Tags
    85  			if tags == nil {
    86  				tags = emptyTags
    87  			}
    88  			_, disableUpdates := tags["DisableUpdates"]
    89  			var ownerGroup string
    90  			if len(vm.OwnerGroups) > 0 {
    91  				ownerGroup = vm.OwnerGroups[0]
    92  			}
    93  			newMdb.Machines = append(newMdb.Machines, mdb.Machine{
    94  				Hostname:       ipAddr,
    95  				IpAddress:      ipAddr,
    96  				RequiredImage:  tags["RequiredImage"],
    97  				PlannedImage:   tags["PlannedImage"],
    98  				DisableUpdates: disableUpdates,
    99  				OwnerGroup:     ownerGroup,
   100  				Tags:           vm.Tags,
   101  			})
   102  		}
   103  	}
   104  	return &newMdb, nil
   105  }
   106  
   107  func (g *hypervisorGeneratorType) updateVMs(vms map[string]*proto.VmInfo,
   108  	initialUpdate bool) {
   109  	vmsToDelete := make(map[string]struct{}, len(g.vms))
   110  	if initialUpdate {
   111  		for ipAddr := range g.vms {
   112  			vmsToDelete[ipAddr] = struct{}{}
   113  		}
   114  	}
   115  	g.mutex.Lock()
   116  	defer g.mutex.Unlock()
   117  	for ipAddr, vm := range vms {
   118  		if vm == nil || len(vm.Volumes) < 1 {
   119  			delete(g.vms, ipAddr)
   120  		} else {
   121  			g.vms[ipAddr] = vm
   122  			delete(vmsToDelete, ipAddr)
   123  		}
   124  	}
   125  	for ipAddr := range vmsToDelete {
   126  		delete(g.vms, ipAddr)
   127  	}
   128  }