Skip to content

Commit

Permalink
Merge pull request #542 from rgooch/master
Browse files Browse the repository at this point in the history
Support migrating VMs with multiple network interfaces and requesting specific IPs on create.
  • Loading branch information
rgooch committed Dec 21, 2018
2 parents fec1543 + c8662d9 commit 8c17042
Show file tree
Hide file tree
Showing 19 changed files with 517 additions and 15 deletions.
4 changes: 4 additions & 0 deletions cmd/hyper-control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,17 @@ Some of the sub-commands available are:
on a machine
- **make-installer-iso**: make a bootable installation ISO (CD-ROM) image for a
machine
- **move-ip-address**: move a (free) IP address to a specific *Hypervisor*
- **netboot-host**: temporarily enable PXE-based network booting and installing
for a machine
- **netboot-machine**: temporarily enable PXE-based network booting for a
machine
- **reinstall**: reinstall the local machine. This erases all data
- **remove-excess-addresses**: remove free addresses for a specific *Hypervisor*
above the specified limit
- **remove-ip-address**: remove a (free) IP address from a specific *Hypervisor*
- **remove-mac-address**: remove a (free) MAC address from a specific
*Hypervisor*
- **rollout-image**: safely roll out specified image to all *Hypervisors* in a
location
- **write-netboot-files**: write the configuration files for installing a
Expand Down
6 changes: 6 additions & 0 deletions cmd/hyper-control/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,13 @@ func printUsage() {
fmt.Fprintln(os.Stderr, " get-updates")
fmt.Fprintln(os.Stderr, " installer-shell hostname")
fmt.Fprintln(os.Stderr, " make-installer-iso hostname dirname")
fmt.Fprintln(os.Stderr, " move-ip-address IPaddr")
fmt.Fprintln(os.Stderr, " netboot-host hostname")
fmt.Fprintln(os.Stderr, " netboot-machine MACaddr IPaddr [hostname]")
fmt.Fprintln(os.Stderr, " reinstall")
fmt.Fprintln(os.Stderr, " remove-excess-addresses MaxFreeAddr")
fmt.Fprintln(os.Stderr, " remove-ip-address IPaddr")
fmt.Fprintln(os.Stderr, " remove-mac-address MACaddr")
fmt.Fprintln(os.Stderr, " rollout-image name")
fmt.Fprintln(os.Stderr, " write-netboot-files hostname dirname")
}
Expand All @@ -95,10 +98,13 @@ var subcommands = []subcommand{
{"get-updates", 0, 0, getUpdatesSubcommand},
{"installer-shell", 1, 1, installerShellSubcommand},
{"make-installer-iso", 2, 2, makeInstallerIsoSubcommand},
{"move-ip-address", 1, 1, moveIpAddressSubcommand},
{"netboot-host", 1, 1, netbootHostSubcommand},
{"netboot-machine", 2, 3, netbootMachineSubcommand},
{"reinstall", 0, 0, reinstallSubcommand},
{"remove-excess-addresses", 1, 1, removeExcessAddressesSubcommand},
{"remove-ip-address", 1, 1, removeIpAddressSubcommand},
{"remove-mac-address", 1, 1, removeMacAddressSubcommand},
{"rollout-image", 1, 1, rolloutImageSubcommand},
{"write-netboot-files", 2, 2, writeNetbootFilesSubcommand},
}
Expand Down
44 changes: 44 additions & 0 deletions cmd/hyper-control/moveIpAddress.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"fmt"
"net"
"os"

"github.com/Symantec/Dominator/lib/errors"
"github.com/Symantec/Dominator/lib/log"
"github.com/Symantec/Dominator/lib/srpc"
proto "github.com/Symantec/Dominator/proto/fleetmanager"
)

func moveIpAddressSubcommand(args []string, logger log.DebugLogger) {
if err := moveIpAddress(args[0], logger); err != nil {
fmt.Fprintf(os.Stderr, "Error moving IP address: %s\n", err)
os.Exit(1)
}
os.Exit(0)
}

func moveIpAddress(addr string, logger log.DebugLogger) error {
ipAddr := net.ParseIP(addr)
if len(ipAddr) < 4 {
return fmt.Errorf("invalid IP address: %s", addr)
}
request := proto.MoveIpAddressesRequest{
HypervisorHostname: *hypervisorHostname,
IpAddresses: []net.IP{ipAddr},
}
var reply proto.MoveIpAddressesResponse
clientName := fmt.Sprintf("%s:%d",
*fleetManagerHostname, *fleetManagerPortNum)
client, err := srpc.DialHTTP("tcp", clientName, 0)
if err != nil {
return err
}
defer client.Close()
err = client.RequestReply("FleetManager.MoveIpAddresses", request, &reply)
if err != nil {
return err
}
return errors.New(reply.Error)
}
54 changes: 54 additions & 0 deletions cmd/hyper-control/removeAddress.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package main

import (
"fmt"
"net"
"os"

"github.com/Symantec/Dominator/lib/errors"
"github.com/Symantec/Dominator/lib/log"
"github.com/Symantec/Dominator/lib/srpc"
proto "github.com/Symantec/Dominator/proto/hypervisor"
)

func removeIpAddressSubcommand(args []string, logger log.DebugLogger) {
ipAddr := net.ParseIP(args[0])
if len(ipAddr) < 4 {
fmt.Fprintf(os.Stderr, "Invalid IP address: %s\n", args[0])
os.Exit(1)
}
err := removeAddress(proto.Address{IpAddress: ipAddr}, logger)
if err != nil {
fmt.Fprintf(os.Stderr, "Error removing IP address: %s\n", err)
os.Exit(1)
}
os.Exit(0)
}

