diff --git a/vmware_nsx/plugins/nsx_v/vshield/vcns.py b/vmware_nsx/plugins/nsx_v/vshield/vcns.py index 1a7b99f461..27d1de9c40 100644 --- a/vmware_nsx/plugins/nsx_v/vshield/vcns.py +++ b/vmware_nsx/plugins/nsx_v/vshield/vcns.py @@ -891,6 +891,10 @@ class Vcns(object): (edge_id, size)) return self.do_request(HTTP_POST, uri) + def change_edge_appliance(self, edge_id, request): + uri = "/api/4.0/edges/%s/appliances" % edge_id + return self.do_request(HTTP_PUT, uri, request) + def upload_edge_certificate(self, edge_id, request): """Creates a certificate on the specified Edge appliance.""" uri = '%s/%s/%s' % (TRUSTSTORE_PREFIX, CERTIFICATE, edge_id) diff --git a/vmware_nsx/shell/admin/plugins/nsxv/resources/edges.py b/vmware_nsx/shell/admin/plugins/nsxv/resources/edges.py index 3253652fe3..3aec9d7403 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv/resources/edges.py +++ b/vmware_nsx/shell/admin/plugins/nsxv/resources/edges.py @@ -25,6 +25,7 @@ import vmware_nsx.shell.resources as shell from neutron.callbacks import registry from neutron_lib import exceptions +from oslo_config import cfg from vmware_nsx._i18n import _LE, _LI from vmware_nsx.db import nsxv_db @@ -191,13 +192,51 @@ def change_edge_appliance_size(properties): LOG.error(_LE("%s"), str(e)) +def _get_edge_resource_pool_and_size(edge_id): + edgeapi = utils.NeutronDbClient() + binding = nsxv_db.get_nsxv_router_binding_by_edge( + edgeapi.context.session, edge_id) + if binding: + return binding['resource_pool'], binding['appliance_size'] + # default fallback + return cfg.CONF.nsxv.resource_pool_id, nsxv_constants.LARGE + + +def change_edge_appliance(edge_id): + """Update the appliances data of an edge + + Update the edge appliances data according to the current + nsx.ini config, including the edge_ha, datastore & ha_datastore. + The resource pool will not be modified. + """ + datastore_id = cfg.CONF.nsxv.datastore_id + ha_datastore_id = cfg.CONF.nsxv.ha_datastore_id + edge_ha = cfg.CONF.nsxv.edge_ha + # find out what is the current resource pool & size, so we can keep them + resource_pool, size = _get_edge_resource_pool_and_size(edge_id) + appliances = [{'resourcePoolId': resource_pool, + 'datastoreId': datastore_id}] + if ha_datastore_id and edge_ha: + appliances.append({'resourcePoolId': resource_pool, + 'datastoreId': ha_datastore_id}) + request = {'appliances': appliances, 'applianceSize': size} + try: + nsxv.change_edge_appliance(edge_id, request) + except nsxv_exceptions.ResourceNotFound as e: + LOG.error(_LE("Edge %s not found"), edge_id) + except exceptions.NeutronException as e: + LOG.error(_LE("%s"), str(e)) + + @admin_utils.output_header def nsx_update_edge(resource, event, trigger, **kwargs): """Update edge properties""" + usage_msg = _LE("Need to specify edge-id parameter and " + "attribute to update. Add --property edge-id= " + "and --property highavailability= or " + "--property size= or --property appliances=True") if not kwargs.get('property'): - LOG.error(_LE("Need to specify edge-id parameter and " - "attribute to update. Add --property edge-id= " - "--property highavailability=True")) + LOG.error(usage_msg) return properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) if not properties.get('edge-id'): @@ -210,6 +249,12 @@ def nsx_update_edge(resource, event, trigger, **kwargs): change_edge_ha(properties) elif properties.get('size'): change_edge_appliance_size(properties) + elif (properties.get('appliances') and + properties.get('appliances').lower() == "true"): + change_edge_appliance(properties['edge-id']) + else: + # no attribute was specified + LOG.error(usage_msg) registry.subscribe(nsx_list_edges, 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 291a042418..4830fe4b07 100644 --- a/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py +++ b/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py @@ -1182,6 +1182,13 @@ class FakeVcns(object): response = {} return (header, response) + def change_edge_appliance(self, edge_id, request): + header = { + 'status': 204 + } + response = {} + return (header, response) + def get_routes(self, edge_id): header = { 'status': 204