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 56f884843a..a578650612 100644 --- a/vmware_nsx/plugins/nsx_v/plugin.py +++ b/vmware_nsx/plugins/nsx_v/plugin.py @@ -192,6 +192,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 @@ -3010,6 +3012,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 27d1de9c40..4f8a09c172 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 8f25e1fdeb..ebbb0dffb4 100644 --- a/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py +++ b/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py @@ -1099,6 +1099,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