blob: ff0d587278faf9cc67dcad24da02b608539bc08e [file] [log] [blame]
Joe Topjian27a62432015-04-18 01:48:50 +00001package schedulerhints
2
3import (
Joe Topjian27a62432015-04-18 01:48:50 +00004 "net"
5 "regexp"
6 "strings"
7
Krzysztof Szukiełojć3f41d082017-05-07 14:43:06 +02008 "gerrit.mcp.mirantis.net/debian/gophercloud.git"
Krzysztof Szukiełojć24a29ce2017-05-07 14:24:02 +02009 "gerrit.mcp.mirantis.net/debian/gophercloud.git/openstack/compute/v2/servers"
Joe Topjian27a62432015-04-18 01:48:50 +000010)
11
12// SchedulerHints represents a set of scheduling hints that are passed to the
13// OpenStack scheduler
14type SchedulerHints struct {
15 // Group specifies a Server Group to place the instance in.
16 Group string
Joe Topjian27a62432015-04-18 01:48:50 +000017 // DifferentHost will place the instance on a compute node that does not
18 // host the given instances.
19 DifferentHost []string
Joe Topjian27a62432015-04-18 01:48:50 +000020 // SameHost will place the instance on a compute node that hosts the given
21 // instances.
22 SameHost []string
Joe Topjian27a62432015-04-18 01:48:50 +000023 // Query is a conditional statement that results in compute nodes able to
24 // host the instance.
Joe Topjian7d6989c2015-05-05 20:38:08 +000025 Query []interface{}
Joe Topjian27a62432015-04-18 01:48:50 +000026 // TargetCell specifies a cell name where the instance will be placed.
Jon Perrittdb0ae142016-03-13 00:33:41 -060027 TargetCell string `json:"target_cell,omitempty"`
Joe Topjian27a62432015-04-18 01:48:50 +000028 // BuildNearHostIP specifies a subnet of compute nodes to host the instance.
29 BuildNearHostIP string
30}
31
Jon Perrittdb0ae142016-03-13 00:33:41 -060032// CreateOptsBuilder builds the scheduler hints into a serializable format.
33type CreateOptsBuilder interface {
34 ToServerSchedulerHintsCreateMap() (map[string]interface{}, error)
Joe Topjian27a62432015-04-18 01:48:50 +000035}
36
37// ToServerSchedulerHintsMap builds the scheduler hints into a serializable format.
Jon Perrittdb0ae142016-03-13 00:33:41 -060038func (opts SchedulerHints) ToServerSchedulerHintsCreateMap() (map[string]interface{}, error) {
Joe Topjian27a62432015-04-18 01:48:50 +000039 sh := make(map[string]interface{})
40
41 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}$")
42
43 if opts.Group != "" {
44 if !uuidRegex.MatchString(opts.Group) {
Jon Perrittf094fef2016-03-07 01:41:59 -060045 err := gophercloud.ErrInvalidInput{}
Jon Perrittf094fef2016-03-07 01:41:59 -060046 err.Argument = "schedulerhints.SchedulerHints.Group"
47 err.Value = opts.Group
48 err.Info = "Group must be a UUID"
49 return nil, err
Joe Topjian27a62432015-04-18 01:48:50 +000050 }
51 sh["group"] = opts.Group
52 }
53
54 if len(opts.DifferentHost) > 0 {
55 for _, diffHost := range opts.DifferentHost {
56 if !uuidRegex.MatchString(diffHost) {
Jon Perrittf094fef2016-03-07 01:41:59 -060057 err := gophercloud.ErrInvalidInput{}
Jon Perrittf094fef2016-03-07 01:41:59 -060058 err.Argument = "schedulerhints.SchedulerHints.DifferentHost"
59 err.Value = opts.DifferentHost
60 err.Info = "The hosts must be in UUID format."
61 return nil, err
Joe Topjian27a62432015-04-18 01:48:50 +000062 }
63 }
64 sh["different_host"] = opts.DifferentHost
65 }
66
67 if len(opts.SameHost) > 0 {
68 for _, sameHost := range opts.SameHost {
69 if !uuidRegex.MatchString(sameHost) {
Jon Perrittf094fef2016-03-07 01:41:59 -060070 err := gophercloud.ErrInvalidInput{}
Jon Perrittf094fef2016-03-07 01:41:59 -060071 err.Argument = "schedulerhints.SchedulerHints.SameHost"
72 err.Value = opts.SameHost
73 err.Info = "The hosts must be in UUID format."
74 return nil, err
Joe Topjian27a62432015-04-18 01:48:50 +000075 }
76 }
77 sh["same_host"] = opts.SameHost
78 }
79
80 /* Query can be something simple like:
81 [">=", "$free_ram_mb", 1024]
82
83 Or more complex like:
84 ['and',
85 ['>=', '$free_ram_mb', 1024],
86 ['>=', '$free_disk_mb', 200 * 1024]
87 ]
88
89 Because of the possible complexity, just make sure the length is a minimum of 3.
90 */
91 if len(opts.Query) > 0 {
92 if len(opts.Query) < 3 {
Jon Perrittf094fef2016-03-07 01:41:59 -060093 err := gophercloud.ErrInvalidInput{}
Jon Perrittf094fef2016-03-07 01:41:59 -060094 err.Argument = "schedulerhints.SchedulerHints.Query"
95 err.Value = opts.Query
96 err.Info = "Must be a conditional statement in the format of [op,variable,value]"
97 return nil, err
Joe Topjian27a62432015-04-18 01:48:50 +000098 }
99 sh["query"] = opts.Query
100 }
101
102 if opts.TargetCell != "" {
103 sh["target_cell"] = opts.TargetCell
104 }
105
106 if opts.BuildNearHostIP != "" {
107 if _, _, err := net.ParseCIDR(opts.BuildNearHostIP); err != nil {
Jon Perrittf094fef2016-03-07 01:41:59 -0600108 err := gophercloud.ErrInvalidInput{}
Jon Perrittf094fef2016-03-07 01:41:59 -0600109 err.Argument = "schedulerhints.SchedulerHints.BuildNearHostIP"
110 err.Value = opts.BuildNearHostIP
111 err.Info = "Must be a valid subnet in the form 192.168.1.1/24"
112 return nil, err
Joe Topjian27a62432015-04-18 01:48:50 +0000113 }
114 ipParts := strings.Split(opts.BuildNearHostIP, "/")
115 sh["build_near_host_ip"] = ipParts[0]
116 sh["cidr"] = "/" + ipParts[1]
117 }
118
119 return sh, nil
120}
121
122// CreateOptsExt adds a SchedulerHints option to the base CreateOpts.
123type CreateOptsExt struct {
124 servers.CreateOptsBuilder
Joe Topjian27a62432015-04-18 01:48:50 +0000125 // SchedulerHints provides a set of hints to the scheduler.
Jon Perrittdb0ae142016-03-13 00:33:41 -0600126 SchedulerHints CreateOptsBuilder
Joe Topjian27a62432015-04-18 01:48:50 +0000127}
128
129// ToServerCreateMap adds the SchedulerHints option to the base server creation options.
130func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
131 base, err := opts.CreateOptsBuilder.ToServerCreateMap()
132 if err != nil {
133 return nil, err
134 }
135
Jon Perrittdb0ae142016-03-13 00:33:41 -0600136 schedulerHints, err := opts.SchedulerHints.ToServerSchedulerHintsCreateMap()
Joe Topjian27a62432015-04-18 01:48:50 +0000137 if err != nil {
138 return nil, err
139 }
140
141 if len(schedulerHints) == 0 {
142 return base, nil
143 }
144
145 base["os:scheduler_hints"] = schedulerHints
146
147 return base, nil
148}