github.com/huaweicloud/golangsdk@v0.0.0-20210831081626-d823fe11ceba/openstack/compute/v2/extensions/schedulerhints/requests.go (about) 1 package schedulerhints 2 3 import ( 4 "net" 5 "regexp" 6 "strings" 7 8 "github.com/huaweicloud/golangsdk" 9 "github.com/huaweicloud/golangsdk/openstack/compute/v2/servers" 10 ) 11 12 // SchedulerHints represents a set of scheduling hints that are passed to the 13 // OpenStack scheduler. 14 type SchedulerHints struct { 15 // Group specifies a Server Group to place the instance in. 16 Group string 17 18 // DifferentHost will place the instance on a compute node that does not 19 // host the given instances. 20 DifferentHost []string 21 22 // SameHost will place the instance on a compute node that hosts the given 23 // instances. 24 SameHost []string 25 26 // Query is a conditional statement that results in compute nodes able to 27 // host the instance. 28 Query []interface{} 29 30 // TargetCell specifies a cell name where the instance will be placed. 31 TargetCell string `json:"target_cell,omitempty"` 32 33 // BuildNearHostIP specifies a subnet of compute nodes to host the instance. 34 BuildNearHostIP string 35 36 // AdditionalProperies are arbitrary key/values that are not validated by nova. 37 AdditionalProperties map[string]interface{} 38 39 // Specifies whether the ECS is created on a Dedicated Host (DeH) or in a shared pool. 40 Tenancy string `json:"tenancy,omitempty"` 41 42 // DedicatedHostID specifies a DeH ID. 43 DedicatedHostID string `json:"dedicated_host_id,omitempty"` 44 } 45 46 // CreateOptsBuilder builds the scheduler hints into a serializable format. 47 type CreateOptsBuilder interface { 48 ToServerSchedulerHintsCreateMap() (map[string]interface{}, error) 49 } 50 51 // ToServerSchedulerHintsMap builds the scheduler hints into a serializable format. 52 func (opts SchedulerHints) ToServerSchedulerHintsCreateMap() (map[string]interface{}, error) { 53 sh := make(map[string]interface{}) 54 55 uuidRegex, _ := regexp.Compile("^[a-z0-9]{8}-[a-z0-9]{4}-[1-5][a-z0-9]{3}-[a-z0-9]{4}-[a-z0-9]{12}$") 56 57 if opts.Group != "" { 58 if !uuidRegex.MatchString(opts.Group) { 59 err := golangsdk.ErrInvalidInput{} 60 err.Argument = "schedulerhints.SchedulerHints.Group" 61 err.Value = opts.Group 62 err.Info = "Group must be a UUID" 63 return nil, err 64 } 65 sh["group"] = opts.Group 66 } 67 68 if len(opts.DifferentHost) > 0 { 69 for _, diffHost := range opts.DifferentHost { 70 if !uuidRegex.MatchString(diffHost) { 71 err := golangsdk.ErrInvalidInput{} 72 err.Argument = "schedulerhints.SchedulerHints.DifferentHost" 73 err.Value = opts.DifferentHost 74 err.Info = "The hosts must be in UUID format." 75 return nil, err 76 } 77 } 78 sh["different_host"] = opts.DifferentHost 79 } 80 81 if len(opts.SameHost) > 0 { 82 for _, sameHost := range opts.SameHost { 83 if !uuidRegex.MatchString(sameHost) { 84 err := golangsdk.ErrInvalidInput{} 85 err.Argument = "schedulerhints.SchedulerHints.SameHost" 86 err.Value = opts.SameHost 87 err.Info = "The hosts must be in UUID format." 88 return nil, err 89 } 90 } 91 sh["same_host"] = opts.SameHost 92 } 93 94 /* 95 Query can be something simple like: 96 [">=", "$free_ram_mb", 1024] 97 98 Or more complex like: 99 ['and', 100 ['>=', '$free_ram_mb', 1024], 101 ['>=', '$free_disk_mb', 200 * 1024] 102 ] 103 104 Because of the possible complexity, just make sure the length is a minimum of 3. 105 */ 106 if len(opts.Query) > 0 { 107 if len(opts.Query) < 3 { 108 err := golangsdk.ErrInvalidInput{} 109 err.Argument = "schedulerhints.SchedulerHints.Query" 110 err.Value = opts.Query 111 err.Info = "Must be a conditional statement in the format of [op,variable,value]" 112 return nil, err 113 } 114 sh["query"] = opts.Query 115 } 116 117 if opts.TargetCell != "" { 118 sh["target_cell"] = opts.TargetCell 119 } 120 121 if opts.BuildNearHostIP != "" { 122 if _, _, err := net.ParseCIDR(opts.BuildNearHostIP); err != nil { 123 err := golangsdk.ErrInvalidInput{} 124 err.Argument = "schedulerhints.SchedulerHints.BuildNearHostIP" 125 err.Value = opts.BuildNearHostIP 126 err.Info = "Must be a valid subnet in the form 192.168.1.1/24" 127 return nil, err 128 } 129 ipParts := strings.Split(opts.BuildNearHostIP, "/") 130 sh["build_near_host_ip"] = ipParts[0] 131 sh["cidr"] = "/" + ipParts[1] 132 } 133 134 if opts.AdditionalProperties != nil { 135 for k, v := range opts.AdditionalProperties { 136 sh[k] = v 137 } 138 } 139 140 if opts.Tenancy != "" { 141 sh["tenancy"] = opts.Tenancy 142 } 143 144 if opts.DedicatedHostID != "" { 145 sh["dedicated_host_id"] = opts.DedicatedHostID 146 } 147 148 return sh, nil 149 } 150 151 // CreateOptsExt adds a SchedulerHints option to the base CreateOpts. 152 type CreateOptsExt struct { 153 servers.CreateOptsBuilder 154 155 // SchedulerHints provides a set of hints to the scheduler. 156 SchedulerHints CreateOptsBuilder 157 } 158 159 // ToServerCreateMap adds the SchedulerHints option to the base server creation options. 160 func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) { 161 base, err := opts.CreateOptsBuilder.ToServerCreateMap() 162 if err != nil { 163 return nil, err 164 } 165 166 schedulerHints, err := opts.SchedulerHints.ToServerSchedulerHintsCreateMap() 167 if err != nil { 168 return nil, err 169 } 170 171 if len(schedulerHints) == 0 { 172 return base, nil 173 } 174 175 base["os:scheduler_hints"] = schedulerHints 176 177 return base, nil 178 }