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 }