Package lochness provides primitives for orchestrating Mistify Agents.
Loch Ness is a simple virtual machine manager ("cloud controller"). It is a proof-of-concept, straight forward implementation for testing various ideas. It is targeted at clusters of up to around 100 physical machines.
A Hypervisor is a physical machine
A subnet is an actual IP subnet with a range of usable IP addresses. A hypervisor can have one of more subnets, while a subnet can span multiple hypervisors. This assumes a rather simple network layout.
A Network is a logical collection of subnets. It is generally used by guest creation to decide what logical segment to place a guest on.
A flavor is a virtual resource "Template" for guest creation. A guest has a single flavor.
A FW Group is a collection of firewall rules for incoming IP traffic. A Guest has a single fwgroup.
A guest is a virtual machine. At creation time, a network, fwgroup, and network is required.
const AgentPort int = 8080AgentPort is the default port on which to attempt contacting an agent
var (
// ConfigPath is the path in the config store.
ConfigPath = "lochness/config/"
)var DefaultCandidateFunctions = []CandidateFunction{
CandidateIsAlive,
CandidateHasSubnet,
CandidateHasResources,
CandidateRandomize,
}DefaultCandidateFunctions is a default list of CandidateFunctions for general use
var (
// FWGroupPath is the path in the config store
FWGroupPath = "lochness/fwgroups/"
)var (
// FlavorPath is the path in the config store
FlavorPath = "lochness/flavors/"
)var (
// GuestPath is the path in the config store
GuestPath = "lochness/guests/"
)var (
// HypervisorPath is the path in the config store
HypervisorPath = "lochness/hypervisors/"
)var (
// NetworkPath is the path in the config store.
NetworkPath = "lochness/networks/"
)var (
// SubnetPath is the key prefix for subnets
SubnetPath = "lochness/subnets/"
)var (
// VLANGroupPath is the path in the config store for VLAN groups
VLANGroupPath = "lochness/vlangroups/"
)var (
// VLANPath is the path in the config store for VLANs
VLANPath = "lochness/vlans/"
)func GetHypervisorID() stringGetHypervisorID gets the hypervisor id as set with SetHypervisorID. It does not make an attempt to discover the id if not set.
func SetHypervisorID(id string) (string, error)SetHypervisorID sets the id of the current hypervisor. It should be used by all daemons that are ran on a hypervisor and are expected to interact with the data stores directly. Passing in a blank string will fall back to first checking the environment variable "HYPERVISOR_ID" and then using the hostname. ID must be a valid UUID. ID will be lowercased.
type Agent interface {
GetGuest(string) (*client.Guest, error)
CreateGuest(string) (string, error)
DeleteGuest(string) (string, error)
GuestAction(string, string) (string, error)
CheckJobStatus(string, string) (bool, error)
}Agent is an interface that allows for communication with a hypervisor agent
type CandidateFunction func(*Guest, Hypervisors) (Hypervisors, error)CandidateFunction is used to select hypervisors that can run the given guest.
type Context struct {
}Context carries around data/structs needed for operations
func NewContext(kv kv.KV) *ContextNewContext creates a new context
func (c *Context) FWGroup(id string) (*FWGroup, error)FWGroup fetches a FWGroup from the config store
func (c *Context) FirstHypervisor(f func(*Hypervisor) bool) (*Hypervisor, error)FirstHypervisor will return the first hypervisor for which the function returns true.
func (c *Context) Flavor(id string) (*Flavor, error)Flavor fetches a single Flavor from the config store
func (c *Context) ForEachConfig(f func(key, val string) error) errorForEachConfig will run f on each config. It will stop iteration if f returns an error.
func (c *Context) ForEachGuest(f func(*Guest) error) errorForEachGuest will run f on each Guest. It will stop iteration if f returns an error.
func (c *Context) ForEachHypervisor(f func(*Hypervisor) error) errorForEachHypervisor will run f on each Hypervisor. It will stop iteration if f returns an error.
func (c *Context) ForEachSubnet(f func(*Subnet) error) errorForEachSubnet will run f on each Subnet. It will stop iteration if f returns an error.
func (c *Context) ForEachVLAN(f func(*VLAN) error) errorForEachVLAN will run f on each VLAN. It will stop iteration if f returns an error.
func (c *Context) ForEachVLANGroup(f func(*VLANGroup) error) errorForEachVLANGroup will run f on each VLAN. It will stop iteration if f returns an error.
func (c *Context) GetConfig(key string) (string, error)GetConfig gets a single value from the config store. The key can contain slashes ("/")
func (c *Context) Guest(id string) (*Guest, error)Guest fetches a Guest from the config store
func (c *Context) Hypervisor(id string) (*Hypervisor, error)Hypervisor fetches a Hypervisor from the config store.
func (c *Context) IsKeyNotFound(err error) boolIsKeyNotFound is a helper to determine if the error is a key not found error
func (c *Context) Network(id string) (*Network, error)Network fetches a Network from the data store.
func (c *Context) NewFWGroup() *FWGroupNewFWGroup creates a new, blank FWGroup
func (c *Context) NewFlavor() *FlavorNewFlavor creates a blank Flavor
func (c *Context) NewGuest() *GuestNewGuest create a new blank Guest
func (c *Context) NewHypervisor() *HypervisorNewHypervisor create a new blank Hypervisor.
func (context *Context) NewMistifyAgent(port int) *MistifyAgentNewMistifyAgent creates a new MistifyAgent instance within the context
func (c *Context) NewNetwork() *NetworkNewNetwork creates a new, blank Network.
func (c *Context) NewSubnet() *SubnetNewSubnet creates a new "blank" subnet. Fill in the needed values and then call Save.
func (c *Context) NewVLAN() *VLANNewVLAN creates a new blank VLAN.
func (c *Context) NewVLANGroup() *VLANGroupNewVLANGroup creates a new blank VLANGroup.
func (c *Context) SetConfig(key, val string) errorSetConfig sets a single value from the config store. The key can contain slashes ("/")
func (c *Context) Subnet(id string) (*Subnet, error)Subnet fetches a single subnet by ID
func (c *Context) VLAN(tag int) (*VLAN, error)VLAN fetches a VLAN from the data store.
func (c *Context) VLANGroup(id string) (*VLANGroup, error)VLANGroup fetches a VLAN from the data store.
type ErrorHTTPCode struct {
Expected int
Code int
}ErrorHTTPCode should be used for errors resulting from an http response code not matching the expected code
func (e ErrorHTTPCode) Error() stringError returns a string error message
type FWGroup struct {
ID string `json:"id"`
Metadata map[string]string `json:"metadata"`
Rules FWRules `json:"rules"`
}FWGroup represents a group of firewall rules
func (f FWGroup) MarshalJSON() ([]byte, error)MarshalJSON is a helper for marshalling a FWGroup
func (f *FWGroup) Refresh() errorRefresh reloads from the data store
func (f *FWGroup) Save() errorSave persists a FWGroup. It will call Validate.
func (f *FWGroup) UnmarshalJSON(input []byte) errorUnmarshalJSON is a helper for unmarshalling a FWGroup
func (f *FWGroup) Validate() errorValidate ensures a FWGroup has reasonable data.
type FWGroups []*FWGroupFWGroups is an alias to FWGroup slices
type FWRule struct {
Source *net.IPNet `json:"source,omitempty"`
Group string `json:"group"`
PortStart uint `json:"portStart"`
PortEnd uint `json:"portEnd"`
Protocol string `json:"protocol"`
Action string `json:"action"`
}FWRule represents a single firewall rule
type FWRules []*FWRuleFWRules is an alias to a slice of *FWRule
type Flavor struct {
ID string `json:"id"`
Image string `json:"image"`
Metadata map[string]string `json:"metadata"`
Resources
}Flavor defines the virtual resources for a guest
func (f *Flavor) Refresh() errorRefresh reloads from the data store
func (f *Flavor) Save() errorSave persists a Flavor. It will call Validate.
func (f *Flavor) Validate() errorValidate ensures a Flavor has reasonable data. It currently does nothing.
type Flavors []*FlavorFlavors is an alias to a slice of *Flavor
type Guest struct {
ID string `json:"id"`
Metadata map[string]string `json:"metadata"`
Type string `json:"type"` // type of guest. currently just kvm
FlavorID string `json:"flavor"` // resource flavor
HypervisorID string `json:"hypervisor"` // hypervisor. may be blank if not assigned yet
NetworkID string `json:"network"`
SubnetID string `json:"subnet"`
FWGroupID string `json:"fwgroup"`
VLANGroupID string `json:"vlangroup"`
MAC net.HardwareAddr `json:"mac"`
IP net.IP `json:"ip"`
Bridge string `json:"bridge"`
}Guest is a virtual machine
func (g *Guest) Candidates(f ...CandidateFunction) (Hypervisors, error)Candidates returns a list of Hypervisors that may run this Guest.
func (g *Guest) Destroy() errorDestroy removes a guest
func (g *Guest) MarshalJSON() ([]byte, error)MarshalJSON is a helper for marshalling a Guest
func (g *Guest) Refresh() errorRefresh reloads from the data store
func (g *Guest) Save() errorSave persists the Guest to the data store.
func (g *Guest) UnmarshalJSON(input []byte) errorUnmarshalJSON is a helper for unmarshalling a Guest
func (g *Guest) Validate() errorValidate ensures a Guest has reasonable data.
type Guests []*GuestGuests is an alias to a slice of *Guest
type Hypervisor struct {
ID string `json:"id"`
Metadata map[string]string `json:"metadata"`
IP net.IP `json:"ip"`
Netmask net.IP `json:"netmask"`
Gateway net.IP `json:"gateway"`
MAC net.HardwareAddr `json:"mac"`
TotalResources Resources `json:"total_resources"`
AvailableResources Resources `json:"available_resources"`
// Config is a set of key/values for driving various config options. writes should
// only be done using SetConfig
Config map[string]string
}Hypervisor is a physical box on which guests run
func (h *Hypervisor) AddGuest(g *Guest) errorAddGuest adds a Guest to the Hypervisor. It reserves an IPaddress for the Guest. It also updates the Guest.
func (h *Hypervisor) AddSubnet(s *Subnet, bridge string) errorAddSubnet adds a subnet to a Hypervisor.
func (h *Hypervisor) Destroy() errorDestroy removes a hypervisor. The Hypervisor must not have any guests.
func (h *Hypervisor) ForEachGuest(f func(*Guest) error) errorForEachGuest will run f on each Guest. It will stop iteration if f returns an error.
func (h *Hypervisor) Guests() []stringGuests returns a slice of GuestIDs assigned to the Hypervisor.
func (h *Hypervisor) Heartbeat(ttl time.Duration) errorHeartbeat announces the availability of a hypervisor. In general, this is useful for service announcement/discovery. Should be ran from the hypervisor, or something monitoring it.
func (h *Hypervisor) IsAlive() boolIsAlive returns true if the heartbeat is present.
func (h *Hypervisor) MarshalJSON() ([]byte, error)MarshalJSON is a helper for marshalling a Hypervisor
func (h *Hypervisor) Refresh() errorRefresh reloads a Hypervisor from the data store.
func (h *Hypervisor) RemoveGuest(g *Guest) errorRemoveGuest removes a guest from the hypervisor. Also releases the IP.
func (h *Hypervisor) RemoveSubnet(s *Subnet) errorRemoveSubnet removes a subnet from a Hypervisor.
func (h *Hypervisor) Save() errorSave persists a FWGroup. It will call Validate.
func (h *Hypervisor) SetConfig(key, value string) errorSetConfig sets a single Hypervisor Config value. Set value to "" to unset.
func (h *Hypervisor) Subnets() map[string]stringSubnets returns the subnet/bridge mappings for a Hypervisor.
func (h *Hypervisor) UnmarshalJSON(input []byte) errorUnmarshalJSON is a helper for unmarshalling a Hypervisor
func (h *Hypervisor) UpdateResources() errorUpdateResources syncs Hypervisor resource usage to the data store. It should only be ran on the actual hypervisor.
func (h *Hypervisor) Validate() errorValidate ensures a Hypervisor has reasonable data. It currently does nothing.
func (h *Hypervisor) VerifyOnHV() errorVerifyOnHV verifies that it is being ran on hypervisor with same hostname as id.
type Hypervisors []*HypervisorHypervisors is an alias to a slice of *Hypervisor
func CandidateHasResources(g *Guest, hs Hypervisors) (Hypervisors, error)CandidateHasResources returns Hypervisors that have available resources based on the request Flavor of the Guest.
func CandidateHasSubnet(g *Guest, hs Hypervisors) (Hypervisors, error)CandidateHasSubnet returns Hypervisors that have subnets with available addresses in the request Network of the Guest.
func CandidateIsAlive(g *Guest, hs Hypervisors) (Hypervisors, error)CandidateIsAlive returns Hypervisors that are "alive" based on heartbeat
func CandidateRandomize(g *Guest, hs Hypervisors) (Hypervisors, error)CandidateRandomize shuffles the list of Hypervisors.
type MistifyAgent struct {
}MistifyAgent is an Agent that communicates with a hypervisor agent to perform actions relating to guests
func (agent *MistifyAgent) CheckJobStatus(guestID, jobID string) (bool, error)CheckJobStatus looks up whether a guest job has been completed or not.
func (agent *MistifyAgent) CreateGuest(guestID string) (string, error)CreateGuest tries to create a new guest on a hypervisor selected from a list of viable candidates
func (agent *MistifyAgent) DeleteGuest(guestID string) (string, error)DeleteGuest deletes a guest from a hypervisor
func (agent *MistifyAgent) FetchImage(guestID string) (string, error)FetchImage fetches a disk image that can be used for guest creation
func (agent *MistifyAgent) GetGuest(guestID string) (*client.Guest, error)GetGuest retrieves information on a guest from an agent
func (agent *MistifyAgent) GuestAction(guestID, actionName string) (string, error)GuestAction is used to run various actions on a guest under a hypervisor Actions: "shutdown", "reboot", "restart", "poweroff", "start", "suspend"
type Network struct {
ID string `json:"id"`
Metadata map[string]string `json:"metadata"`
}Network is a logical collection of subnets.
func (n *Network) AddSubnet(s *Subnet) errorAddSubnet adds a Subnet to the Network.
func (n *Network) Refresh() errorRefresh reloads the Network from the data store.
func (n *Network) RemoveSubnet(s *Subnet) errorRemoveSubnet removes a subnet from the network
func (n *Network) Save() errorSave persists a Network. It will call Validate.
func (n *Network) Subnets() []stringSubnets returns the IDs of the Subnets associated with the network.
func (n *Network) Validate() errorValidate ensures a Network has reasonable data. It currently does nothing.
type Networks []*NetworkNetworks is an alias to a slice of *Network
type Resources struct {
Memory uint64 `json:"memory"` // memory in MB
Disk uint64 `json:"disk"` // disk in MB
CPU uint32 `json:"cpu"` // virtual cpus
}Resources represents compute resources
type Subnet struct {
ID string `json:"id"`
Metadata map[string]string `json:"metadata"`
NetworkID string `json:"network"`
Gateway net.IP `json:"gateway"`
CIDR *net.IPNet `json:"cidr"`
StartRange net.IP `json:"start"` // first usable IP in range
EndRange net.IP `json:"end"` // last usable IP in range
}Subnet is an actual ip subnet for assigning addresses
func (s *Subnet) Addresses() map[string]stringAddresses returns used IP addresses.
func (s *Subnet) AvailableAddresses() []net.IPAvailableAddresses returns the available ip addresses. this is probably a horrible idea for ipv6.
func (s *Subnet) Delete() errorDelete removes a subnet. It does not ensure it is unused, so use with extreme caution.
func (s *Subnet) MarshalJSON() ([]byte, error)MarshalJSON is used by the json package
func (s *Subnet) Refresh() errorRefresh reloads the Subnet from the data store.
func (s *Subnet) ReleaseAddress(ip net.IP) errorReleaseAddress releases an address. This does not change any thing that may also be referring to this address.
func (s *Subnet) ReserveAddress(id string) (net.IP, error)ReserveAddress reserves an ip address. The id is a guest id.
func (s *Subnet) Save() errorSave persists the subnet to the datastore.
func (s *Subnet) UnmarshalJSON(input []byte) errorUnmarshalJSON is used by the json package
func (s *Subnet) Validate() errorValidate ensures the values are reasonable.
type Subnets []*SubnetSubnets is an alias to a slice of *Subnet
type VLAN struct {
Tag int `json:"tag"`
Description string `json:"description"`
}VLAN devines the virtual lan for a guest interface
func (v *VLAN) Destroy() errorDestroy removes the VLAN
func (v *VLAN) Refresh() errorRefresh reloads the VLAN from the data store.
func (v *VLAN) Save() errorSave persists a VLAN. It will call Validate.
func (v *VLAN) VLANGroups() []stringVLANGroups returns the IDs of the VLANGroups associated with the VLAN
func (v *VLAN) Validate() errorValidate ensures a VLAN has resonable data.
type VLANGroup struct {
ID string `json:"id"`
Description string `json:"description"`
Metadata map[string]string `json:"metadata"`
}VLANGroup defines a set of VLANs for a guest interface
func (vg *VLANGroup) AddVLAN(vlan *VLAN) errorAddVLAN adds a VLAN to the VLANGroup
func (vg *VLANGroup) Destroy() errorDestroy removes a VLANGroup
func (vg *VLANGroup) Refresh() errorRefresh reloads the VLAN from the data store.
func (vg *VLANGroup) RemoveVLAN(vlan *VLAN) errorRemoveVLAN removes a VLAN from the VLANGroup
func (vg *VLANGroup) Save() errorSave persists a VLANgroup. It will call Validate.
func (vg *VLANGroup) VLANs() []intVLANs returns the Tags of the VLANs associated with the VLANGroup
func (vg *VLANGroup) Validate() errorValidate ensures a VLANGroup has resonable data.
type VLANGroups []*VLANGroupVLANGroups is an alias to a slice of *VLANGroup
type VLANs []*VLANVLANs is an alias to a slice of *VLAN
-- Generated with godocdown
