github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/fleetmanager/hypervisors/notifier.go (about)

     1  package hypervisors
     2  
     3  import (
     4  	"bytes"
     5  	"flag"
     6  	"fmt"
     7  	"net/smtp"
     8  	"time"
     9  )
    10  
    11  var (
    12  	emailDomain = flag.String("emailDomain", "",
    13  		"Email domain to sent notifications to")
    14  	smtpServer = flag.String("smtpServer", "", "Address of SMTP server")
    15  )
    16  
    17  func sendEmail(user string, vms []*vmInfoType) error {
    18  	fromAddress := "DoNotReply@" + *emailDomain
    19  	toAddress := user + "@" + *emailDomain
    20  	buffer := &bytes.Buffer{}
    21  	fmt.Fprintf(buffer, "From: %s\n", fromAddress)
    22  	fmt.Fprintf(buffer, "To: %s\n", toAddress)
    23  	fmt.Fprintln(buffer, "Subject: Please migrate your VMs")
    24  	fmt.Fprintln(buffer)
    25  	fmt.Fprintln(buffer,
    26  		"You own the following VMs which are on unhealthy Hypervisors.")
    27  	fmt.Fprintln(buffer,
    28  		"Please migrate your VMs to healthy Hypervisors ASAP.")
    29  	fmt.Fprintln(buffer, "Below is the list of your VMs which are affected:")
    30  	fmt.Fprintln(buffer)
    31  	for _, vm := range vms {
    32  		fmt.Fprintf(buffer, "IP: %s  name: %s  Hypervisor: %s  status: %s\n",
    33  			vm.Address.IpAddress, vm.Tags["Name"],
    34  			vm.hypervisor.machine.Hostname, vm.hypervisor.getHealthStatus())
    35  	}
    36  	return smtp.SendMail(*smtpServer, nil, fromAddress, []string{toAddress},
    37  		buffer.Bytes())
    38  }
    39  
    40  func (h *hypervisorType) addVmsToMap(vmsPerOwner map[string][]*vmInfoType) {
    41  	h.mutex.RLock()
    42  	defer h.mutex.RUnlock()
    43  	for _, vm := range h.vms {
    44  		for _, owner := range vm.OwnerUsers {
    45  			vmsPerOwner[owner] = append(vmsPerOwner[owner], vm)
    46  		}
    47  	}
    48  }
    49  
    50  func (m *Manager) getBadHypervisors() []*hypervisorType {
    51  	m.mutex.RLock()
    52  	defer m.mutex.RUnlock()
    53  	badHypervisors := make([]*hypervisorType, 0)
    54  	for _, hypervisor := range m.hypervisors {
    55  		switch hypervisor.probeStatus {
    56  		case probeStatusNotYetProbed:
    57  			continue
    58  		case probeStatusConnected:
    59  			if hypervisor.healthStatus == "" {
    60  				continue
    61  			}
    62  			if hypervisor.healthStatus == "healthy" {
    63  				continue
    64  			}
    65  			badHypervisors = append(badHypervisors, hypervisor)
    66  		default:
    67  			badHypervisors = append(badHypervisors, hypervisor)
    68  		}
    69  	}
    70  	return badHypervisors
    71  }
    72  
    73  func (m *Manager) notifierLoop() {
    74  	if *emailDomain == "" || *smtpServer == "" {
    75  		return
    76  	}
    77  	for time.Sleep(time.Minute); ; time.Sleep(time.Hour * 48) {
    78  		m.notify()
    79  	}
    80  }
    81  
    82  func (m *Manager) notify() {
    83  	badHypervisors := m.getBadHypervisors()
    84  	if len(badHypervisors) < 1 {
    85  		return
    86  	}
    87  	vmsPerOwner := make(map[string][]*vmInfoType)
    88  	for _, hypervisor := range badHypervisors {
    89  		hypervisor.addVmsToMap(vmsPerOwner)
    90  	}
    91  	for user, vms := range vmsPerOwner {
    92  		if err := sendEmail(user, vms); err != nil {
    93  			m.logger.Printf("error sending email for %s: %s\n", user, err)
    94  		}
    95  	}
    96  }