summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoe Gordon <jogo@cloudscaling.com>2012-12-20 03:13:01 +0000
committerJoe Gordon <jogo@cloudscaling.com>2013-01-08 14:01:30 -0800
commit1ab2fc6477c402e29a95fbc93fe4a67950c083df (patch)
treeed42c15787905fe9e42ca3058bc8db3737d2fcbb
parent9f4534ab584faeee1e24d4c1bb38a2b194f24626 (diff)
downloadnova-1ab2fc6477c402e29a95fbc93fe4a67950c083df.tar.gz
nova-1ab2fc6477c402e29a95fbc93fe4a67950c083df.tar.xz
nova-1ab2fc6477c402e29a95fbc93fe4a67950c083df.zip
Remove availability_zones from service table
This is the final step in enabling availability_zones using aggregate metadata. Previously all services had an availability_zone, but the availability_zone is only used for nova-compute. Services such as nova-scheduler, nova-network, nova-conductor have always spanned all availability_zones. After this change only compute nodes (nova-compute), will have an availability_zone. In order to preserve current APIs, when running: * nova host-list (os-hosts) * euca-describe-availability-zones verbose * nova-manage service list Internal services will appear in there own internal availability_zone (CONF.internal_service_availability_zone) Internal zone is hidden in euca-describe-availability_zones (non-verbose) CONF.node_availability_zone has been renamed to CONF.default_availability_zone and is only used by the nova-api and nova-scheduler. CONF.node_availability_zone still works but is deprecated DocImpact Completes blueprint aggregate-based-availability-zones Change-Id: Ib772df5f9ac2865f20df479f8ddce575a9ce3aff
-rwxr-xr-xbin/nova-manage3
-rw-r--r--doc/api_samples/os-hosts/hosts-list-resp.json10
-rw-r--r--nova/api/ec2/cloud.py43
-rw-r--r--nova/api/ec2/ec2utils.py3
-rw-r--r--nova/api/openstack/compute/contrib/hosts.py2
-rw-r--r--nova/availability_zones.py62
-rw-r--r--nova/compute/api.py5
-rw-r--r--nova/config.py3
-rw-r--r--nova/db/api.py6
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/147_no_service_zones.py83
-rw-r--r--nova/db/sqlalchemy/models.py1
-rw-r--r--nova/network/quantumv2/api.py5
-rw-r--r--nova/scheduler/filters/availability_zone_filter.py14
-rw-r--r--nova/service.py5
-rw-r--r--nova/servicegroup/db_driver.py3
-rw-r--r--nova/tests/api/ec2/test_cloud.py36
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_hosts.py14
-rw-r--r--nova/tests/compute/test_compute.py3
-rw-r--r--nova/tests/integrated/api_samples/os-hosts/hosts-list-resp.json.tpl8
-rw-r--r--nova/tests/network/test_quantumv2.py1
-rw-r--r--nova/tests/test_libvirt.py3
-rw-r--r--nova/tests/test_migrations.py58
-rw-r--r--nova/tests/test_service.py4
-rw-r--r--nova/tests/test_xenapi.py9
24 files changed, 291 insertions, 93 deletions
diff --git a/bin/nova-manage b/bin/nova-manage
index 45002cfd8..ba484a04e 100755
--- a/bin/nova-manage
+++ b/bin/nova-manage
@@ -70,6 +70,7 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'nova', '__init__.py')):
gettext.install('nova', unicode=1)
from nova.api.ec2 import ec2utils
+from nova import availability_zones
from nova.compute import instance_types
from nova.compute import rpcapi as compute_rpcapi
from nova import config
@@ -626,6 +627,7 @@ class ServiceCommands(object):
ctxt = context.get_admin_context()
now = timeutils.utcnow()
services = db.service_get_all(ctxt)
+ services = availability_zone.set_availability_zones(ctxt, services)
if host:
services = [s for s in services if s['host'] == host]
if service:
@@ -741,6 +743,7 @@ class HostCommands(object):
ctxt = context.get_admin_context()
now = timeutils.utcnow()
services = db.service_get_all(ctxt)
+ services = availability_zones.set_availability_zones(ctxt, services)
if zone:
services = [s for s in services if s['availability_zone'] == zone]
hosts = []
diff --git a/doc/api_samples/os-hosts/hosts-list-resp.json b/doc/api_samples/os-hosts/hosts-list-resp.json
index d4146c082..5a963c602 100644
--- a/doc/api_samples/os-hosts/hosts-list-resp.json
+++ b/doc/api_samples/os-hosts/hosts-list-resp.json
@@ -8,22 +8,22 @@
{
"host_name": "a98b433151084aee8b1a986e28823b36",
"service": "cert",
- "zone": "nova"
+ "zone": "internal"
},
{
"host_name": "c56158d13a884a87abf9171efb7de9d8",
"service": "network",
- "zone": "nova"
+ "zone": "internal"
},
{
"host_name": "81d5cdcda0014918b3ebd3503a2e5c9a",
"service": "scheduler",
- "zone": "nova"
+ "zone": "internal"
},
{
"host_name": "6e48bfe1a3304b7b86154326328750ae",
"service": "conductor",
- "zone": "nova"
+ "zone": "internal"
}
]
-} \ No newline at end of file
+}
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 208574903..a7162a101 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -28,6 +28,7 @@ import time
from nova.api.ec2 import ec2utils
from nova.api.ec2 import inst_state
from nova.api import validator
+from nova import availability_zones
from nova import block_device
from nova import compute
from nova.compute import api as compute_api
@@ -72,6 +73,8 @@ CONF.register_opts(ec2_opts)
CONF.import_opt('my_ip', 'nova.config')
CONF.import_opt('vpn_image_id', 'nova.config')
CONF.import_opt('vpn_key_suffix', 'nova.config')
+CONF.import_opt('internal_service_availability_zone',
+ 'nova.availability_zones')
LOG = logging.getLogger(__name__)
@@ -250,6 +253,10 @@ class CloudController(object):
"""Return available and unavailable zones."""
enabled_services = db.service_get_all(context, False)
disabled_services = db.service_get_all(context, True)
+ enabled_services = availability_zones.set_availability_zones(context,
+ enabled_services)
+ disabled_services = availability_zones.set_availability_zones(context,
+ disabled_services)
available_zones = []
for zone in [service['availability_zone'] for service
@@ -257,17 +264,11 @@ class CloudController(object):
if not zone in available_zones:
available_zones.append(zone)
- # aggregate based availability_zones
- metadata = db.aggregate_host_get_by_metadata_key(context,
- key='availability_zone')
- for zone_set in metadata.values():
- for zone in zone_set:
- if zone not in available_zones:
- available_zones.append(zone)
not_available_zones = []
- for zone in [service.availability_zone for service in disabled_services
- if not service['availability_zone'] in available_zones]:
- if not zone in not_available_zones:
+ zones = [service['available_zones'] for service in disabled_services
+ if service['available_zones'] not in available_zones]
+ for zone in zones:
+ if zone not in not_available_zones:
not_available_zones.append(zone)
return (available_zones, not_available_zones)
@@ -277,6 +278,9 @@ class CloudController(object):
result = []
for zone in available_zones:
+ # Hide internal_service_availability_zone
+ if zone == CONF.internal_service_availability_zone:
+ continue
result.append({'zoneName': zone,
'zoneState': "available"})
for zone in not_available_zones:
@@ -290,6 +294,8 @@ class CloudController(object):
# Available services
enabled_services = db.service_get_all(context, False)
+ enabled_services = availability_zones.set_availability_zones(context,
+ enabled_services)
zone_hosts = {}
host_services = {}
for service in enabled_services:
@@ -298,17 +304,10 @@ class CloudController(object):
zone_hosts[service['availability_zone']].append(
service['host'])
- host_services.setdefault(service['host'], [])
- host_services[service['host']].append(service)
- # aggregate based available_zones
- metadata = db.aggregate_host_get_by_metadata_key(context,
- key='availability_zone')
- # metdata: {machine: set( az1, az2 )}
- for host, zones in metadata.items():
- for zone in zones:
- zone_hosts.setdefault(zone, [])
- if host not in zone_hosts[zone]:
- zone_hosts[zone].append(host)
+ host_services.setdefault(service['availability_zone'] +
+ service['host'], [])
+ host_services[service['availability_zone'] + service['host']].\
+ append(service)
result = []
for zone in available_zones:
@@ -318,7 +317,7 @@ class CloudController(object):
result.append({'zoneName': '|- %s' % host,
'zoneState': ''})
- for service in host_services[host]:
+ for service in host_services[zone + host]:
alive = self.servicegroup_api.service_is_up(service)
art = (alive and ":-)") or "XXX"
active = 'enabled'
diff --git a/nova/api/ec2/ec2utils.py b/nova/api/ec2/ec2utils.py
index 1c2ceea6f..f86642ff6 100644
--- a/nova/api/ec2/ec2utils.py
+++ b/nova/api/ec2/ec2utils.py
@@ -18,6 +18,7 @@
import re
+from nova import availability_zones
from nova import context
from nova import db
from nova import exception
@@ -116,7 +117,7 @@ def get_ip_info_for_instance(context, instance):
def get_availability_zone_by_host(services, host):
if len(services) > 0:
- return services[0]['availability_zone']
+ return availability_zones.get_host_availability_zone(context, host)
return 'unknown zone'
diff --git a/nova/api/openstack/compute/contrib/hosts.py b/nova/api/openstack/compute/contrib/hosts.py
index 7da596a78..2401147f4 100644
--- a/nova/api/openstack/compute/contrib/hosts.py
+++ b/nova/api/openstack/compute/contrib/hosts.py
@@ -22,6 +22,7 @@ from xml.parsers import expat
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
+from nova import availability_zones
from nova.compute import api as compute_api
from nova import db
from nova import exception
@@ -99,6 +100,7 @@ def _list_hosts(req):
"""
context = req.environ['nova.context']
services = db.service_get_all(context, False)
+ services = availability_zones.set_availability_zones(context, services)
zone = ''
if 'zone' in req.GET:
zone = req.GET['zone']
diff --git a/nova/availability_zones.py b/nova/availability_zones.py
new file mode 100644
index 000000000..c08e029cf
--- /dev/null
+++ b/nova/availability_zones.py
@@ -0,0 +1,62 @@
+# Copyright (c) 2012 OpenStack, LLC.
+# 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.
+
+""" utilities for multiple APIs"""
+
+from nova import db
+from nova.openstack.common import cfg
+from nova.openstack.common import jsonutils
+from nova.openstack.common import log as logging
+
+availability_zone_opts = [
+ cfg.StrOpt('internal_service_availability_zone',
+ default='internal',
+ help='availability_zone to show internal services under'),
+ cfg.StrOpt('default_availability_zone',
+ # deprecated in Grizzly release
+ deprecated_name='node_availability_zone',
+ default='nova',
+ help='default compute node availability_zone'),
+ ]
+
+CONF = cfg.CONF
+CONF.register_opts(availability_zone_opts)
+
+LOG = logging.getLogger(__name__)
+
+
+def set_availability_zones(context, services):
+ # Makes sure services isn't a sqlalchemy object
+ services = [dict(service.iteritems()) for service in services]
+ metadata = db.aggregate_host_get_by_metadata_key(context,
+ key='availability_zone')
+ for service in services:
+ az = CONF.internal_service_availability_zone
+ if service['topic'] == "compute":
+ if metadata.get(service['host']):
+ az = str(metadata[service['host']])[5:-2]
+ else:
+ az = CONF.default_availability_zone
+ service['availability_zone'] = az
+ return services
+
+
+def get_host_availability_zone(context, host):
+ metadata = db.aggregate_metadata_get_by_host(
+ context.get_admin_context(), host, key='availability_zone')
+ if 'availability_zone' in metadata:
+ return list(metadata['availability_zone'])[0]
+ else:
+ return CONF.default_availability_zone
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 4ac04e790..c7a1d6126 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -2241,11 +2241,6 @@ class AggregateAPI(base.Base):
# validates the host; ComputeHostNotFound is raised if invalid
service = self.db.service_get_all_compute_by_host(context, host)[0]
aggregate = self.db.aggregate_get(context, aggregate_id)
- if service['availability_zone'] != aggregate['availability_zone']:
- raise exception.InvalidAggregateAction(
- action='add host',
- aggregate_id=aggregate_id,
- reason='availability zone mismatch')
self.db.aggregate_host_add(context, aggregate_id, host)
#NOTE(jogo): Send message to host to support resource pools
self.compute_rpcapi.add_aggregate_host(context,
diff --git a/nova/config.py b/nova/config.py
index c39adfd45..e5d65db23 100644
--- a/nova/config.py
+++ b/nova/config.py
@@ -118,9 +118,6 @@ global_opts = [
'However, the node name must be valid within '
'an AMQP key, and if using ZeroMQ, a valid '
'hostname, FQDN, or IP address'),
- cfg.StrOpt('node_availability_zone',
- default='nova',
- help='availability zone of this node'),
cfg.ListOpt('memcached_servers',
default=None,
help='Memcached servers or None for in process cache.'),
diff --git a/nova/db/api.py b/nova/db/api.py
index 8d93701c8..7f202862e 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -1546,8 +1546,10 @@ def aggregate_metadata_get_by_host(context, host, key=None):
def aggregate_host_get_by_metadata_key(context, key):
"""Get hosts with a specific metadata key metadata for all aggregates.
- Returns a dictionary where each key is a hostname and each value is the
- key value"""
+ Returns a dictionary where each key is a hostname and each value is a set
+ of the key values
+ return value: {machine: set( az1, az2 )}
+ """
return IMPL.aggregate_host_get_by_metadata_key(context, key)
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/147_no_service_zones.py b/nova/db/sqlalchemy/migrate_repo/versions/147_no_service_zones.py
new file mode 100644
index 000000000..a20799fbe
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/147_no_service_zones.py
@@ -0,0 +1,83 @@
+# Copyright 2012 OpenStack LLC.
+#
+# 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.
+
+from sqlalchemy import String, Column, MetaData, Table, select
+
+from nova.openstack.common import log as logging
+
+LOG = logging.getLogger(__name__)
+
+
+""" Remove availability_zone column from services model and replace with
+ aggregate based zone."""
+
+
+def upgrade(migrate_engine):
+ meta = MetaData()
+ meta.bind = migrate_engine
+
+ services = Table('services', meta, autoload=True)
+ aggregates = Table('aggregates', meta, autoload=True)
+ aggregate_metadata = Table('aggregate_metadata', meta, autoload=True)
+ # migrate data
+ record_list = list(services.select().execute())
+ for rec in record_list:
+ # Only need to migrate nova-compute availability_zones
+ if rec['binary'] != 'nova-compute':
+ continue
+ # if zone doesn't exist create
+ result = aggregate_metadata.select().where(aggregate_metadata.c.key ==
+ 'availability_zone' and
+ aggregate_metadata.c.key == rec['availability_zone']).execute()
+ result = [r for r in result]
+ if len(result) > 0:
+ agg_id = result[0].aggregate_id
+ else:
+ agg = aggregates.insert()
+ result = agg.execute({'name': rec['availability_zone']})
+ agg_id = result.inserted_primary_key[0]
+ row = aggregate_metadata.insert()
+ row.execute({'created_at': rec['created_at'],
+ 'updated_at': rec['updated_at'],
+ 'deleted_at': rec['deleted_at'],
+ 'deleted': rec['deleted'],
+ 'key': 'availability_zone',
+ 'value': rec['availability_zone'],
+ 'aggregate_id': agg_id,
+ })
+ # add host to zone
+ agg_hosts = Table('aggregate_hosts', meta, autoload=True)
+ row = agg_hosts.insert()
+ row.execute({'host': rec['host'], 'aggregate_id': agg_id})
+
+ services.drop_column('availability_zone')
+
+
+def downgrade(migrate_engine):
+ meta = MetaData()
+ meta.bind = migrate_engine
+
+ services = Table('services', meta, autoload=True)
+ aggregate_metadata = Table('aggregate_metadata', meta, autoload=True)
+ agg_hosts = Table('aggregate_hosts', meta, autoload=True)
+ availability_zone = Column('availability_zone', String(255),
+ default='nova')
+ services.create_column(availability_zone)
+ # migrate data
+ services.update().values(availability_zone=select(
+ [aggregate_metadata.c.value]).
+ where(agg_hosts.c.aggregate_id == aggregate_metadata.c.aggregate_id).
+ where(aggregate_metadata.c.key == 'availability_zone').
+ where(agg_hosts.c.host == services.c.host).
+ where(services.c.binary == 'nova-compute')).execute()
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 8a161efdf..2d3e23c26 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -106,7 +106,6 @@ class Service(BASE, NovaBase):
topic = Column(String(255))
report_count = Column(Integer, nullable=False, default=0)
disabled = Column(Boolean, default=False)
- availability_zone = Column(String(255), default='nova')
class ComputeNode(BASE, NovaBase):
diff --git a/nova/network/quantumv2/api.py b/nova/network/quantumv2/api.py
index 88431b91d..0a4b24538 100644
--- a/nova/network/quantumv2/api.py
+++ b/nova/network/quantumv2/api.py
@@ -52,7 +52,6 @@ quantum_opts = [
CONF = cfg.CONF
CONF.register_opts(quantum_opts)
-CONF.import_opt('node_availability_zone', 'nova.config')
CONF.import_opt('default_floating_pool', 'nova.network.manager')
LOG = logging.getLogger(__name__)
@@ -126,7 +125,7 @@ class API(base.Base):
created_port_ids = []
for network in nets:
network_id = network['id']
- zone = 'compute:%s' % CONF.node_availability_zone
+ zone = 'compute:%s' % instance['availability_zone']
port_req_body = {'port': {'device_id': instance['uuid'],
'device_owner': zone}}
try:
@@ -287,7 +286,7 @@ class API(base.Base):
def _get_port_id_by_fixed_address(self, client,
instance, address):
- zone = 'compute:%s' % CONF.node_availability_zone
+ zone = 'compute:%s' % instance['availability_zone']
search_opts = {'device_id': instance['uuid'],
'device_owner': zone}
data = client.list_ports(**search_opts)
diff --git a/nova/scheduler/filters/availability_zone_filter.py b/nova/scheduler/filters/availability_zone_filter.py
index 24ea0dd35..585acbaf8 100644
--- a/nova/scheduler/filters/availability_zone_filter.py
+++ b/nova/scheduler/filters/availability_zone_filter.py
@@ -14,15 +14,21 @@
# under the License.
+from nova import availability_zones
from nova import db
+from nova.openstack.common import cfg
from nova.scheduler import filters
+CONF = cfg.CONF
+CONF.import_opt('default_availability_zone', 'nova.availability_zones')
+
+
class AvailabilityZoneFilter(filters.BaseHostFilter):
"""Filters Hosts by availability zone.
- Works with both service and aggregate metadata.
- For aggregate metadata uses the key 'availability_zone'
+ Works with aggregate metadata availability zones, using the key
+ 'availability_zone'
Note: in theory a compute node can be part of multiple availability_zones
"""
@@ -32,12 +38,12 @@ class AvailabilityZoneFilter(filters.BaseHostFilter):
availability_zone = props.get('availability_zone')
if availability_zone:
- if availability_zone == host_state.service['availability_zone']:
- return True
context = filter_properties['context'].elevated()
metadata = db.aggregate_metadata_get_by_host(
context, host_state.host, key='availability_zone')
if 'availability_zone' in metadata:
return availability_zone in metadata['availability_zone']
+ else:
+ return availability_zone == CONF.default_availability_zone
return False
return True
diff --git a/nova/service.py b/nova/service.py
index fc0ac4a1b..43619fd56 100644
--- a/nova/service.py
+++ b/nova/service.py
@@ -92,7 +92,6 @@ service_opts = [
CONF = cfg.CONF
CONF.register_opts(service_opts)
CONF.import_opt('host', 'nova.config')
-CONF.import_opt('node_availability_zone', 'nova.config')
class SignalExit(SystemExit):
@@ -447,13 +446,11 @@ class Service(object):
self.timers.append(periodic)
def _create_service_ref(self, context):
- zone = CONF.node_availability_zone
service_ref = db.service_create(context,
{'host': self.host,
'binary': self.binary,
'topic': self.topic,
- 'report_count': 0,
- 'availability_zone': zone})
+ 'report_count': 0})
self.service_id = service_ref['id']
def __getattr__(self, key):
diff --git a/nova/servicegroup/db_driver.py b/nova/servicegroup/db_driver.py
index a52ed258c..f859f9f8b 100644
--- a/nova/servicegroup/db_driver.py
+++ b/nova/servicegroup/db_driver.py
@@ -72,7 +72,6 @@ class DbDriver(api.ServiceGroupDriver):
def _report_state(self, service):
"""Update the state of this service in the datastore."""
ctxt = context.get_admin_context()
- zone = CONF.node_availability_zone
state_catalog = {}
try:
try:
@@ -84,8 +83,6 @@ class DbDriver(api.ServiceGroupDriver):
service_ref = db.service_get(ctxt, service.service_id)
state_catalog['report_count'] = service_ref['report_count'] + 1
- if zone != service_ref['availability_zone']:
- state_catalog['availability_zone'] = zone
db.service_update(ctxt,
service.service_id, state_catalog)
diff --git a/nova/tests/api/ec2/test_cloud.py b/nova/tests/api/ec2/test_cloud.py
index 429746dac..e0470689a 100644
--- a/nova/tests/api/ec2/test_cloud.py
+++ b/nova/tests/api/ec2/test_cloud.py
@@ -703,23 +703,24 @@ class CloudTestCase(test.TestCase):
service1 = db.service_create(self.context, {'host': 'host1_zones',
'binary': "nova-compute",
'topic': 'compute',
- 'report_count': 0,
- 'availability_zone': "zone1"})
+ 'report_count': 0})
service2 = db.service_create(self.context, {'host': 'host2_zones',
'binary': "nova-compute",
'topic': 'compute',
- 'report_count': 0,
- 'availability_zone': "zone2"})
+ 'report_count': 0})
# Aggregate based zones
agg = db.aggregate_create(self.context,
- {'name': 'agg1'}, {'availability_zone': 'aggzones'})
+ {'name': 'agg1'}, {'availability_zone': 'zone1'})
+ db.aggregate_host_add(self.context, agg.id, 'host1_zones')
+ agg = db.aggregate_create(self.context,
+ {'name': 'agg2'}, {'availability_zone': 'zone2'})
db.aggregate_host_add(self.context, agg.id, 'host2_zones')
result = self.cloud.describe_availability_zones(self.context)
- self.assertEqual(len(result['availabilityZoneInfo']), 4)
+ self.assertEqual(len(result['availabilityZoneInfo']), 3)
admin_ctxt = context.get_admin_context(read_deleted="no")
result = self.cloud.describe_availability_zones(admin_ctxt,
zone_name='verbose')
- self.assertEqual(len(result['availabilityZoneInfo']), 18)
+ self.assertEqual(len(result['availabilityZoneInfo']), 16)
db.service_destroy(self.context, service1['id'])
db.service_destroy(self.context, service2['id'])
@@ -728,13 +729,14 @@ class CloudTestCase(test.TestCase):
service1 = db.service_create(self.context, {'host': 'host1_zones',
'binary': "nova-compute",
'topic': 'compute',
- 'report_count': 0,
- 'availability_zone': "zone1"})
+ 'report_count': 0})
service2 = db.service_create(self.context, {'host': 'host2_zones',
'binary': "nova-compute",
'topic': 'compute',
- 'report_count': 0,
- 'availability_zone': "zone2"})
+ 'report_count': 0})
+ agg = db.aggregate_create(self.context,
+ {'name': 'agg1'}, {'availability_zone': 'second_zone'})
+ db.aggregate_host_add(self.context, agg.id, 'host2_zones')
admin_ctxt = context.get_admin_context(read_deleted="no")
result = self.cloud.describe_availability_zones(admin_ctxt,
@@ -765,11 +767,17 @@ class CloudTestCase(test.TestCase):
'hostname': 'server-4321',
'vm_state': 'active'})
comp1 = db.service_create(self.context, {'host': 'host1',
- 'availability_zone': 'zone1',
'topic': "compute"})
+ agg = db.aggregate_create(self.context,
+ {'name': 'agg1'}, {'availability_zone': 'zone1'})
+ db.aggregate_host_add(self.context, agg.id, 'host1')
+
comp2 = db.service_create(self.context, {'host': 'host2',
- 'availability_zone': 'zone2',
'topic': "compute"})
+ agg2 = db.aggregate_create(self.context,
+ {'name': 'agg2'}, {'availability_zone': 'zone2'})
+ db.aggregate_host_add(self.context, agg2.id, 'host2')
+
result = self.cloud.describe_instances(self.context)
result = result['reservationSet'][0]
self.assertEqual(len(result['instancesSet']), 2)
@@ -852,11 +860,9 @@ class CloudTestCase(test.TestCase):
inst3 = db.instance_create(self.context, inst3_kwargs)
comp1 = db.service_create(self.context, {'host': 'host1',
- 'availability_zone': 'zone1',
'topic': "compute"})
comp2 = db.service_create(self.context, {'host': 'host2',
- 'availability_zone': 'zone2',
'topic': "compute"})
result = self.cloud.describe_instances(self.context)
diff --git a/nova/tests/api/openstack/compute/contrib/test_hosts.py b/nova/tests/api/openstack/compute/contrib/test_hosts.py
index 8469c7eba..71eae6f81 100644
--- a/nova/tests/api/openstack/compute/contrib/test_hosts.py
+++ b/nova/tests/api/openstack/compute/contrib/test_hosts.py
@@ -27,18 +27,14 @@ from nova import test
LOG = logging.getLogger(__name__)
HOST_LIST = {"hosts": [
{"host_name": "host_c1", "service": "compute", "zone": "nova"},
- {"host_name": "host_c2", "service": "compute", "zone": "nonova"},
- {"host_name": "host_v1", "service": "volume", "zone": "nova"},
- {"host_name": "host_v2", "service": "volume", "zone": "nonova"}]
+ {"host_name": "host_c2", "service": "compute", "zone": "nova"}]
}
HOST_LIST_NOVA_ZONE = [
{"host_name": "host_c1", "service": "compute", "zone": "nova"},
- {"host_name": "host_v1", "service": "volume", "zone": "nova"}]
+ {"host_name": "host_c2", "service": "compute", "zone": "nova"}]
SERVICES_LIST = [
- {"host": "host_c1", "topic": "compute", "availability_zone": "nova"},
- {"host": "host_c2", "topic": "compute", "availability_zone": "nonova"},
- {"host": "host_v1", "topic": "volume", "availability_zone": "nova"},
- {"host": "host_v2", "topic": "volume", "availability_zone": "nonova"}]
+ {"host": "host_c1", "topic": "compute"},
+ {"host": "host_c2", "topic": "compute"}]
def stub_service_get_all(self, req):
@@ -250,7 +246,7 @@ class HostTestCase(test.TestCase):
"""Create compute-manager(ComputeNode and Service record)."""
ctxt = context.get_admin_context()
dic = {'host': 'dummy', 'binary': 'nova-compute', 'topic': 'compute',
- 'report_count': 0, 'availability_zone': 'dummyzone'}
+ 'report_count': 0}
s_ref = db.service_create(ctxt, dic)
dic = {'service_id': s_ref['id'],
diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py
index 823eeaf4e..f6889ff2c 100644
--- a/nova/tests/compute/test_compute.py
+++ b/nova/tests/compute/test_compute.py
@@ -5383,8 +5383,7 @@ def _create_service_entries(context, values={'avail_zone1': ['fake_host1',
{'host': host,
'binary': 'nova-compute',
'topic': 'compute',
- 'report_count': 0,
- 'availability_zone': avail_zone})
+ 'report_count': 0})
return values
diff --git a/nova/tests/integrated/api_samples/os-hosts/hosts-list-resp.json.tpl b/nova/tests/integrated/api_samples/os-hosts/hosts-list-resp.json.tpl
index 555901b2e..eeb191597 100644
--- a/nova/tests/integrated/api_samples/os-hosts/hosts-list-resp.json.tpl
+++ b/nova/tests/integrated/api_samples/os-hosts/hosts-list-resp.json.tpl
@@ -8,22 +8,22 @@
{
"host_name": "%(host_name)s",
"service": "cert",
- "zone": "nova"
+ "zone": "internal"
},
{
"host_name": "%(host_name)s",
"service": "network",
- "zone": "nova"
+ "zone": "internal"
},
{
"host_name": "%(host_name)s",
"service": "scheduler",
- "zone": "nova"
+ "zone": "internal"
},
{
"host_name": "%(host_name)s",
"service": "conductor",
- "zone": "nova"
+ "zone": "internal"
}
]
}
diff --git a/nova/tests/network/test_quantumv2.py b/nova/tests/network/test_quantumv2.py
index 1eab23a03..622365c76 100644
--- a/nova/tests/network/test_quantumv2.py
+++ b/nova/tests/network/test_quantumv2.py
@@ -137,6 +137,7 @@ class TestQuantumv2(test.TestCase):
self.instance = {'project_id': '9d049e4b60b64716978ab415e6fbd5c0',
'uuid': str(uuid.uuid4()),
'display_name': 'test_instance',
+ 'availability_zone': 'nova',
'security_groups': []}
self.nets1 = [{'id': 'my_netid1',
'name': 'my_netname1',
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index 6bc18251f..7443d5289 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -628,8 +628,7 @@ class LibvirtConnTestCase(test.TestCase):
service_ref = {'host': kwargs.get('host', 'dummy'),
'binary': 'nova-compute',
'topic': 'compute',
- 'report_count': 0,
- 'availability_zone': 'zone'}
+ 'report_count': 0}
return db.service_create(context.get_admin_context(), service_ref)
diff --git a/nova/tests/test_migrations.py b/nova/tests/test_migrations.py
index bcd858d96..9badfb61a 100644
--- a/nova/tests/test_migrations.py
+++ b/nova/tests/test_migrations.py
@@ -331,3 +331,61 @@ class TestMigrations(test.TestCase):
migration_api.downgrade(engine, TestMigrations.REPOSITORY, 145)
_145_check()
+
+ def test_migration_147(self):
+ az = 'test_zone'
+ host1 = 'compute-host1'
+ host2 = 'compute-host2'
+
+ def _146_check():
+ service = services.select(services.c.id == 1).execute().first()
+ self.assertEqual(az, service.availability_zone)
+ self.assertEqual(host1, service.host)
+ service = services.select(services.c.id == 2).execute().first()
+ self.assertNotEqual(az, service.availability_zone)
+ service = services.select(services.c.id == 3).execute().first()
+ self.assertEqual(az, service.availability_zone)
+ self.assertEqual(host2, service.host)
+
+ for key, engine in self.engines.items():
+ migration_api.version_control(engine, TestMigrations.REPOSITORY,
+ migration.INIT_VERSION)
+ migration_api.upgrade(engine, TestMigrations.REPOSITORY, 146)
+ metadata = sqlalchemy.schema.MetaData()
+ metadata.bind = engine
+
+ #populate service table
+ services = sqlalchemy.Table('services', metadata,
+ autoload=True)
+ services.insert().values(id=1, host=host1,
+ binary='nova-compute', topic='compute', report_count=0,
+ availability_zone=az).execute()
+ services.insert().values(id=2, host='sched-host',
+ binary='nova-scheduler', topic='scheduler', report_count=0,
+ availability_zone='ignore_me').execute()
+ services.insert().values(id=3, host=host2,
+ binary='nova-compute', topic='compute', report_count=0,
+ availability_zone=az).execute()
+
+ _146_check()
+
+ migration_api.upgrade(engine, TestMigrations.REPOSITORY, 147)
+
+ # check aggregate metadata
+ aggregate_metadata = sqlalchemy.Table('aggregate_metadata',
+ metadata, autoload=True)
+ aggregate_hosts = sqlalchemy.Table('aggregate_hosts',
+ metadata, autoload=True)
+ metadata = aggregate_metadata.select(aggregate_metadata.c.
+ aggregate_id == 1).execute().first()
+ self.assertEqual(az, metadata['value'])
+ self.assertEqual(aggregate_hosts.select(
+ aggregate_hosts.c.aggregate_id == 1).execute().
+ first().host, host1)
+ blank = [h for h in aggregate_hosts.select(
+ aggregate_hosts.c.aggregate_id == 2).execute()]
+ self.assertEqual(blank, [])
+
+ migration_api.downgrade(engine, TestMigrations.REPOSITORY, 146)
+
+ _146_check()
diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py
index 211a91e45..4c834e9c9 100644
--- a/nova/tests/test_service.py
+++ b/nova/tests/test_service.py
@@ -127,13 +127,11 @@ class ServiceTestCase(test.TestCase):
service_create = {'host': self.host,
'binary': self.binary,
'topic': self.topic,
- 'report_count': 0,
- 'availability_zone': 'nova'}
+ 'report_count': 0}
service_ref = {'host': self.host,
'binary': self.binary,
'topic': self.topic,
'report_count': 0,
- 'availability_zone': 'nova',
'id': 1}
service.db.service_get_by_args(mox.IgnoreArg(),
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index 64659a21f..897bccd39 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -61,7 +61,7 @@ CONF.import_opt('compute_manager', 'nova.config')
CONF.import_opt('compute_driver', 'nova.virt.driver')
CONF.import_opt('host', 'nova.config')
CONF.import_opt('network_manager', 'nova.config')
-CONF.import_opt('node_availability_zone', 'nova.config')
+CONF.import_opt('default_availability_zone', 'nova.availability_zones')
IMAGE_MACHINE = '1'
IMAGE_KERNEL = '2'
@@ -206,7 +206,7 @@ class XenAPIVolumeTestCase(stubs.XenAPITestBase):
vol['user_id'] = 'fake'
vol['project_id'] = 'fake'
vol['host'] = 'localhost'
- vol['availability_zone'] = CONF.node_availability_zone
+ vol['availability_zone'] = CONF.default_availability_zone
vol['status'] = "creating"
vol['attach_status'] = "detached"
return db.volume_create(self.context, vol)
@@ -2196,8 +2196,7 @@ def _create_service_entries(context, values={'avail_zone1': ['fake_host1',
{'host': host,
'binary': 'nova-compute',
'topic': 'compute',
- 'report_count': 0,
- 'availability_zone': avail_zone})
+ 'report_count': 0})
return values
@@ -2213,7 +2212,7 @@ class XenAPIAggregateTestCase(stubs.XenAPITestBase):
'Dom0IptablesFirewallDriver',
host='host',
compute_driver='xenapi.XenAPIDriver',
- node_availability_zone='avail_zone1')
+ default_availability_zone='avail_zone1')
self.flags(use_local=True, group='conductor')
host_ref = xenapi_fake.get_all('host')[0]
stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests)