Merge "Remove availability_zones from service table"
This commit is contained in:
commit
ddb2400047
|
@ -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 = []
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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']
|
||||||
|
|
|
@ -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
|
|
@ -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,
|
||||||
|
|
|
@ -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.'),
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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'],
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue