github.com/Cloud-Foundations/Dominator@v0.3.4/proto/hypervisor/methods.go (about)

     1  package hypervisor
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"net"
     7  	"strings"
     8  )
     9  
    10  const consoleTypeUnknown = "UNKNOWN ConsoleType"
    11  const stateUnknown = "UNKNOWN State"
    12  const volumeFormatUnknown = "UNKNOWN VolumeFormat"
    13  const volumeTypeUnknown = "UNKNOWN VolumeType"
    14  
    15  var (
    16  	consoleTypeToText = map[ConsoleType]string{
    17  		ConsoleNone:  "none",
    18  		ConsoleDummy: "dummy",
    19  		ConsoleVNC:   "vnc",
    20  	}
    21  	textToConsoleType map[string]ConsoleType
    22  
    23  	stateToText = map[State]string{
    24  		StateStarting:      "starting",
    25  		StateRunning:       "running",
    26  		StateFailedToStart: "failed to start",
    27  		StateStopping:      "stopping",
    28  		StateStopped:       "stopped",
    29  		StateDestroying:    "destroying",
    30  		StateMigrating:     "migrating",
    31  		StateExporting:     "exporting",
    32  		StateCrashed:       "crashed",
    33  		StateDebugging:     "debugging",
    34  	}
    35  	textToState map[string]State
    36  
    37  	volumeFormatToText = map[VolumeFormat]string{
    38  		VolumeFormatRaw:   "raw",
    39  		VolumeFormatQCOW2: "qcow2",
    40  	}
    41  	textToVolumeFormat map[string]VolumeFormat
    42  
    43  	volumeTypeToText = map[VolumeType]string{
    44  		VolumeTypePersistent: "persistent",
    45  		VolumeTypeMemory:     "memory",
    46  	}
    47  	textToVolumeType map[string]VolumeType
    48  )
    49  
    50  func init() {
    51  	textToConsoleType = make(map[string]ConsoleType, len(consoleTypeToText))
    52  	for consoleType, text := range consoleTypeToText {
    53  		textToConsoleType[text] = consoleType
    54  	}
    55  	textToState = make(map[string]State, len(stateToText))
    56  	for state, text := range stateToText {
    57  		textToState[text] = state
    58  	}
    59  	textToVolumeFormat = make(map[string]VolumeFormat, len(volumeFormatToText))
    60  	for format, text := range volumeFormatToText {
    61  		textToVolumeFormat[text] = format
    62  	}
    63  	textToVolumeType = make(map[string]VolumeType, len(volumeTypeToText))
    64  	for vtype, text := range volumeTypeToText {
    65  		textToVolumeType[text] = vtype
    66  	}
    67  }
    68  
    69  // CompareIP returns true if the two IPs are equivalent, else false.
    70  func CompareIPs(left, right net.IP) bool {
    71  	if len(left) < 1 {
    72  		if len(right) > 0 {
    73  			return false
    74  		}
    75  		return true
    76  	} else if len(right) < 1 {
    77  		return false
    78  	}
    79  	return left.Equal(right)
    80  }
    81  
    82  func ShrinkIP(netIP net.IP) net.IP {
    83  	switch len(netIP) {
    84  	case 4:
    85  		return netIP
    86  	case 16:
    87  		if ip4 := netIP.To4(); ip4 == nil {
    88  			return netIP
    89  		} else {
    90  			return ip4
    91  		}
    92  	default:
    93  		return netIP
    94  	}
    95  }
    96  
    97  func (left *Address) Equal(right *Address) bool {
    98  	if !CompareIPs(left.IpAddress, right.IpAddress) {
    99  		return false
   100  	}
   101  	if left.MacAddress != right.MacAddress {
   102  		return false
   103  	}
   104  	return true
   105  }
   106  
   107  func (address *Address) Set(value string) error {
   108  	if split := strings.Split(value, ";"); len(split) != 2 {
   109  		return errors.New("malformed address pair: " + value)
   110  	} else if ip := net.ParseIP(split[1]); ip == nil {
   111  		return errors.New("unable to parse IP: " + split[1])
   112  	} else if ip4 := ip.To4(); ip4 == nil {
   113  		return errors.New("address is not IPv4: " + split[1])
   114  	} else {
   115  		*address = Address{IpAddress: ip4, MacAddress: split[0]}
   116  		return nil
   117  	}
   118  }
   119  
   120  func (address *Address) Shrink() {
   121  	address.IpAddress = ShrinkIP(address.IpAddress)
   122  }
   123  
   124  func (address *Address) String() string {
   125  	return address.IpAddress.String() + ";" + address.MacAddress
   126  }
   127  
   128  func (al *AddressList) String() string {
   129  	buffer := &bytes.Buffer{}
   130  	buffer.WriteString(`"`)
   131  	for index, address := range *al {
   132  		buffer.WriteString(address.String())
   133  		if index < len(*al)-1 {
   134  			buffer.WriteString(",")
   135  		}
   136  	}
   137  	buffer.WriteString(`"`)
   138  	return buffer.String()
   139  }
   140  
   141  func (al *AddressList) Set(value string) error {
   142  	newList := make(AddressList, 0)
   143  	if value != "" {
   144  		addressStrings := strings.Split(value, ",")
   145  		for _, addressString := range addressStrings {
   146  			var address Address
   147  			if err := address.Set(addressString); err != nil {
   148  				return err
   149  			}
   150  			newList = append(newList, address)
   151  		}
   152  	}
   153  	*al = newList
   154  	return nil
   155  }
   156  
   157  func stringSlicesEqual(left, right []string) bool {
   158  	if len(left) != len(right) {
   159  		return false
   160  	}
   161  	for index, leftString := range left {
   162  		if leftString != right[index] {
   163  			return false
   164  		}
   165  	}
   166  	return true
   167  }
   168  
   169  func (consoleType *ConsoleType) CheckValid() error {
   170  	if _, ok := consoleTypeToText[*consoleType]; !ok {
   171  		return errors.New(consoleTypeUnknown)
   172  	} else {
   173  		return nil
   174  	}
   175  }
   176  
   177  func (consoleType ConsoleType) MarshalText() ([]byte, error) {
   178  	if text := consoleType.String(); text == consoleTypeUnknown {
   179  		return nil, errors.New(text)
   180  	} else {
   181  		return []byte(text), nil
   182  	}
   183  }
   184  
   185  func (consoleType *ConsoleType) Set(value string) error {
   186  	if val, ok := textToConsoleType[value]; !ok {
   187  		return errors.New(consoleTypeUnknown)
   188  	} else {
   189  		*consoleType = val
   190  		return nil
   191  	}
   192  }
   193  
   194  func (consoleType ConsoleType) String() string {
   195  	if str, ok := consoleTypeToText[consoleType]; !ok {
   196  		return consoleTypeUnknown
   197  	} else {
   198  		return str
   199  	}
   200  }
   201  
   202  func (consoleType *ConsoleType) UnmarshalText(text []byte) error {
   203  	txt := string(text)
   204  	if val, ok := textToConsoleType[txt]; ok {
   205  		*consoleType = val
   206  		return nil
   207  	} else {
   208  		return errors.New("unknown ConsoleType: " + txt)
   209  	}
   210  }
   211  
   212  func (state State) MarshalText() ([]byte, error) {
   213  	if text := state.String(); text == stateUnknown {
   214  		return nil, errors.New(text)
   215  	} else {
   216  		return []byte(text), nil
   217  	}
   218  }
   219  
   220  func (state State) String() string {
   221  	if text, ok := stateToText[state]; ok {
   222  		return text
   223  	} else {
   224  		return stateUnknown
   225  	}
   226  }
   227  
   228  func (state *State) UnmarshalText(text []byte) error {
   229  	txt := string(text)
   230  	if val, ok := textToState[txt]; ok {
   231  		*state = val
   232  		return nil
   233  	} else {
   234  		return errors.New("unknown State: " + txt)
   235  	}
   236  }
   237  
   238  func (left *Subnet) Equal(right *Subnet) bool {
   239  	if left.Id != right.Id {
   240  		return false
   241  	}
   242  	if !CompareIPs(left.IpGateway, right.IpGateway) {
   243  		return false
   244  	}
   245  	if !CompareIPs(left.IpMask, right.IpMask) {
   246  		return false
   247  	}
   248  	if left.DomainName != right.DomainName {
   249  		return false
   250  	}
   251  	if !IpListsEqual(left.DomainNameServers, right.DomainNameServers) {
   252  		return false
   253  	}
   254  	if left.DisableMetadata != right.DisableMetadata {
   255  		return false
   256  	}
   257  	if left.Manage != right.Manage {
   258  		return false
   259  	}
   260  	if left.VlanId != right.VlanId {
   261  		return false
   262  	}
   263  	if !stringSlicesEqual(left.AllowedGroups, right.AllowedGroups) {
   264  		return false
   265  	}
   266  	if !stringSlicesEqual(left.AllowedUsers, right.AllowedUsers) {
   267  		return false
   268  	}
   269  	if !CompareIPs(left.FirstDynamicIP, right.FirstDynamicIP) {
   270  		return false
   271  	}
   272  	return true
   273  }
   274  
   275  func IpListsEqual(left, right []net.IP) bool {
   276  	if len(left) != len(right) {
   277  		return false
   278  	}
   279  	for index, leftIP := range left {
   280  		if !CompareIPs(leftIP, right[index]) {
   281  			return false
   282  		}
   283  	}
   284  	return true
   285  }
   286  
   287  func (subnet *Subnet) Shrink() {
   288  	subnet.IpGateway = ShrinkIP(subnet.IpGateway)
   289  	subnet.IpMask = ShrinkIP(subnet.IpMask)
   290  	for index, ipAddr := range subnet.DomainNameServers {
   291  		subnet.DomainNameServers[index] = ShrinkIP(ipAddr)
   292  	}
   293  }
   294  
   295  func (left *VmInfo) Equal(right *VmInfo) bool {
   296  	if !left.Address.Equal(&right.Address) {
   297  		return false
   298  	}
   299  	if left.ConsoleType != right.ConsoleType {
   300  		return false
   301  	}
   302  	if left.DestroyProtection != right.DestroyProtection {
   303  		return false
   304  	}
   305  	if left.DisableVirtIO != right.DisableVirtIO {
   306  		return false
   307  	}
   308  	if left.Hostname != right.Hostname {
   309  		return false
   310  	}
   311  	if left.ImageName != right.ImageName {
   312  		return false
   313  	}
   314  	if left.ImageURL != right.ImageURL {
   315  		return false
   316  	}
   317  	if left.MemoryInMiB != right.MemoryInMiB {
   318  		return false
   319  	}
   320  	if left.MilliCPUs != right.MilliCPUs {
   321  		return false
   322  	}
   323  	if !stringSlicesEqual(left.OwnerGroups, right.OwnerGroups) {
   324  		return false
   325  	}
   326  	if !stringSlicesEqual(left.OwnerUsers, right.OwnerUsers) {
   327  		return false
   328  	}
   329  	if left.SpreadVolumes != right.SpreadVolumes {
   330  		return false
   331  	}
   332  	if left.State != right.State {
   333  		return false
   334  	}
   335  	if !left.Tags.Equal(right.Tags) {
   336  		return false
   337  	}
   338  	if len(left.SecondaryAddresses) != len(right.SecondaryAddresses) {
   339  		return false
   340  	}
   341  	for index, leftAddress := range left.SecondaryAddresses {
   342  		if !leftAddress.Equal(&right.SecondaryAddresses[index]) {
   343  			return false
   344  		}
   345  	}
   346  	if !stringSlicesEqual(left.SecondarySubnetIDs, right.SecondarySubnetIDs) {
   347  		return false
   348  	}
   349  	if left.SubnetId != right.SubnetId {
   350  		return false
   351  	}
   352  	if left.Uncommitted != right.Uncommitted {
   353  		return false
   354  	}
   355  	if len(left.Volumes) != len(right.Volumes) {
   356  		return false
   357  	}
   358  	for index, leftVolume := range left.Volumes {
   359  		if leftVolume != right.Volumes[index] {
   360  			return false
   361  		}
   362  	}
   363  	return true
   364  }
   365  
   366  func (volumeFormat VolumeFormat) MarshalText() ([]byte, error) {
   367  	if text := volumeFormat.String(); text == volumeFormatUnknown {
   368  		return nil, errors.New(text)
   369  	} else {
   370  		return []byte(text), nil
   371  	}
   372  }
   373  
   374  func (volumeFormat VolumeFormat) String() string {
   375  	if text, ok := volumeFormatToText[volumeFormat]; ok {
   376  		return text
   377  	} else {
   378  		return volumeFormatUnknown
   379  	}
   380  }
   381  
   382  func (volumeFormat *VolumeFormat) UnmarshalText(text []byte) error {
   383  	txt := string(text)
   384  	if val, ok := textToVolumeFormat[txt]; ok {
   385  		*volumeFormat = val
   386  		return nil
   387  	} else {
   388  		return errors.New("unknown VolumeFormat: " + txt)
   389  	}
   390  }
   391  
   392  func (volumeType VolumeType) MarshalText() ([]byte, error) {
   393  	if text := volumeType.String(); text == volumeTypeUnknown {
   394  		return nil, errors.New(text)
   395  	} else {
   396  		return []byte(text), nil
   397  	}
   398  }
   399  
   400  func (volumeType *VolumeType) Set(value string) error {
   401  	if val, ok := textToVolumeType[value]; !ok {
   402  		return errors.New(volumeTypeUnknown)
   403  	} else {
   404  		*volumeType = val
   405  		return nil
   406  	}
   407  }
   408  
   409  func (volumeType VolumeType) String() string {
   410  	if text, ok := volumeTypeToText[volumeType]; ok {
   411  		return text
   412  	} else {
   413  		return volumeTypeUnknown
   414  	}
   415  }
   416  
   417  func (volumeType *VolumeType) UnmarshalText(text []byte) error {
   418  	txt := string(text)
   419  	if val, ok := textToVolumeType[txt]; ok {
   420  		*volumeType = val
   421  		return nil
   422  	} else {
   423  		return errors.New("unknown VolumeType: " + txt)
   424  	}
   425  }