Merge "Remove availability_zones from service table"

This commit is contained in:
Jenkins 2013-01-09 04:09:31 +00:00 committed by Gerrit Code Review
commit ddb2400047
24 changed files with 291 additions and 93 deletions

View File

@ -70,6 +70,7 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'nova', '__init__.py')):
gettext.install('nova', unicode=1) gettext.install('nova', unicode=1)
from nova.api.ec2 import ec2utils from nova.api.ec2 import ec2utils
from nova import availability_zones
from nova.compute import instance_types from nova.compute import instance_types
from nova.compute import rpcapi as compute_rpcapi from nova.compute import rpcapi as compute_rpcapi
from nova import config from nova import config
@ -626,6 +627,7 @@ class ServiceCommands(object):
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
now = timeutils.utcnow() now = timeutils.utcnow()
services = db.service_get_all(ctxt) services = db.service_get_all(ctxt)
services = availability_zone.set_availability_zones(ctxt, services)
if host: if host:
services = [s for s in services if s['host'] == host] services = [s for s in services if s['host'] == host]
if service: if service:
@ -741,6 +743,7 @@ class HostCommands(object):
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
now = timeutils.utcnow() now = timeutils.utcnow()
services = db.service_get_all(ctxt) services = db.service_get_all(ctxt)
services = availability_zones.set_availability_zones(ctxt, services)
if zone: if zone:
services = [s for s in services if s['availability_zone'] == zone] services = [s for s in services if s['availability_zone'] == zone]
hosts = [] hosts = []

View File

@ -8,22 +8,22 @@
{ {
"host_name": "a98b433151084aee8b1a986e28823b36", "host_name": "a98b433151084aee8b1a986e28823b36",
"service": "cert", "service": "cert",
"zone": "nova" "zone": "internal"
}, },
{ {
"host_name": "c56158d13a884a87abf9171efb7de9d8", "host_name": "c56158d13a884a87abf9171efb7de9d8",
"service": "network", "service": "network",
"zone": "nova" "zone": "internal"
}, },
{ {
"host_name": "81d5cdcda0014918b3ebd3503a2e5c9a", "host_name": "81d5cdcda0014918b3ebd3503a2e5c9a",
"service": "scheduler", "service": "scheduler",
"zone": "nova" "zone": "internal"
}, },
{ {
"host_name": "6e48bfe1a3304b7b86154326328750ae", "host_name": "6e48bfe1a3304b7b86154326328750ae",
"service": "conductor", "service": "conductor",
"zone": "nova" "zone": "internal"
} }
] ]
} }

View File

