From 7aecce88a3d699fe836ca237c919ff9867bdb1ba Mon Sep 17 00:00:00 2001 From: Levi Blackstone Date: Thu, 30 Aug 2018 16:44:28 -0600 Subject: [PATCH] OpenStack: vendor schedulerhints --- Gopkg.lock | 4 +- .../pkg/fi/cloudup/openstacktasks/BUILD.bazel | 2 + .../pkg/fi/cloudup/openstacktasks/instance.go | 22 +++ .../v2/extensions/schedulerhints/BUILD.bazel | 16 ++ .../v2/extensions/schedulerhints/doc.go | 76 ++++++++ .../v2/extensions/schedulerhints/requests.go | 164 ++++++++++++++++++ 6 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 upup/pkg/fi/cloudup/openstacktasks/instance.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints/BUILD.bazel create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints/doc.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints/requests.go diff --git a/Gopkg.lock b/Gopkg.lock index 943d06240e..b3f3d02de3 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -610,13 +610,14 @@ revision = "0c5108395e2debce0d731cf0287ddf7242066aba" [[projects]] - digest = "1:5df55e3834b01308cf93fdaf6118fc1ad8418a3bb954bcfaa4b060545a94d4ca" + digest = "1:dc8be055c0a43584d2b728953be6d507c8a48a9b6e055c2dffdb8d8414eb703b" name = "github.com/gophercloud/gophercloud" packages = [ ".", "openstack", "openstack/blockstorage/v2/volumes", "openstack/compute/v2/extensions/keypairs", + "openstack/compute/v2/extensions/schedulerhints", "openstack/compute/v2/extensions/servergroups", "openstack/compute/v2/flavors", "openstack/compute/v2/images", @@ -2150,6 +2151,7 @@ "github.com/gophercloud/gophercloud/openstack", "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes", "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs", + "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints", "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups", "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers", "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups", diff --git a/upup/pkg/fi/cloudup/openstacktasks/BUILD.bazel b/upup/pkg/fi/cloudup/openstacktasks/BUILD.bazel index f1ee10b059..5362530e73 100644 --- a/upup/pkg/fi/cloudup/openstacktasks/BUILD.bazel +++ b/upup/pkg/fi/cloudup/openstacktasks/BUILD.bazel @@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ + "instance.go", "network.go", "network_fitask.go", "router.go", @@ -28,6 +29,7 @@ go_library( "//vendor/github.com/gophercloud/gophercloud:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs:go_default_library", + "//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules:go_default_library", diff --git a/upup/pkg/fi/cloudup/openstacktasks/instance.go b/upup/pkg/fi/cloudup/openstacktasks/instance.go new file mode 100644 index 0000000000..a7cceee686 --- /dev/null +++ b/upup/pkg/fi/cloudup/openstacktasks/instance.go @@ -0,0 +1,22 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package openstacktasks + +import "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints" + +// TODO(lmb): Remove after implementing. Using this to pull in the vendor dep. +var _ schedulerhints.SchedulerHints diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints/BUILD.bazel b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints/BUILD.bazel new file mode 100644 index 0000000000..b73ee52209 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints/BUILD.bazel @@ -0,0 +1,16 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "requests.go", + ], + importmap = "vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints", + importpath = "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/gophercloud/gophercloud:go_default_library", + "//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers:go_default_library", + ], +) diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints/doc.go new file mode 100644 index 0000000000..2d9d3acdec --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints/doc.go @@ -0,0 +1,76 @@ +/* +Package schedulerhints extends the server create request with the ability to +specify additional parameters which determine where the server will be +created in the OpenStack cloud. + +Example to Add a Server to a Server Group + + schedulerHints := schedulerhints.SchedulerHints{ + Group: "servergroup-uuid", + } + + serverCreateOpts := servers.CreateOpts{ + Name: "server_name", + ImageRef: "image-uuid", + FlavorRef: "flavor-uuid", + } + + createOpts := schedulerhints.CreateOptsExt{ + CreateOptsBuilder: serverCreateOpts, + SchedulerHints: schedulerHints, + } + + server, err := servers.Create(computeClient, createOpts).Extract() + if err != nil { + panic(err) + } + +Example to Place Server B on a Different Host than Server A + + schedulerHints := schedulerhints.SchedulerHints{ + DifferentHost: []string{ + "server-a-uuid", + } + } + + serverCreateOpts := servers.CreateOpts{ + Name: "server_b", + ImageRef: "image-uuid", + FlavorRef: "flavor-uuid", + } + + createOpts := schedulerhints.CreateOptsExt{ + CreateOptsBuilder: serverCreateOpts, + SchedulerHints: schedulerHints, + } + + server, err := servers.Create(computeClient, createOpts).Extract() + if err != nil { + panic(err) + } + +Example to Place Server B on the Same Host as Server A + + schedulerHints := schedulerhints.SchedulerHints{ + SameHost: []string{ + "server-a-uuid", + } + } + + serverCreateOpts := servers.CreateOpts{ + Name: "server_b", + ImageRef: "image-uuid", + FlavorRef: "flavor-uuid", + } + + createOpts := schedulerhints.CreateOptsExt{ + CreateOptsBuilder: serverCreateOpts, + SchedulerHints: schedulerHints, + } + + server, err := servers.Create(computeClient, createOpts).Extract() + if err != nil { + panic(err) + } +*/ +package schedulerhints diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints/requests.go new file mode 100644 index 0000000000..3fabeddef3 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints/requests.go @@ -0,0 +1,164 @@ +package schedulerhints + +import ( + "net" + "regexp" + "strings" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" +) + +// SchedulerHints represents a set of scheduling hints that are passed to the +// OpenStack scheduler. +type SchedulerHints struct { + // Group specifies a Server Group to place the instance in. + Group string + + // DifferentHost will place the instance on a compute node that does not + // host the given instances. + DifferentHost []string + + // SameHost will place the instance on a compute node that hosts the given + // instances. + SameHost []string + + // Query is a conditional statement that results in compute nodes able to + // host the instance. + Query []interface{} + + // TargetCell specifies a cell name where the instance will be placed. + TargetCell string `json:"target_cell,omitempty"` + + // BuildNearHostIP specifies a subnet of compute nodes to host the instance. + BuildNearHostIP string + + // AdditionalProperies are arbitrary key/values that are not validated by nova. + AdditionalProperties map[string]interface{} +} + +// CreateOptsBuilder builds the scheduler hints into a serializable format. +type CreateOptsBuilder interface { + ToServerSchedulerHintsCreateMap() (map[string]interface{}, error) +} + +// ToServerSchedulerHintsMap builds the scheduler hints into a serializable format. +func (opts SchedulerHints) ToServerSchedulerHintsCreateMap() (map[string]interface{}, error) { + sh := make(map[string]interface{}) + + 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}$") + + if opts.Group != "" { + if !uuidRegex.MatchString(opts.Group) { + err := gophercloud.ErrInvalidInput{} + err.Argument = "schedulerhints.SchedulerHints.Group" + err.Value = opts.Group + err.Info = "Group must be a UUID" + return nil, err + } + sh["group"] = opts.Group + } + + if len(opts.DifferentHost) > 0 { + for _, diffHost := range opts.DifferentHost { + if !uuidRegex.MatchString(diffHost) { + err := gophercloud.ErrInvalidInput{} + err.Argument = "schedulerhints.SchedulerHints.DifferentHost" + err.Value = opts.DifferentHost + err.Info = "The hosts must be in UUID format." + return nil, err + } + } + sh["different_host"] = opts.DifferentHost + } + + if len(opts.SameHost) > 0 { + for _, sameHost := range opts.SameHost { + if !uuidRegex.MatchString(sameHost) { + err := gophercloud.ErrInvalidInput{} + err.Argument = "schedulerhints.SchedulerHints.SameHost" + err.Value = opts.SameHost + err.Info = "The hosts must be in UUID format." + return nil, err + } + } + sh["same_host"] = opts.SameHost + } + + /* + Query can be something simple like: + [">=", "$free_ram_mb", 1024] + + Or more complex like: + ['and', + ['>=', '$free_ram_mb', 1024], + ['>=', '$free_disk_mb', 200 * 1024] + ] + + Because of the possible complexity, just make sure the length is a minimum of 3. + */ + if len(opts.Query) > 0 { + if len(opts.Query) < 3 { + err := gophercloud.ErrInvalidInput{} + err.Argument = "schedulerhints.SchedulerHints.Query" + err.Value = opts.Query + err.Info = "Must be a conditional statement in the format of [op,variable,value]" + return nil, err + } + sh["query"] = opts.Query + } + + if opts.TargetCell != "" { + sh["target_cell"] = opts.TargetCell + } + + if opts.BuildNearHostIP != "" { + if _, _, err := net.ParseCIDR(opts.BuildNearHostIP); err != nil { + err := gophercloud.ErrInvalidInput{} + err.Argument = "schedulerhints.SchedulerHints.BuildNearHostIP" + err.Value = opts.BuildNearHostIP + err.Info = "Must be a valid subnet in the form 192.168.1.1/24" + return nil, err + } + ipParts := strings.Split(opts.BuildNearHostIP, "/") + sh["build_near_host_ip"] = ipParts[0] + sh["cidr"] = "/" + ipParts[1] + } + + if opts.AdditionalProperties != nil { + for k, v := range opts.AdditionalProperties { + sh[k] = v + } + } + + return sh, nil +} + +// CreateOptsExt adds a SchedulerHints option to the base CreateOpts. +type CreateOptsExt struct { + servers.CreateOptsBuilder + + // SchedulerHints provides a set of hints to the scheduler. + SchedulerHints CreateOptsBuilder +} + +// ToServerCreateMap adds the SchedulerHints option to the base server creation options. +func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) { + base, err := opts.CreateOptsBuilder.ToServerCreateMap() + if err != nil { + return nil, err + } + + schedulerHints, err := opts.SchedulerHints.ToServerSchedulerHintsCreateMap() + if err != nil { + return nil, err + } + + if len(schedulerHints) == 0 { + return base, nil + } + + base["os:scheduler_hints"] = schedulerHints + + return base, nil +}