func removeMacAddressSubcommand(args []string, logger log.DebugLogger) {
address := proto.Address{MacAddress: args[0]}
err := removeAddress(address, logger)
if err != nil {
fmt.Fprintf(os.Stderr, "Error removing MAC address: %s\n", err)
os.Exit(1)
}
os.Exit(0)
}

func removeAddress(address proto.Address, logger log.DebugLogger) error {
address.Shrink()
request := proto.ChangeAddressPoolRequest{
AddressesToRemove: []proto.Address{address}}
var reply proto.ChangeAddressPoolResponse
clientName := fmt.Sprintf("%s:%d", *hypervisorHostname, *hypervisorPortNum)
client, err := srpc.DialHTTP("tcp", clientName, 0)
if err != nil {
return err
}
defer client.Close()
err = client.RequestReply("Hypervisor.ChangeAddressPool", request, &reply)
if err != nil {
return err
}
return errors.New(reply.Error)
}
22 changes: 22 additions & 0 deletions cmd/vm-control/createVm.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,28 @@ func createVmOnHypervisor(hypervisor string, logger log.DebugLogger) error {
MinimumFreeBytes: uint64(minFreeBytes),
RoundupPower: *roundupPower,
}
if len(requestIPs) > 0 && requestIPs[0] != "" {
ipAddr := net.ParseIP(requestIPs[0])
if ipAddr == nil {
return fmt.Errorf("invalid IP address: %s", requestIPs[0])
}
request.Address.IpAddress = ipAddr
}
if len(requestIPs) > 1 && len(secondarySubnetIDs) > 0 {
request.SecondaryAddresses = make([]hyper_proto.Address,
len(secondarySubnetIDs))
for index, addr := range requestIPs[1:] {
if addr == "" {
continue
}
ipAddr := net.ParseIP(addr)
if ipAddr == nil {
return fmt.Errorf("invalid IP address: %s", requestIPs[0])
}
request.SecondaryAddresses[index] = hyper_proto.Address{
IpAddress: ipAddr}
}
}
if sizes, err := parseSizes(secondaryVolumeSizes); err != nil {
return err
} else {
Expand Down
2 changes: 2 additions & 0 deletions cmd/vm-control/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ var (
secondaryVolumeSizes flagutil.StringList
subnetId = flag.String("subnetId", "",
"Subnet ID to launch VM in")
requestIPs flagutil.StringList
roundupPower = flag.Uint64("roundupPower", 24,
"power of 2 to round up root volume size")
snapshotRootOnly = flag.Bool("snapshotRootOnly", false,
Expand All @@ -78,6 +79,7 @@ func init() {
"minimum number of free bytes in root volume")
flag.Var(&ownerGroups, "ownerGroups", "Groups who own the VM")
flag.Var(&ownerUsers, "ownerUsers", "Extra users who own the VM")
flag.Var(&requestIPs, "requestIPs", "Request specific IPs, if available")
flag.Var(&secondarySubnetIDs, "secondarySubnetIDs", "Secondary Subnet IDs")
flag.Var(&secondaryVolumeSizes, "secondaryVolumeSizes",
"Sizes for secondary volumes")
Expand Down
5 changes: 5 additions & 0 deletions fleetmanager/hypervisors/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type hypervisorType struct {
type ipStorer interface {
AddIPsForHypervisor(hypervisor net.IP, addrs []net.IP) error
CheckIpIsRegistered(addr net.IP) (bool, error)
GetHypervisorForIp(addr net.IP) (net.IP, error)
SetIPsForHypervisor(hypervisor net.IP, addrs []net.IP) error
UnregisterHypervisor(hypervisor net.IP) error
}
Expand Down Expand Up @@ -146,6 +147,10 @@ func (m *Manager) MakeUpdateChannel(location string) <-chan fm_proto.Update {
return m.makeUpdateChannel(location)
}

func (m *Manager) MoveIpAddresses(hostname string, ipAddresses []net.IP) error {
return m.moveIpAddresses(hostname, ipAddresses)
}

func (m *Manager) WriteHtml(writer io.Writer) {
m.writeHtml(writer)
}
Expand Down
4 changes: 4 additions & 0 deletions fleetmanager/hypervisors/fsstorer/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ func (s *Storer) DeleteVm(hypervisor net.IP, ipAddr string) error {
return s.deleteVm(hypervisor, ipAddr)
}

func (s *Storer) GetHypervisorForIp(addr net.IP) (net.IP, error) {
return s.getHypervisorForIp(addr)
}

func (s *Storer) ListVMs(hypervisor net.IP) ([]string, error) {
return s.listVMs(hypervisor)
}
Expand Down
4 changes: 2 additions & 2 deletions fleetmanager/hypervisors/fsstorer/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import (
)

func (s *Storer) checkIpIsRegistered(addr net.IP) (bool, error) {
s.mutex.RLock()
defer s.mutex.RUnlock()
if ip, err := netIpToIp(addr); err != nil {
return false, err
} else {
s.mutex.RLock()
defer s.mutex.RUnlock()
_, ok := s.ipToHypervisor[ip]
return ok, nil
}
Expand Down
19 changes: 19 additions & 0 deletions fleetmanager/hypervisors/fsstorer/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package fsstorer

import (
"net"
)

func (s *Storer) getHypervisorForIp(addr net.IP) (net.IP, error) {
if ip, err := netIpToIp(addr); err != nil {
return nil, err
} else {
s.mutex.RLock()
hypervisor, ok := s.ipToHypervisor[ip]
s.mutex.RUnlock()
if !ok {
return nil, nil
}
return hypervisor[:], nil
}
}
Loading

0 comments on commit 8c17042

Please sign in to comment.