@ -28,6 +28,7 @@ import time
from nova.api.ec2 import ec2utils from nova.api.ec2 import ec2utils
from nova.api.ec2 import inst_state from nova.api.ec2 import inst_state
from nova.api import validator from nova.api import validator
from nova import availability_zones
from nova import block_device from nova import block_device
from nova import compute from nova import compute
from nova.compute import api as compute_api 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('my_ip', 'nova.config')
CONF.import_opt('vpn_image_id', 'nova.config') CONF.import_opt('vpn_image_id', 'nova.config')
CONF.import_opt('vpn_key_suffix', 'nova.config') CONF.import_opt('vpn_key_suffix', 'nova.config')
CONF.import_opt('internal_service_availability_zone',
'nova.availability_zones')
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -250,6 +253,10 @@ class CloudController(object):
"""Return available and unavailable zones.""" """Return available and unavailable zones."""
enabled_services = db.service_get_all(context, False) enabled_services = db.service_get_all(context, False)
disabled_services = db.service_get_all(context, True) 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 = [] available_zones = []
for zone in [service['availability_zone'] for service for zone in [service['availability_zone'] for service
@ -257,17 +264,11 @@ class CloudController(object):
if not zone in available_zones: if not zone in available_zones:
available_zones.append(zone) 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 = [] not_available_zones = []
for zone in [service.availability_zone for service in disabled_services zones = [service['available_zones'] for service in disabled_services
if not service['availability_zone'] in available_zones]: if service['available_zones'] not in available_zones]
if not zone in not_available_zones: for zone in zones:
if zone not in not_available_zones:
not_available_zones.append(zone) not_available_zones.append(zone)
return (available_zones, not_available_zones) return (available_zones, not_available_zones)
@ -277,6 +278,9 @@ class CloudController(object):
result = [] result = []
for zone in available_zones: for zone in available_zones:
# Hide internal_service_availability_zone
if zone == CONF.internal_service_availability_zone:
continue
result.append({'zoneName': zone, result.append({'zoneName': zone,
'zoneState': "available"}) 'zoneState': "available"})
for zone in not_available_zones: for zone in not_available_zones:
@ -290,6 +294,8 @@ class CloudController(object):
# Available services # Available services
enabled_services = db.service_get_all(context, False) enabled_services = db.service_get_all(context, False)
enabled_services = availability_zones.set_availability_zones(context,
enabled_services)
zone_hosts = {} zone_hosts = {}
host_services = {} host_services = {}
for service in enabled_services: for service in enabled_services:
@ -298,17 +304,10 @@ class CloudController(object):
zone_hosts[service['availability_zone']].append( zone_hosts[service['availability_zone']].append(
service['host']) service['host'])
host_services.setdefault(service['host'], []) host_services.setdefault(service['availability_zone'] +
host_services[service['host']].append(service) service['host'], [])
# aggregate based available_zones host_services[service['availability_zone'] + service['host']].\
metadata = db.aggregate_host_get_by_metadata_key(context, append(service)
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)
result = [] result = []
for zone in available_zones: for zone in available_zones:
@ -318,7 +317,7 @@ class CloudController(object):
result.append({'zoneName': '|- %s' % host, result.append({'zoneName': '|- %s' % host,
'zoneState': ''}) 'zoneState': ''})
for service in host_services[host]: for service in host_services[zone + host]:
alive = self.servicegroup_api.service_is_up(service) alive = self.servicegroup_api.service_is_up(service)
art = (alive and ":-)") or "XXX" art = (alive and ":-)") or "XXX"
active = 'enabled' active = 'enabled'

View File

@ -18,6 +18,7 @@
import re import re
from nova import availability_zones
from nova import context from nova import context
from nova import db from nova import db
from nova import exception from nova import exception
@ -116,7 +117,7 @@ def get_ip_info_for_instance(context, instance):
def get_availability_zone_by_host(services, host): def get_availability_zone_by_host(services, host):
if len(services) > 0: if len(services) > 0:
return services[0]['availability_zone'] return availability_zones.get_host_availability_zone(context, host)
return 'unknown zone' return 'unknown zone'

View File

@ -22,6 +22,7 @@ from xml.parsers import expat
from nova.api.openstack import extensions from nova.api.openstack import extensions
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil from nova.api.openstack import xmlutil
from nova import availability_zones
from nova.compute import api as compute_api from nova.compute import api as compute_api
from nova import db from nova import db
from nova import exception from nova import exception
@ -99,6 +100,7 @@ def _list_hosts(req):
""" """
context = req.environ['nova.context'] context = req.environ['nova.context']
services = db.service_get_all(context, False) services = db.service_get_all(context, False)
services = availability_zones.set_availability_zones(context, services)
zone = '' zone = ''
if 'zone' in req.GET: if 'zone' in req.GET:
zone = req.GET['zone'] zone = req.GET['zone']

View File

@ -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

View File

@ -2242,11 +2242,6 @@ class AggregateAPI(base.Base):
# validates the host; ComputeHostNotFound is raised if invalid # validates the host; ComputeHostNotFound is raised if invalid
service = self.db.service_get_all_compute_by_host(context, host)[0] service = self.db.service_get_all_compute_by_host(context, host)[0]
aggregate = self.db.aggregate_get(context, aggregate_id) 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) self.db.aggregate_host_add(context, aggregate_id, host)
#NOTE(jogo): Send message to host to support resource pools #NOTE(jogo): Send message to host to support resource pools
self.compute_rpcapi.add_aggregate_host(context, self.compute_rpcapi.add_aggregate_host(context,

View File

@ -108,9 +108,6 @@ global_opts = [
'However, the node name must be valid within ' 'However, the node name must be valid within '
'an AMQP key, and if using ZeroMQ, a valid ' 'an AMQP key, and if using ZeroMQ, a valid '
'hostname, FQDN, or IP address'), 'hostname, FQDN, or IP address'),
cfg.StrOpt('node_availability_zone',
default='nova',
help='availability zone of this node'),
cfg.ListOpt('memcached_servers', cfg.ListOpt('memcached_servers',
default=None, default=None,
help='Memcached servers or None for in process cache.'), help='Memcached servers or None for in process cache.'),

View File

@ -1546,8 +1546,10 @@ def aggregate_metadata_get_by_host(context, host, key=None):
def aggregate_host_get_by_metadata_key(context, key): def aggregate_host_get_by_metadata_key(context, key):
"""Get hosts with a specific metadata key metadata for all aggregates. """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 Returns a dictionary where each key is a hostname and each value is a set
key value""" of the key values
return value: {machine: set( az1, az2 )}
"""
return IMPL.aggregate_host_get_by_metadata_key(context, key) return IMPL.aggregate_host_get_by_metadata_key(context, key)

View File

@ -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()

View File

@ -106,7 +106,6 @@ class Service(BASE, NovaBase):
topic = Column(String(255)) topic = Column(String(255))
report_count = Column(Integer, nullable=False, default=0) report_count = Column(Integer, nullable=False, default=0)
disabled = Column(Boolean, default=False) disabled = Column(Boolean, default=False)
availability_zone = Column(String(255), default='nova')
class ComputeNode(BASE, NovaBase): class ComputeNode(BASE, NovaBase):

View File

@ -52,7 +52,6 @@ quantum_opts = [
CONF = cfg.CONF CONF = cfg.CONF
CONF.register_opts(quantum_opts) CONF.register_opts(quantum_opts)
CONF.import_opt('node_availability_zone', 'nova.config')
CONF.import_opt('default_floating_pool', 'nova.network.manager') CONF.import_opt('default_floating_pool', 'nova.network.manager')
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -126,7 +125,7 @@ class API(base.Base):
created_port_ids = [] created_port_ids = []
for network in nets: for network in nets:
network_id = network['id'] 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'], port_req_body = {'port': {'device_id': instance['uuid'],
'device_owner': zone}} 'device_owner': zone}}
try: try:
@ -287,7 +286,7 @@ class API(base.Base):
def _get_port_id_by_fixed_address(self, client, def _get_port_id_by_fixed_address(self, client,
instance, address): instance, address):
zone = 'compute:%s' % CONF.node_availability_zone zone = 'compute:%s' % instance['availability_zone']
search_opts = {'device_id': instance['uuid'], search_opts = {'device_id': instance['uuid'],
'device_owner': zone} 'device_owner': zone}
data = client.list_ports(**search_opts) data = client.list_ports(**search_opts)

