From ae8184fa1591eec91ac9634f769a3a9a25945b09 Mon Sep 17 00:00:00 2001 From: Gary Kotton Date: Sun, 13 Mar 2016 01:00:37 -0800 Subject: [PATCH] NSX|V: add in edge resource configuration support Version 6.2.3 enables on to configure edge resources. This patch ensures that no reservations will take place. This will also enable us in the future to expose this feature. The patch also adds in a utility that can be run out of band. This can be done if the NSX is upgraded to 6.2.3 and the plugin will not need to be restarted. Change-Id: I19a8e7371047f1e274dddf8d734b126289167fad --- devstack/tools/nsxv_edge_resources.py | 110 ++++++++++++++++++ vmware_nsx/plugins/nsx_v/plugin.py | 13 +++ vmware_nsx/plugins/nsx_v/vshield/vcns.py | 17 +++ .../tests/unit/nsx_v/vshield/fake_vcns.py | 3 + 4 files changed, 143 insertions(+) create mode 100644 devstack/tools/nsxv_edge_resources.py diff --git a/devstack/tools/nsxv_edge_resources.py b/devstack/tools/nsxv_edge_resources.py new file mode 100644 index 0000000000..6ac639c092 --- /dev/null +++ b/devstack/tools/nsxv_edge_resources.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# Copyright 2015 VMware Inc +# All Rights Reserved +# +# 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. + +""" +Purpose: Configure edge resource limits + +Usage: + python nsxv_edge_resources.py --vsm-ip + --username + --password +""" + +import base64 +import optparse + +from oslo_serialization import jsonutils +import requests +import six +import xml.etree.ElementTree as et + +requests.packages.urllib3.disable_warnings() + + +class NSXClient(object): + + def __init__(self, host, username, password, *args, **kwargs): + self._host = host + self._username = username + self._password = password + + def _get_headers(self, format): + auth_cred = self._username + ":" + self._password + auth = base64.b64encode(auth_cred) + headers = {} + headers['Authorization'] = "Basic %s" % auth + headers['Content-Type'] = "application/%s" % format + headers['Accept'] = "application/%s" % format + return headers + + def _get_url(self, uri): + return 'https://%s/%s' % (self._host, uri) + + def _get(self, format, uri): + headers = self._get_headers(format) + url = self._get_url(uri) + response = requests.get(url, headers=headers, + verify=False) + return response + + def _put(self, format, uri, data): + headers = self._get_headers(format) + url = self._get_url(uri) + response = requests.put(url, headers=headers, + verify=False, data=data) + return response + + def _get_tuning_configration(self): + response = self._get("json", + "/api/4.0/edgePublish/tuningConfiguration") + return jsonutils.loads(response.text) + + def configure_reservations(self): + config = self._get_tuning_configration() + # NSX only receive XML format for the resource allocation update + tuning = et.Element('tuningConfiguration') + for opt, val in six.iteritems(config): + child = et.Element(opt) + if (opt == 'edgeVCpuReservationPercentage' or + opt == 'edgeMemoryReservationPercentage'): + child.text = '0' + elif opt == 'megaHertzPerVCpu': + child.text = '1500' + else: + child.text = str(val) + tuning.append(child) + self._put("xml", + "/api/4.0/edgePublish/tuningConfiguration", + et.tostring(tuning)) + print ("Edge resource limits set") + + +if __name__ == "__main__": + + parser = optparse.OptionParser() + parser.add_option("--vsm-ip", dest="vsm_ip", help="NSX Manager IP address") + parser.add_option("-u", "--username", default="admin", dest="username", + help="NSX Manager username") + parser.add_option("-p", "--password", default="default", dest="password", + help="NSX Manager password") + (options, args) = parser.parse_args() + print ("vsm-ip: %s" % options.vsm_ip) + print ("username: %s" % options.username) + print ("password: %s" % options.password) + + nsx_client = NSXClient(options.vsm_ip, options.username, + options.password) + nsx_client.configure_reservations() diff --git a/vmware_nsx/plugins/nsx_v/plugin.py b/vmware_nsx/plugins/nsx_v/plugin.py index 462449bb99..8599767f4e 100644 --- a/vmware_nsx/plugins/nsx_v/plugin.py +++ b/vmware_nsx/plugins/nsx_v/plugin.py @@ -188,6 +188,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin, self._ensure_lock_operations() # Configure aggregate publishing self._aggregate_publishing() + # Configure edge reservations + self._configure_reservations() self.edge_manager = edge_utils.EdgeManager(self.nsx_v, self) self.vdn_scope_id = cfg.CONF.nsxv.vdn_scope_id self.dvs_id = cfg.CONF.nsxv.dvs_id @@ -2972,6 +2974,17 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin, except Exception: LOG.info(_LI("Unable to configure aggregate publishing")) + def _configure_reservations(self): + ver = self.nsx_v.vcns.get_version() + if version.LooseVersion(ver) < version.LooseVersion('6.2.3'): + LOG.debug("Skipping reservation configuration. " + "Not supported by version - %s.", ver) + return + try: + self.nsx_v.vcns.configure_reservations() + except Exception: + LOG.info(_LI("Unable to configure edge reservations")) + def _validate_config(self): if (cfg.CONF.nsxv.dvs_id and not self.nsx_v.vcns.validate_dvs(cfg.CONF.nsxv.dvs_id)): diff --git a/vmware_nsx/plugins/nsx_v/vshield/vcns.py b/vmware_nsx/plugins/nsx_v/vshield/vcns.py index 1a7b99f461..0083725d6b 100644 --- a/vmware_nsx/plugins/nsx_v/vshield/vcns.py +++ b/vmware_nsx/plugins/nsx_v/vshield/vcns.py @@ -878,6 +878,23 @@ class Vcns(object): return self.do_request(HTTP_PUT, uri, et.tostring(tuning), format='xml', decode=True) + def configure_reservations(self): + uri = "/api/4.0/edgePublish/tuningConfiguration" + config = self.get_tuning_configration() + tuning = et.Element('tuningConfiguration') + for opt, val in six.iteritems(config): + child = et.Element(opt) + if (opt == 'edgeVCpuReservationPercentage' or + opt == 'edgeMemoryReservationPercentage'): + child.text = '0' + elif opt == 'megaHertzPerVCpu': + child.text = '1500' + else: + child.text = str(val) + tuning.append(child) + return self.do_request(HTTP_PUT, uri, et.tostring(tuning), + format='xml', decode=True) + def enable_ha(self, edge_id, request_config, async=True): """Enable HA in the given edge.""" uri = "/api/4.0/edges/%s/highavailability/config" % edge_id diff --git a/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py b/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py index b16c6237fc..b162d5ff96 100644 --- a/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py +++ b/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py @@ -1069,6 +1069,9 @@ class FakeVcns(object): def publish_assigned_addresses(self, policy_id, vnic_id): pass + def configure_reservations(self): + pass + def inactivate_vnic_assigned_addresses(self, policy_id, vnic_id): pass