View File

@ -14,15 +14,21 @@
# under the License. # under the License.
from nova import availability_zones
from nova import db from nova import db
from nova.openstack.common import cfg
from nova.scheduler import filters from nova.scheduler import filters
CONF = cfg.CONF
CONF.import_opt('default_availability_zone', 'nova.availability_zones')
class AvailabilityZoneFilter(filters.BaseHostFilter): class AvailabilityZoneFilter(filters.BaseHostFilter):
"""Filters Hosts by availability zone. """Filters Hosts by availability zone.
Works with both service and aggregate metadata. Works with aggregate metadata availability zones, using the key
For aggregate metadata uses the key 'availability_zone' 'availability_zone'
Note: in theory a compute node can be part of multiple availability_zones 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') availability_zone = props.get('availability_zone')
if availability_zone: if availability_zone:
if availability_zone == host_state.service['availability_zone']:
return True
context = filter_properties['context'].elevated() context = filter_properties['context'].elevated()
metadata = db.aggregate_metadata_get_by_host( metadata = db.aggregate_metadata_get_by_host(
context, host_state.host, key='availability_zone') context, host_state.host, key='availability_zone')
if 'availability_zone' in metadata: if 'availability_zone' in metadata:
return availability_zone in metadata['availability_zone'] return availability_zone in metadata['availability_zone']
else:
return availability_zone == CONF.default_availability_zone
return False return False
return True return True

View File

@ -92,7 +92,6 @@ service_opts = [
CONF = cfg.CONF CONF = cfg.CONF
CONF.register_opts(service_opts) CONF.register_opts(service_opts)
CONF.import_opt('host', 'nova.config') CONF.import_opt('host', 'nova.config')
CONF.import_opt('node_availability_zone', 'nova.config')
class SignalExit(SystemExit): class SignalExit(SystemExit):
@ -447,13 +446,11 @@ class Service(object):
self.timers.append(periodic) self.timers.append(periodic)
def _create_service_ref(self, context): def _create_service_ref(self, context):
zone = CONF.node_availability_zone
service_ref = db.service_create(context, service_ref = db.service_create(context,
{'host': self.host, {'host': self.host,
'binary': self.binary, 'binary': self.binary,
'topic': self.topic, 'topic': self.topic,
'report_count': 0, 'report_count': 0})
'availability_zone': zone})
self.service_id = service_ref['id'] self.service_id = service_ref['id']
def __getattr__(self, key): def __getattr__(self, key):

View File

@ -72,7 +72,6 @@ class DbDriver(api.ServiceGroupDriver):
def _report_state(self, service): def _report_state(self, service):
"""Update the state of this service in the datastore.""" """Update the state of this service in the datastore."""
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
zone = CONF.node_availability_zone
state_catalog = {} state_catalog = {}
try: try:
try: try:
@ -84,8 +83,6 @@ class DbDriver(api.ServiceGroupDriver):
service_ref = db.service_get(ctxt, service.service_id) service_ref = db.service_get(ctxt, service.service_id)
state_catalog['report_count'] = service_ref['report_count'] + 1 state_catalog['report_count'] = service_ref['report_count'] + 1
if zone != service_ref['availability_zone']:
state_catalog['availability_zone'] = zone
db.service_update(ctxt, db.service_update(ctxt,
service.service_id, state_catalog) service.service_id, state_catalog)

View File

@ -703,23 +703,24 @@ class CloudTestCase(test.TestCase):
service1 = db.service_create(self.context, {'host': 'host1_zones', service1 = db.service_create(self.context, {'host': 'host1_zones',
'binary': "nova-compute", 'binary': "nova-compute",
'topic': 'compute', 'topic': 'compute',
'report_count': 0, 'report_count': 0})
'availability_zone': "zone1"})
service2 = db.service_create(self.context, {'host': 'host2_zones', service2 = db.service_create(self.context, {'host': 'host2_zones',
'binary': "nova-compute", 'binary': "nova-compute",
'topic': 'compute', 'topic': 'compute',
'report_count': 0, 'report_count': 0})
'availability_zone': "zone2"})
# Aggregate based zones # Aggregate based zones
agg = db.aggregate_create(self.context, 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') db.aggregate_host_add(self.context, agg.id, 'host2_zones')
result = self.cloud.describe_availability_zones(self.context) 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") admin_ctxt = context.get_admin_context(read_deleted="no")
result = self.cloud.describe_availability_zones(admin_ctxt, result = self.cloud.describe_availability_zones(admin_ctxt,
zone_name='verbose') 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, service1['id'])
db.service_destroy(self.context, service2['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', service1 = db.service_create(self.context, {'host': 'host1_zones',
'binary': "nova-compute", 'binary': "nova-compute",
'topic': 'compute', 'topic': 'compute',
'report_count': 0, 'report_count': 0})
'availability_zone': "zone1"})
service2 = db.service_create(self.context, {'host': 'host2_zones', service2 = db.service_create(self.context, {'host': 'host2_zones',
'binary': "nova-compute", 'binary': "nova-compute",
'topic': 'compute', 'topic': 'compute',
'report_count': 0, 'report_count': 0})
'availability_zone': "zone2"}) 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") admin_ctxt = context.get_admin_context(read_deleted="no")
result = self.cloud.describe_availability_zones(admin_ctxt, result = self.cloud.describe_availability_zones(admin_ctxt,
@ -765,11 +767,17 @@ class CloudTestCase(test.TestCase):
'hostname': 'server-4321', 'hostname': 'server-4321',
'vm_state': 'active'}) 'vm_state': 'active'})
comp1 = db.service_create(self.context, {'host': 'host1', comp1 = db.service_create(self.context, {'host': 'host1',
'availability_zone': 'zone1',
'topic': "compute"}) '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', comp2 = db.service_create(self.context, {'host': 'host2',
'availability_zone': 'zone2',
'topic': "compute"}) '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 = self.cloud.describe_instances(self.context)
result = result['reservationSet'][0] result = result['reservationSet'][0]
self.assertEqual(len(result['instancesSet']), 2) self.assertEqual(len(result['instancesSet']), 2)
@ -852,11 +860,9 @@ class CloudTestCase(test.TestCase):
inst3 = db.instance_create(self.context, inst3_kwargs) inst3 = db.instance_create(self.context, inst3_kwargs)
comp1 = db.service_create(self.context, {'host': 'host1', comp1 = db.service_create(self.context, {'host': 'host1',
'availability_zone': 'zone1',
'topic': "compute"}) 'topic': "compute"})
comp2 = db.service_create(self.context, {'host': 'host2', comp2 = db.service_create(self.context, {'host': 'host2',
'availability_zone': 'zone2',
'topic': "compute"}) 'topic': "compute"})
result = self.cloud.describe_instances(self.context) result = self.cloud.describe_instances(self.context)

View File

@ -27,18 +27,14 @@ from nova import test
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
HOST_LIST = {"hosts": [ HOST_LIST = {"hosts": [
{"host_name": "host_c1", "service": "compute", "zone": "nova"}, {"host_name": "host_c1", "service": "compute", "zone": "nova"},
{"host_name": "host_c2", "service": "compute", "zone": "nonova"}, {"host_name": "host_c2", "service": "compute", "zone": "nova"}]
{"host_name": "host_v1", "service": "volume", "zone": "nova"},
{"host_name": "host_v2", "service": "volume", "zone": "nonova"}]
} }
HOST_LIST_NOVA_ZONE = [ HOST_LIST_NOVA_ZONE = [
{"host_name": "host_c1", "service": "compute", "zone": "nova"}, {"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 = [ SERVICES_LIST = [
{"host": "host_c1", "topic": "compute", "availability_zone": "nova"}, {"host": "host_c1", "topic": "compute"},
{"host": "host_c2", "topic": "compute", "availability_zone": "nonova"}, {"host": "host_c2", "topic": "compute"}]
{"host": "host_v1", "topic": "volume", "availability_zone": "nova"},
{"host": "host_v2", "topic": "volume", "availability_zone": "nonova"}]
def stub_service_get_all(self, req): def stub_service_get_all(self, req):
@ -250,7 +246,7 @@ class HostTestCase(test.TestCase):
"""Create compute-manager(ComputeNode and Service record).""" """Create compute-manager(ComputeNode and Service record)."""
ctxt = context.get_admin_context() ctxt = context.get_admin_context()
dic = {'host': 'dummy', 'binary': 'nova-compute', 'topic': 'compute', dic = {'host': 'dummy', 'binary': 'nova-compute', 'topic': 'compute',
'report_count': 0, 'availability_zone': 'dummyzone'} 'report_count': 0}
s_ref = db.service_create(ctxt, dic) s_ref = db.service_create(ctxt, dic)
dic = {'service_id': s_ref['id'], dic = {'service_id': s_ref['id'],

View File

@ -5527,8 +5527,7 @@ def _create_service_entries(context, values={'avail_zone1': ['fake_host1',
{'host': host, {'host': host,
'binary': 'nova-compute', 'binary': 'nova-compute',
'topic': 'compute', 'topic': 'compute',
'report_count': 0, 'report_count': 0})
'availability_zone': avail_zone})
return values return values

View File

@ -8,22 +8,22 @@
{ {
"host_name": "%(host_name)s", "host_name": "%(host_name)s",
"service": "cert", "service": "cert",
"zone": "nova" "zone": "internal"
}, },
{ {
"host_name": "%(host_name)s", "host_name": "%(host_name)s",
"service": "network", "service": "network",
"zone": "nova" "zone": "internal"
}, },
{ {
"host_name": "%(host_name)s", "host_name": "%(host_name)s",
"service": "scheduler", "service": "scheduler",
"zone": "nova" "zone": "internal"
}, },
{ {
"host_name": "%(host_name)s", "host_name": "%(host_name)s",
"service": "conductor", "service": "conductor",
"zone": "nova" "zone": "internal"
} }
] ]
} }

View File

@ -137,6 +137,7 @@ class TestQuantumv2(test.TestCase):
self.instance = {'project_id': '9d049e4b60b64716978ab415e6fbd5c0', self.instance = {'project_id': '9d049e4b60b64716978ab415e6fbd5c0',
'uuid': str(uuid.uuid4()), 'uuid': str(uuid.uuid4()),
'display_name': 'test_instance', 'display_name': 'test_instance',
'availability_zone': 'nova',
'security_groups': []} 'security_groups': []}
self.nets1 = [{'id': 'my_netid1', self.nets1 = [{'id': 'my_netid1',
'name': 'my_netname1', 'name': 'my_netname1',

View File

@ -628,8 +628,7 @@ class LibvirtConnTestCase(test.TestCase):
service_ref = {'host': kwargs.get('host', 'dummy'), service_ref = {'host': kwargs.get('host', 'dummy'),
'binary': 'nova-compute', 'binary': 'nova-compute',
'topic': 'compute', 'topic': 'compute',
'report_count': 0, 'report_count': 0}
'availability_zone': 'zone'}
return db.service_create(context.get_admin_context(), service_ref) return db.service_create(context.get_admin_context(), service_ref)

View File

@ -331,3 +331,61 @@ class TestMigrations(test.TestCase):
migration_api.downgrade(engine, TestMigrations.REPOSITORY, 145) migration_api.downgrade(engine, TestMigrations.REPOSITORY, 145)
_145_check() _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()

View File

@ -127,13 +127,11 @@ class ServiceTestCase(test.TestCase):
service_create = {'host': self.host, service_create = {'host': self.host,
'binary': self.binary, 'binary': self.binary,
'topic': self.topic, 'topic': self.topic,
'report_count': 0, 'report_count': 0}
'availability_zone': 'nova'}
service_ref = {'host': self.host, service_ref = {'host': self.host,
'binary': self.binary, 'binary': self.binary,
'topic': self.topic, 'topic': self.topic,
'report_count': 0, 'report_count': 0,
'availability_zone': 'nova',
'id': 1} 'id': 1}
service.db.service_get_by_args(mox.IgnoreArg(), service.db.service_get_by_args(mox.IgnoreArg(),

View File

@ -61,7 +61,7 @@ CONF.import_opt('compute_manager', 'nova.config')
CONF.import_opt('compute_driver', 'nova.virt.driver') CONF.import_opt('compute_driver', 'nova.virt.driver')
CONF.import_opt('host', 'nova.config') CONF.import_opt('host', 'nova.config')
CONF.import_opt('network_manager', '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_MACHINE = '1'
IMAGE_KERNEL = '2' IMAGE_KERNEL = '2'
@ -206,7 +206,7 @@ class XenAPIVolumeTestCase(stubs.XenAPITestBase):
vol['user_id'] = 'fake' vol['user_id'] = 'fake'
vol['project_id'] = 'fake' vol['project_id'] = 'fake'
vol['host'] = 'localhost' vol['host'] = 'localhost'
vol['availability_zone'] = CONF.node_availability_zone vol['availability_zone'] = CONF.default_availability_zone
vol['status'] = "creating" vol['status'] = "creating"
vol['attach_status'] = "detached" vol['attach_status'] = "detached"
return db.volume_create(self.context, vol) return db.volume_create(self.context, vol)
@ -2196,8 +2196,7 @@ def _create_service_entries(context, values={'avail_zone1': ['fake_host1',
{'host': host, {'host': host,
'binary': 'nova-compute', 'binary': 'nova-compute',
'topic': 'compute', 'topic': 'compute',
'report_count': 0, 'report_count': 0})
'availability_zone': avail_zone})
return values return values
@ -2213,7 +2212,7 @@ class XenAPIAggregateTestCase(stubs.XenAPITestBase):
'Dom0IptablesFirewallDriver', 'Dom0IptablesFirewallDriver',
host='host', host='host',
compute_driver='xenapi.XenAPIDriver', compute_driver='xenapi.XenAPIDriver',
node_availability_zone='avail_zone1') default_availability_zone='avail_zone1')
self.flags(use_local=True, group='conductor') self.flags(use_local=True, group='conductor')
host_ref = xenapi_fake.get_all('host')[0] host_ref = xenapi_fake.get_all('host')[0]
stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests)