Move nova_utils functions to nova client plugin
All uses of nova_utils functions have been migrated to using the nova client plugin version. Existing functions now have a deprecation warning which is suppressed during nova_utils unit tests. nova_utils.get_flavor_id was being called with the trove client, so there is now a dedicated trove plugin method get_flavor_id. Change-Id: Ic8120022a1f9117c783f6422069f94614bcbb3c6
This commit is contained in:
parent
cbcfe1cedf
commit
60e6eeb075
@ -16,7 +16,6 @@ import copy
|
||||
from heat.common import exception
|
||||
from heat.engine import attributes
|
||||
from heat.engine import properties
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.engine.resources import server
|
||||
from heat.openstack.common.gettextutils import _
|
||||
from heat.openstack.common import log as logging
|
||||
@ -200,7 +199,7 @@ class CloudServer(server.Server):
|
||||
if not self._check_active(server):
|
||||
return False
|
||||
|
||||
nova_utils.refresh_server(server)
|
||||
self.client_plugin().refresh_server(server)
|
||||
|
||||
if 'rack_connect' in self.context.roles and not \
|
||||
self._check_rack_connect_complete(server):
|
||||
@ -216,7 +215,7 @@ class CloudServer(server.Server):
|
||||
if name == self.DISTRO:
|
||||
return self.distro
|
||||
if name == self.PRIVATE_IP_V4:
|
||||
return nova_utils.get_ip(self.server, 'private', 4)
|
||||
return self.client_plugin().get_ip(self.server, 'private', 4)
|
||||
if name == self.ADMIN_PASS_ATTR:
|
||||
return self.data().get(self.ADMIN_PASS_ATTR, '')
|
||||
return super(CloudServer, self)._resolve_attribute(name)
|
||||
|
@ -11,15 +11,42 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import email
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import pkgutil
|
||||
import string
|
||||
|
||||
from novaclient import client as nc
|
||||
from novaclient import exceptions
|
||||
from novaclient import shell as novashell
|
||||
from oslo.config import cfg
|
||||
import six
|
||||
from six.moves.urllib import parse as urlparse
|
||||
|
||||
from heat.common import exception
|
||||
from heat.engine.clients import client_plugin
|
||||
from heat.engine import scheduler
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NovaClientPlugin(client_plugin.ClientPlugin):
|
||||
|
||||
deferred_server_statuses = ['BUILD',
|
||||
'HARD_REBOOT',
|
||||
'PASSWORD',
|
||||
'REBOOT',
|
||||
'RESCUE',
|
||||
'RESIZE',
|
||||
'REVERT_RESIZE',
|
||||
'SHUTOFF',
|
||||
'SUSPENDED',
|
||||
'VERIFY_RESIZE']
|
||||
|
||||
exceptions_module = exceptions
|
||||
|
||||
def _create(self):
|
||||
@ -58,3 +85,307 @@ class NovaClientPlugin(client_plugin.ClientPlugin):
|
||||
|
||||
def is_bad_request(self, ex):
|
||||
return isinstance(ex, exceptions.BadRequest)
|
||||
|
||||
def refresh_server(self, server):
|
||||
'''
|
||||
Refresh server's attributes and log warnings for non-critical
|
||||
API errors.
|
||||
'''
|
||||
try:
|
||||
server.get()
|
||||
except exceptions.OverLimit as exc:
|
||||
msg = _("Server %(name)s (%(id)s) received an OverLimit "
|
||||
"response during server.get(): %(exception)s")
|
||||
LOG.warning(msg % {'name': server.name,
|
||||
'id': server.id,
|
||||
'exception': exc})
|
||||
except exceptions.ClientException as exc:
|
||||
if ((getattr(exc, 'http_status', getattr(exc, 'code', None)) in
|
||||
(500, 503))):
|
||||
msg = _('Server "%(name)s" (%(id)s) received the following '
|
||||
'exception during server.get(): %(exception)s')
|
||||
LOG.warning(msg % {'name': server.name,
|
||||
'id': server.id,
|
||||
'exception': exc})
|
||||
else:
|
||||
raise
|
||||
|
||||
def get_ip(self, server, net_type, ip_version):
|
||||
"""Return the server's IP of the given type and version."""
|
||||
if net_type in server.addresses:
|
||||
for ip in server.addresses[net_type]:
|
||||
if ip['version'] == ip_version:
|
||||
return ip['addr']
|
||||
|
||||
def get_flavor_id(self, flavor):
|
||||
'''
|
||||
Get the id for the specified flavor name.
|
||||
If the specified value is flavor id, just return it.
|
||||
|
||||
:param flavor: the name of the flavor to find
|
||||
:returns: the id of :flavor:
|
||||
:raises: exception.FlavorMissing
|
||||
'''
|
||||
flavor_id = None
|
||||
flavor_list = self.client().flavors.list()
|
||||
for o in flavor_list:
|
||||
if o.name == flavor:
|
||||
flavor_id = o.id
|
||||
break
|
||||
if o.id == flavor:
|
||||
flavor_id = o.id
|
||||
break
|
||||
if flavor_id is None:
|
||||
raise exception.FlavorMissing(flavor_id=flavor)
|
||||
return flavor_id
|
||||
|
||||
def get_keypair(self, key_name):
|
||||
'''
|
||||
Get the public key specified by :key_name:
|
||||
|
||||
:param key_name: the name of the key to look for
|
||||
:returns: the keypair (name, public_key) for :key_name:
|
||||
:raises: exception.UserKeyPairMissing
|
||||
'''
|
||||
try:
|
||||
return self.client().keypairs.get(key_name)
|
||||
except exceptions.NotFound:
|
||||
raise exception.UserKeyPairMissing(key_name=key_name)
|
||||
|
||||
def build_userdata(self, metadata, userdata=None, instance_user=None,
|
||||
user_data_format='HEAT_CFNTOOLS'):
|
||||
'''
|
||||
Build multipart data blob for CloudInit which includes user-supplied
|
||||
Metadata, user data, and the required Heat in-instance configuration.
|
||||
|
||||
:param resource: the resource implementation
|
||||
:type resource: heat.engine.Resource
|
||||
:param userdata: user data string
|
||||
:type userdata: str or None
|
||||
:param instance_user: the user to create on the server
|
||||
:type instance_user: string
|
||||
:param user_data_format: Format of user data to return
|
||||
:type user_data_format: string
|
||||
:returns: multipart mime as a string
|
||||
'''
|
||||
|
||||
if user_data_format == 'RAW':
|
||||
return userdata
|
||||
|
||||
is_cfntools = user_data_format == 'HEAT_CFNTOOLS'
|
||||
is_software_config = user_data_format == 'SOFTWARE_CONFIG'
|
||||
|
||||
def make_subpart(content, filename, subtype=None):
|
||||
if subtype is None:
|
||||
subtype = os.path.splitext(filename)[0]
|
||||
msg = MIMEText(content, _subtype=subtype)
|
||||
msg.add_header('Content-Disposition', 'attachment',
|
||||
filename=filename)
|
||||
return msg
|
||||
|
||||
def read_cloudinit_file(fn):
|
||||
return pkgutil.get_data('heat', 'cloudinit/%s' % fn)
|
||||
|
||||
if instance_user:
|
||||
config_custom_user = 'user: %s' % instance_user
|
||||
# FIXME(shadower): compatibility workaround for cloud-init 0.6.3.
|
||||
# We can drop this once we stop supporting 0.6.3 (which ships
|
||||
# with Ubuntu 12.04 LTS).
|
||||
#
|
||||
# See bug https://bugs.launchpad.net/heat/+bug/1257410
|
||||
boothook_custom_user = r"""useradd -m %s
|
||||
echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers
|
||||
""" % (instance_user, instance_user)
|
||||
else:
|
||||
config_custom_user = ''
|
||||
boothook_custom_user = ''
|
||||
|
||||
cloudinit_config = string.Template(
|
||||
read_cloudinit_file('config')).safe_substitute(
|
||||
add_custom_user=config_custom_user)
|
||||
cloudinit_boothook = string.Template(
|
||||
read_cloudinit_file('boothook.sh')).safe_substitute(
|
||||
add_custom_user=boothook_custom_user)
|
||||
|
||||
attachments = [(cloudinit_config, 'cloud-config'),
|
||||
(cloudinit_boothook, 'boothook.sh', 'cloud-boothook'),
|
||||
(read_cloudinit_file('part_handler.py'),
|
||||
'part-handler.py')]
|
||||
|
||||
if is_cfntools:
|
||||
attachments.append((userdata, 'cfn-userdata', 'x-cfninitdata'))
|
||||
elif is_software_config:
|
||||
# attempt to parse userdata as a multipart message, and if it
|
||||
# is, add each part as an attachment
|
||||
userdata_parts = None
|
||||
try:
|
||||
userdata_parts = email.message_from_string(userdata)
|
||||
except Exception:
|
||||
pass
|
||||
if userdata_parts and userdata_parts.is_multipart():
|
||||
for part in userdata_parts.get_payload():
|
||||
attachments.append((part.get_payload(),
|
||||
part.get_filename(),
|
||||
part.get_content_subtype()))
|
||||
else:
|
||||
attachments.append((userdata, 'userdata', 'x-shellscript'))
|
||||
|
||||
if is_cfntools:
|
||||
attachments.append((read_cloudinit_file('loguserdata.py'),
|
||||
'loguserdata.py', 'x-shellscript'))
|
||||
|
||||
if metadata:
|
||||
attachments.append((json.dumps(metadata),
|
||||
'cfn-init-data', 'x-cfninitdata'))
|
||||
|
||||
attachments.append((cfg.CONF.heat_watch_server_url,
|
||||
'cfn-watch-server', 'x-cfninitdata'))
|
||||
|
||||
if is_cfntools:
|
||||
attachments.append((cfg.CONF.heat_metadata_server_url,
|
||||
'cfn-metadata-server', 'x-cfninitdata'))
|
||||
|
||||
# Create a boto config which the cfntools on the host use to know
|
||||
# where the cfn and cw API's are to be accessed
|
||||
cfn_url = urlparse.urlparse(cfg.CONF.heat_metadata_server_url)
|
||||
cw_url = urlparse.urlparse(cfg.CONF.heat_watch_server_url)
|
||||
is_secure = cfg.CONF.instance_connection_is_secure
|
||||
vcerts = cfg.CONF.instance_connection_https_validate_certificates
|
||||
boto_cfg = "\n".join(["[Boto]",
|
||||
"debug = 0",
|
||||
"is_secure = %s" % is_secure,
|
||||
"https_validate_certificates = %s" % vcerts,
|
||||
"cfn_region_name = heat",
|
||||
"cfn_region_endpoint = %s" %
|
||||
cfn_url.hostname,
|
||||
"cloudwatch_region_name = heat",
|
||||
"cloudwatch_region_endpoint = %s" %
|
||||
cw_url.hostname])
|
||||
attachments.append((boto_cfg,
|
||||
'cfn-boto-cfg', 'x-cfninitdata'))
|
||||
|
||||
subparts = [make_subpart(*args) for args in attachments]
|
||||
mime_blob = MIMEMultipart(_subparts=subparts)
|
||||
|
||||
return mime_blob.as_string()
|
||||
|
||||
def delete_server(self, server):
|
||||
'''
|
||||
Deletes a server and waits for it to disappear from Nova.
|
||||
'''
|
||||
if not server:
|
||||
return
|
||||
try:
|
||||
server.delete()
|
||||
except Exception as exc:
|
||||
self.ignore_not_found(exc)
|
||||
return
|
||||
|
||||
while True:
|
||||
yield
|
||||
|
||||
try:
|
||||
self.refresh_server(server)
|
||||
except Exception as exc:
|
||||
self.ignore_not_found(exc)
|
||||
break
|
||||
else:
|
||||
# Some clouds append extra (STATUS) strings to the status
|
||||
short_server_status = server.status.split('(')[0]
|
||||
if short_server_status == "DELETED":
|
||||
break
|
||||
if short_server_status == "ERROR":
|
||||
fault = getattr(server, 'fault', {})
|
||||
message = fault.get('message', 'Unknown')
|
||||
code = fault.get('code')
|
||||
errmsg = (_("Server %(name)s delete failed: (%(code)s) "
|
||||
"%(message)s"))
|
||||
raise exception.Error(errmsg % {"name": server.name,
|
||||
"code": code,
|
||||
"message": message})
|
||||
|
||||
@scheduler.wrappertask
|
||||
def resize(self, server, flavor, flavor_id):
|
||||
"""Resize the server and then call check_resize task to verify."""
|
||||
server.resize(flavor_id)
|
||||
yield self.check_resize(server, flavor, flavor_id)
|
||||
|
||||
def rename(self, server, name):
|
||||
"""Update the name for a server."""
|
||||
server.update(name)
|
||||
|
||||
def check_resize(self, server, flavor, flavor_id):
|
||||
"""
|
||||
Verify that a resizing server is properly resized.
|
||||
If that's the case, confirm the resize, if not raise an error.
|
||||
"""
|
||||
self.refresh_server(server)
|
||||
while server.status == 'RESIZE':
|
||||
yield
|
||||
self.refresh_server(server)
|
||||
if server.status == 'VERIFY_RESIZE':
|
||||
server.confirm_resize()
|
||||
else:
|
||||
raise exception.Error(
|
||||
_("Resizing to '%(flavor)s' failed, status '%(status)s'") %
|
||||
dict(flavor=flavor, status=server.status))
|
||||
|
||||
@scheduler.wrappertask
|
||||
def rebuild(self, server, image_id, preserve_ephemeral=False):
|
||||
"""Rebuild the server and call check_rebuild to verify."""
|
||||
server.rebuild(image_id, preserve_ephemeral=preserve_ephemeral)
|
||||
yield self.check_rebuild(server, image_id)
|
||||
|
||||
def check_rebuild(self, server, image_id):
|
||||
"""
|
||||
Verify that a rebuilding server is rebuilt.
|
||||
Raise error if it ends up in an ERROR state.
|
||||
"""
|
||||
self.refresh_server(server)
|
||||
while server.status == 'REBUILD':
|
||||
yield
|
||||
self.refresh_server(server)
|
||||
if server.status == 'ERROR':
|
||||
raise exception.Error(
|
||||
_("Rebuilding server failed, status '%s'") % server.status)
|
||||
|
||||
def meta_serialize(self, metadata):
|
||||
"""
|
||||
Serialize non-string metadata values before sending them to
|
||||
Nova.
|
||||
"""
|
||||
return dict((key, (value if isinstance(value,
|
||||
six.string_types)
|
||||
else json.dumps(value))
|
||||
) for (key, value) in metadata.items())
|
||||
|
||||
def meta_update(self, server, metadata):
|
||||
"""Delete/Add the metadata in nova as needed."""
|
||||
metadata = self.meta_serialize(metadata)
|
||||
current_md = server.metadata
|
||||
to_del = [key for key in current_md.keys() if key not in metadata]
|
||||
client = self.client()
|
||||
if len(to_del) > 0:
|
||||
client.servers.delete_meta(server, to_del)
|
||||
|
||||
client.servers.set_meta(server, metadata)
|
||||
|
||||
def server_to_ipaddress(self, server):
|
||||
'''
|
||||
Return the server's IP address, fetching it from Nova.
|
||||
'''
|
||||
try:
|
||||
server = self.client().servers.get(server)
|
||||
except exceptions.NotFound as ex:
|
||||
LOG.warn(_('Instance (%(server)s) not found: %(ex)s')
|
||||
% {'server': server, 'ex': ex})
|
||||
else:
|
||||
for n in server.networks:
|
||||
if len(server.networks[n]) > 0:
|
||||
return server.networks[n][0]
|
||||
|
||||
def absolute_limits(self):
|
||||
"""Return the absolute limits as a dictionary."""
|
||||
limits = self.client().limits.get()
|
||||
return dict([(limit.name, limit.value)
|
||||
for limit in list(limits.absolute)])
|
||||
|
@ -14,6 +14,7 @@
|
||||
from troveclient import client as tc
|
||||
from troveclient.openstack.common.apiclient import exceptions
|
||||
|
||||
from heat.common import exception
|
||||
from heat.engine.clients import client_plugin
|
||||
|
||||
|
||||
@ -49,3 +50,25 @@ class TroveClientPlugin(client_plugin.ClientPlugin):
|
||||
|
||||
def is_over_limit(self, ex):
|
||||
return isinstance(ex, exceptions.RequestEntityTooLarge)
|
||||
|
||||
def get_flavor_id(self, flavor):
|
||||
'''
|
||||
Get the id for the specified flavor name.
|
||||
If the specified value is flavor id, just return it.
|
||||
|
||||
:param flavor: the name of the flavor to find
|
||||
:returns: the id of :flavor:
|
||||
:raises: exception.FlavorMissing
|
||||
'''
|
||||
flavor_id = None
|
||||
flavor_list = self.client().flavors.list()
|
||||
for o in flavor_list:
|
||||
if o.name == flavor:
|
||||
flavor_id = o.id
|
||||
break
|
||||
if o.id == flavor:
|
||||
flavor_id = o.id
|
||||
break
|
||||
if flavor_id is None:
|
||||
raise exception.FlavorMissing(flavor_id=flavor)
|
||||
return flavor_id
|
||||
|
@ -23,7 +23,6 @@ from heat.engine import properties
|
||||
from heat.engine import resource
|
||||
from heat.engine.resources.network_interface import NetworkInterface
|
||||
from heat.engine.resources.neutron import neutron
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.engine.resources import volume
|
||||
from heat.engine import scheduler
|
||||
from heat.engine import signal_responder
|
||||
@ -432,8 +431,8 @@ class Instance(resource.Resource):
|
||||
Return the server's IP address, fetching it from Nova if necessary
|
||||
'''
|
||||
if self.ipaddress is None:
|
||||
self.ipaddress = nova_utils.server_to_ipaddress(
|
||||
self.nova(), self.resource_id)
|
||||
self.ipaddress = self.client_plugin().server_to_ipaddress(
|
||||
self.resource_id)
|
||||
|
||||
return self.ipaddress or '0.0.0.0'
|
||||
|
||||
@ -547,7 +546,7 @@ class Instance(resource.Resource):
|
||||
|
||||
image_id = self.client_plugin('glance').get_image_id(image_name)
|
||||
|
||||
flavor_id = nova_utils.get_flavor_id(self.nova(), flavor)
|
||||
flavor_id = self.client_plugin().get_flavor_id(flavor)
|
||||
|
||||
scheduler_hints = {}
|
||||
if self.properties[self.NOVA_SCHEDULER_HINTS]:
|
||||
@ -587,8 +586,8 @@ class Instance(resource.Resource):
|
||||
flavor=flavor_id,
|
||||
key_name=self.properties[self.KEY_NAME],
|
||||
security_groups=security_groups,
|
||||
userdata=nova_utils.build_userdata(self, userdata,
|
||||
instance_user),
|
||||
userdata=self.client_plugin().build_userdata(
|
||||
self.metadata_get(), userdata, instance_user),
|
||||
meta=self._get_nova_metadata(self.properties),
|
||||
scheduler_hints=scheduler_hints,
|
||||
nics=nics,
|
||||
@ -624,15 +623,16 @@ class Instance(resource.Resource):
|
||||
return volume_attach_task.step()
|
||||
|
||||
def _check_active(self, server):
|
||||
cp = self.client_plugin()
|
||||
if server.status != 'ACTIVE':
|
||||
nova_utils.refresh_server(server)
|
||||
cp.refresh_server(server)
|
||||
|
||||
if server.status == 'ACTIVE':
|
||||
return True
|
||||
|
||||
# Some clouds append extra (STATUS) strings to the status
|
||||
short_server_status = server.status.split('(')[0]
|
||||
if short_server_status in nova_utils.deferred_server_statuses:
|
||||
if short_server_status in cp.deferred_server_statuses:
|
||||
return False
|
||||
|
||||
if server.status == 'ERROR':
|
||||
@ -671,17 +671,16 @@ class Instance(resource.Resource):
|
||||
server = None
|
||||
if self.TAGS in prop_diff:
|
||||
server = self.nova().servers.get(self.resource_id)
|
||||
nova_utils.meta_update(self.nova(),
|
||||
server,
|
||||
self._get_nova_metadata(prop_diff))
|
||||
self.client_plugin().meta_update(
|
||||
server, self._get_nova_metadata(prop_diff))
|
||||
|
||||
if self.INSTANCE_TYPE in prop_diff:
|
||||
flavor = prop_diff[self.INSTANCE_TYPE]
|
||||
flavor_id = nova_utils.get_flavor_id(self.nova(), flavor)
|
||||
flavor_id = self.client_plugin().get_flavor_id(flavor)
|
||||
if not server:
|
||||
server = self.nova().servers.get(self.resource_id)
|
||||
checker = scheduler.TaskRunner(nova_utils.resize, server, flavor,
|
||||
flavor_id)
|
||||
checker = scheduler.TaskRunner(self.client_plugin().resize,
|
||||
server, flavor, flavor_id)
|
||||
checkers.append(checker)
|
||||
if self.NETWORK_INTERFACES in prop_diff:
|
||||
new_network_ifaces = prop_diff.get(self.NETWORK_INTERFACES)
|
||||
@ -815,11 +814,11 @@ class Instance(resource.Resource):
|
||||
server = self.nova().servers.get(self.resource_id)
|
||||
except Exception as e:
|
||||
self.client_plugin().ignore_not_found(e)
|
||||
self.resource_id_set(None)
|
||||
return
|
||||
deleters = (
|
||||
scheduler.TaskRunner(self._detach_volumes_task()),
|
||||
scheduler.TaskRunner(nova_utils.delete_server, server))
|
||||
scheduler.TaskRunner(self.client_plugin().delete_server,
|
||||
server))
|
||||
deleters[0].start()
|
||||
return deleters
|
||||
|
||||
@ -872,11 +871,12 @@ class Instance(resource.Resource):
|
||||
if server.status == 'SUSPENDED':
|
||||
return True
|
||||
|
||||
nova_utils.refresh_server(server)
|
||||
cp = self.client_plugin()
|
||||
cp.refresh_server(server)
|
||||
LOG.debug("%(name)s check_suspend_complete "
|
||||
"status = %(status)s",
|
||||
{'name': self.name, 'status': server.status})
|
||||
if server.status in list(nova_utils.deferred_server_statuses +
|
||||
if server.status in list(cp.deferred_server_statuses +
|
||||
['ACTIVE']):
|
||||
return server.status == 'SUSPENDED'
|
||||
else:
|
||||
|
@ -19,7 +19,6 @@ from heat.common import template_format
|
||||
from heat.engine import attributes
|
||||
from heat.engine import constraints
|
||||
from heat.engine import properties
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.engine import stack_resource
|
||||
from heat.openstack.common.gettextutils import _
|
||||
from heat.openstack.common import log as logging
|
||||
@ -422,9 +421,9 @@ class LoadBalancer(stack_resource.StackResource):
|
||||
|
||||
servers = []
|
||||
n = 1
|
||||
client = self.nova()
|
||||
nova_cp = self.client_plugin('nova')
|
||||
for i in instances:
|
||||
ip = nova_utils.server_to_ipaddress(client, i) or '0.0.0.0'
|
||||
ip = nova_cp.server_to_ipaddress(i) or '0.0.0.0'
|
||||
LOG.debug('haproxy server:%s' % ip)
|
||||
servers.append('%sserver server%d %s:%s %s' % (spaces, n,
|
||||
ip, inst_port,
|
||||
|
@ -18,7 +18,6 @@ from heat.engine import properties
|
||||
from heat.engine import resource
|
||||
from heat.engine.resources.neutron import neutron
|
||||
from heat.engine.resources.neutron import neutron_utils
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.engine import scheduler
|
||||
from heat.engine import support
|
||||
|
||||
@ -647,11 +646,10 @@ class LoadBalancer(resource.Resource):
|
||||
def handle_create(self):
|
||||
pool = self.properties[self.POOL_ID]
|
||||
client = self.neutron()
|
||||
nova_client = self.nova()
|
||||
protocol_port = self.properties[self.PROTOCOL_PORT]
|
||||
|
||||
for member in self.properties.get(self.MEMBERS):
|
||||
address = nova_utils.server_to_ipaddress(nova_client, member)
|
||||
address = self.client_plugin('nova').server_to_ipaddress(member)
|
||||
lb_member = client.create_member({
|
||||
'member': {
|
||||
'pool_id': pool,
|
||||
@ -673,10 +671,10 @@ class LoadBalancer(resource.Resource):
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
self.data_delete(member)
|
||||
pool = self.properties[self.POOL_ID]
|
||||
nova_client = self.nova()
|
||||
protocol_port = self.properties[self.PROTOCOL_PORT]
|
||||
for member in members - old_members:
|
||||
address = nova_utils.server_to_ipaddress(nova_client, member)
|
||||
address = self.client_plugin('nova').server_to_ipaddress(
|
||||
member)
|
||||
lb_member = client.create_member({
|
||||
'member': {
|
||||
'pool_id': pool,
|
||||
|
@ -16,7 +16,6 @@ from heat.engine import attributes
|
||||
from heat.engine import constraints
|
||||
from heat.engine import properties
|
||||
from heat.engine import resource
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.openstack.common.gettextutils import _
|
||||
|
||||
|
||||
@ -97,8 +96,7 @@ class KeyPair(resource.Resource):
|
||||
if self.properties[self.PUBLIC_KEY]:
|
||||
self._public_key = self.properties[self.PUBLIC_KEY]
|
||||
elif self.resource_id:
|
||||
nova_key = nova_utils.get_keypair(self.nova(),
|
||||
self.resource_id)
|
||||
nova_key = self.client_plugin().get_keypair(self.resource_id)
|
||||
self._public_key = nova_key.public_key
|
||||
return self._public_key
|
||||
|
||||
@ -138,8 +136,7 @@ class KeypairConstraint(constraints.BaseCustomConstraint):
|
||||
# Don't validate empty key, which can happen when you use a KeyPair
|
||||
# resource
|
||||
return True
|
||||
nova_client = client.client('nova')
|
||||
nova_utils.get_keypair(nova_client, value)
|
||||
client.client_plugin('nova').get_keypair(value)
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
|
@ -24,6 +24,7 @@ import string
|
||||
from oslo.config import cfg
|
||||
import six
|
||||
from six.moves.urllib import parse as urlparse
|
||||
import warnings
|
||||
|
||||
from heat.common import exception
|
||||
from heat.engine import scheduler
|
||||
@ -49,6 +50,8 @@ def refresh_server(server):
|
||||
'''
|
||||
Refresh server's attributes and log warnings for non-critical API errors.
|
||||
'''
|
||||
warnings.warn('nova_utils.refresh_server is deprecated. '
|
||||
'Use self.client_plugin("nova").refresh_server')
|
||||
try:
|
||||
server.get()
|
||||
except nova_exceptions.OverLimit as exc:
|
||||
@ -72,6 +75,8 @@ def refresh_server(server):
|
||||
|
||||
def get_ip(server, net_type, ip_version):
|
||||
"""Return the server's IP of the given type and version."""
|
||||
warnings.warn('nova_utils.get_ip is deprecated. '
|
||||
'Use self.client_plugin("nova").get_ip')
|
||||
if net_type in server.addresses:
|
||||
for ip in server.addresses[net_type]:
|
||||
if ip['version'] == ip_version:
|
||||
@ -79,6 +84,8 @@ def get_ip(server, net_type, ip_version):
|
||||
|
||||
|
||||
def get_flavor_id(nova_client, flavor):
|
||||
warnings.warn('nova_utils.get_flavor_id is deprecated. '
|
||||
'Use self.client_plugin("nova").get_flavor_id')
|
||||
'''
|
||||
Get the id for the specified flavor name.
|
||||
If the specified value is flavor id, just return it.
|
||||
@ -103,6 +110,8 @@ def get_flavor_id(nova_client, flavor):
|
||||
|
||||
|
||||
def get_keypair(nova_client, key_name):
|
||||
warnings.warn('nova_utils.get_keypair is deprecated. '
|
||||
'Use self.client_plugin("nova").get_keypair')
|
||||
'''
|
||||
Get the public key specified by :key_name:
|
||||
|
||||
@ -119,6 +128,8 @@ def get_keypair(nova_client, key_name):
|
||||
|
||||
def build_userdata(resource, userdata=None, instance_user=None,
|
||||
user_data_format='HEAT_CFNTOOLS'):
|
||||
warnings.warn('nova_utils.build_userdata is deprecated. '
|
||||
'Use self.client_plugin("nova").build_userdata')
|
||||
'''
|
||||
Build multipart data blob for CloudInit which includes user-supplied
|
||||
Metadata, user data, and the required Heat in-instance configuration.
|
||||
@ -241,6 +252,8 @@ def delete_server(server):
|
||||
A co-routine that deletes the server and waits for it to
|
||||
disappear from Nova.
|
||||
'''
|
||||
warnings.warn('nova_utils.delete_server is deprecated. '
|
||||
'Use self.client_plugin("nova").delete_server')
|
||||
if not server:
|
||||
return
|
||||
try:
|
||||
@ -274,12 +287,16 @@ def delete_server(server):
|
||||
@scheduler.wrappertask
|
||||
def resize(server, flavor, flavor_id):
|
||||
"""Resize the server and then call check_resize task to verify."""
|
||||
warnings.warn('nova_utils.resize is deprecated. '
|
||||
'Use self.client_plugin("nova").resize')
|
||||
server.resize(flavor_id)
|
||||
yield check_resize(server, flavor, flavor_id)
|
||||
|
||||
|
||||
def rename(server, name):
|
||||
"""Update the name for a server."""
|
||||
warnings.warn('nova_utils.rename is deprecated. '
|
||||
'Use self.client_plugin("nova").rename')
|
||||
server.update(name)
|
||||
|
||||
|
||||
@ -288,6 +305,8 @@ def check_resize(server, flavor, flavor_id):
|
||||
Verify that a resizing server is properly resized.
|
||||
If that's the case, confirm the resize, if not raise an error.
|
||||
"""
|
||||
warnings.warn('nova_utils.check_resize is deprecated. '
|
||||
'Use self.client_plugin("nova").check_resize')
|
||||
refresh_server(server)
|
||||
while server.status == 'RESIZE':
|
||||
yield
|
||||
@ -303,6 +322,8 @@ def check_resize(server, flavor, flavor_id):
|
||||
@scheduler.wrappertask
|
||||
def rebuild(server, image_id, preserve_ephemeral=False):
|
||||
"""Rebuild the server and call check_rebuild to verify."""
|
||||
warnings.warn('nova_utils.rebuild is deprecated. '
|
||||
'Use self.client_plugin("nova").rebuild')
|
||||
server.rebuild(image_id, preserve_ephemeral=preserve_ephemeral)
|
||||
yield check_rebuild(server, image_id)
|
||||
|
||||
@ -312,6 +333,8 @@ def check_rebuild(server, image_id):
|
||||
Verify that a rebuilding server is rebuilt.
|
||||
Raise error if it ends up in an ERROR state.
|
||||
"""
|
||||
warnings.warn('nova_utils.check_rebuild is deprecated. '
|
||||
'Use self.client_plugin("nova").check_rebuild')
|
||||
refresh_server(server)
|
||||
while server.status == 'REBUILD':
|
||||
yield
|
||||
@ -326,6 +349,8 @@ def meta_serialize(metadata):
|
||||
Serialize non-string metadata values before sending them to
|
||||
Nova.
|
||||
"""
|
||||
warnings.warn('nova_utils.meta_serialize is deprecated. '
|
||||
'Use self.client_plugin("nova").meta_serialize')
|
||||
return dict((key, (value if isinstance(value,
|
||||
six.string_types)
|
||||
else json.dumps(value))
|
||||
@ -334,6 +359,8 @@ def meta_serialize(metadata):
|
||||
|
||||
def meta_update(client, server, metadata):
|
||||
"""Delete/Add the metadata in nova as needed."""
|
||||
warnings.warn('nova_utils.meta_update is deprecated. '
|
||||
'Use self.client_plugin("nova").meta_update')
|
||||
metadata = meta_serialize(metadata)
|
||||
current_md = server.metadata
|
||||
to_del = [key for key in current_md.keys() if key not in metadata]
|
||||
@ -347,6 +374,8 @@ def server_to_ipaddress(client, server):
|
||||
'''
|
||||
Return the server's IP address, fetching it from Nova.
|
||||
'''
|
||||
warnings.warn('nova_utils.server_to_ipaddress is deprecated. '
|
||||
'Use self.client_plugin("nova").server_to_ipaddress')
|
||||
try:
|
||||
server = client.servers.get(server)
|
||||
except nova_exceptions.NotFound as ex:
|
||||
@ -360,5 +389,7 @@ def server_to_ipaddress(client, server):
|
||||
|
||||
def absolute_limits(nova_client):
|
||||
"""Return the absolute limits as a dictionary."""
|
||||
warnings.warn('nova_utils.absolute_limits is deprecated. '
|
||||
'Use self.client_plugin("nova").absolute_limits')
|
||||
limits = nova_client.limits.get()
|
||||
return dict([(limit.name, limit.value) for limit in list(limits.absolute)])
|
||||
|
@ -16,7 +16,6 @@ from heat.engine import attributes
|
||||
from heat.engine import constraints
|
||||
from heat.engine import properties
|
||||
from heat.engine import resource
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.openstack.common.gettextutils import _
|
||||
from heat.openstack.common import log as logging
|
||||
|
||||
@ -228,7 +227,7 @@ class OSDBInstance(resource.Resource):
|
||||
'''
|
||||
Create cloud database instance.
|
||||
'''
|
||||
self.flavor = nova_utils.get_flavor_id(self.trove(),
|
||||
self.flavor = self.client_plugin().get_flavor_id(
|
||||
self.properties[self.FLAVOR])
|
||||
self.volume = {'size': self.properties[self.SIZE]}
|
||||
self.databases = self.properties.get(self.DATABASES)
|
||||
|
@ -22,7 +22,6 @@ from heat.engine import constraints
|
||||
from heat.engine import properties
|
||||
from heat.engine import resource
|
||||
from heat.engine.resources.neutron import subnet
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.engine import scheduler
|
||||
from heat.engine import stack_user
|
||||
from heat.engine import support
|
||||
@ -471,8 +470,8 @@ class Server(stack_user.StackUser):
|
||||
else:
|
||||
instance_user = None
|
||||
|
||||
userdata = nova_utils.build_userdata(
|
||||
self,
|
||||
userdata = self.client_plugin().build_userdata(
|
||||
self.metadata_get(),
|
||||
ud_content,
|
||||
instance_user=instance_user,
|
||||
user_data_format=user_data_format)
|
||||
@ -484,11 +483,12 @@ class Server(stack_user.StackUser):
|
||||
if image:
|
||||
image = self.client_plugin('glance').get_image_id(image)
|
||||
|
||||
flavor_id = nova_utils.get_flavor_id(self.nova(), flavor)
|
||||
flavor_id = self.client_plugin().get_flavor_id(flavor)
|
||||
|
||||
instance_meta = self.properties.get(self.METADATA)
|
||||
if instance_meta is not None:
|
||||
instance_meta = nova_utils.meta_serialize(instance_meta)
|
||||
instance_meta = self.client_plugin().meta_serialize(
|
||||
instance_meta)
|
||||
|
||||
scheduler_hints = self.properties.get(self.SCHEDULER_HINTS)
|
||||
nics = self._build_nics(self.properties.get(self.NETWORKS))
|
||||
@ -532,12 +532,13 @@ class Server(stack_user.StackUser):
|
||||
|
||||
def _check_active(self, server):
|
||||
|
||||
cp = self.client_plugin()
|
||||
if server.status != 'ACTIVE':
|
||||
nova_utils.refresh_server(server)
|
||||
cp.refresh_server(server)
|
||||
|
||||
# Some clouds append extra (STATUS) strings to the status
|
||||
short_server_status = server.status.split('(')[0]
|
||||
if short_server_status in nova_utils.deferred_server_statuses:
|
||||
if short_server_status in cp.deferred_server_statuses:
|
||||
return False
|
||||
elif server.status == 'ACTIVE':
|
||||
return True
|
||||
@ -621,8 +622,8 @@ class Server(stack_user.StackUser):
|
||||
|
||||
def _resolve_attribute(self, name):
|
||||
if name == self.FIRST_ADDRESS:
|
||||
return nova_utils.server_to_ipaddress(
|
||||
self.nova(), self.resource_id) or ''
|
||||
return self.client_plugin().server_to_ipaddress(
|
||||
self.resource_id) or ''
|
||||
try:
|
||||
server = self.nova().servers.get(self.resource_id)
|
||||
except Exception as e:
|
||||
@ -718,8 +719,7 @@ class Server(stack_user.StackUser):
|
||||
|
||||
if self.METADATA in prop_diff:
|
||||
server = self.nova().servers.get(self.resource_id)
|
||||
nova_utils.meta_update(self.nova(),
|
||||
server,
|
||||
self.client_plugin().meta_update(server,
|
||||
prop_diff[self.METADATA])
|
||||
|
||||
if self.FLAVOR in prop_diff:
|
||||
@ -732,11 +732,11 @@ class Server(stack_user.StackUser):
|
||||
raise resource.UpdateReplace(self.name)
|
||||
|
||||
flavor = prop_diff[self.FLAVOR]
|
||||
flavor_id = nova_utils.get_flavor_id(self.nova(), flavor)
|
||||
flavor_id = self.client_plugin().get_flavor_id(flavor)
|
||||
if not server:
|
||||
server = self.nova().servers.get(self.resource_id)
|
||||
checker = scheduler.TaskRunner(nova_utils.resize, server, flavor,
|
||||
flavor_id)
|
||||
checker = scheduler.TaskRunner(self.client_plugin().resize,
|
||||
server, flavor, flavor_id)
|
||||
checkers.append(checker)
|
||||
|
||||
if self.IMAGE in prop_diff:
|
||||
@ -752,14 +752,14 @@ class Server(stack_user.StackUser):
|
||||
preserve_ephemeral = (
|
||||
image_update_policy == 'REBUILD_PRESERVE_EPHEMERAL')
|
||||
checker = scheduler.TaskRunner(
|
||||
nova_utils.rebuild, server, image_id,
|
||||
self.client_plugin().rebuild, server, image_id,
|
||||
preserve_ephemeral=preserve_ephemeral)
|
||||
checkers.append(checker)
|
||||
|
||||
if self.NAME in prop_diff:
|
||||
if not server:
|
||||
server = self.nova().servers.get(self.resource_id)
|
||||
nova_utils.rename(server, prop_diff[self.NAME])
|
||||
self.client_plugin().rename(server, prop_diff[self.NAME])
|
||||
|
||||
if self.NETWORKS in prop_diff:
|
||||
new_networks = prop_diff.get(self.NETWORKS)
|
||||
@ -928,7 +928,7 @@ class Server(stack_user.StackUser):
|
||||
metadata = self.properties.get(self.METADATA)
|
||||
personality = self.properties.get(self.PERSONALITY)
|
||||
if metadata is not None or personality:
|
||||
limits = nova_utils.absolute_limits(self.nova())
|
||||
limits = self.client_plugin().absolute_limits()
|
||||
|
||||
# if 'security_groups' present for the server and explict 'port'
|
||||
# in one or more entries in 'networks', raise validation error
|
||||
@ -977,7 +977,8 @@ class Server(stack_user.StackUser):
|
||||
except Exception as e:
|
||||
self.client_plugin().ignore_not_found(e)
|
||||
else:
|
||||
deleter = scheduler.TaskRunner(nova_utils.delete_server, server)
|
||||
deleter = scheduler.TaskRunner(self.client_plugin().delete_server,
|
||||
server)
|
||||
deleter.start()
|
||||
return deleter
|
||||
|
||||
@ -1022,10 +1023,11 @@ class Server(stack_user.StackUser):
|
||||
if server.status == 'SUSPENDED':
|
||||
return True
|
||||
|
||||
nova_utils.refresh_server(server)
|
||||
cp = self.client_plugin()
|
||||
cp.refresh_server(server)
|
||||
LOG.debug('%(name)s check_suspend_complete status = %(status)s'
|
||||
% {'name': self.name, 'status': server.status})
|
||||
if server.status in list(nova_utils.deferred_server_statuses +
|
||||
if server.status in list(cp.deferred_server_statuses +
|
||||
['ACTIVE']):
|
||||
return server.status == 'SUSPENDED'
|
||||
else:
|
||||
@ -1067,8 +1069,7 @@ class FlavorConstraint(constraints.BaseCustomConstraint):
|
||||
expected_exceptions = (exception.FlavorMissing,)
|
||||
|
||||
def validate_with_client(self, client, value):
|
||||
nova_client = client.client('nova')
|
||||
nova_utils.get_flavor_id(nova_client, value)
|
||||
client.client_plugin('nova').get_flavor_id(value)
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
|
@ -40,7 +40,6 @@ from heat.engine import parser
|
||||
from heat.engine.properties import Properties
|
||||
from heat.engine import resource as res
|
||||
from heat.engine.resources import instance as instances
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.engine import service
|
||||
from heat.engine import stack_lock
|
||||
from heat.engine import watchrule
|
||||
@ -209,6 +208,7 @@ def setup_mocks(mocks, stack, mock_image_constraint=True):
|
||||
mocks.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||
nova.NovaClientPlugin._create().AndReturn(fc)
|
||||
instance = stack['WebServer']
|
||||
metadata = instance.metadata_get()
|
||||
if mock_image_constraint:
|
||||
setup_mock_for_image_constraint(mocks,
|
||||
instance.t['Properties']['ImageId'])
|
||||
@ -216,11 +216,11 @@ def setup_mocks(mocks, stack, mock_image_constraint=True):
|
||||
setup_keystone_mocks(mocks, stack)
|
||||
|
||||
user_data = instance.properties['UserData']
|
||||
server_userdata = nova_utils.build_userdata(instance, user_data,
|
||||
'ec2-user')
|
||||
mocks.StubOutWithMock(nova_utils, 'build_userdata')
|
||||
nova_utils.build_userdata(
|
||||
instance,
|
||||
server_userdata = instance.client_plugin().build_userdata(
|
||||
metadata, user_data, 'ec2-user')
|
||||
mocks.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||
nova.NovaClientPlugin.build_userdata(
|
||||
metadata,
|
||||
instance.t['Properties']['UserData'],
|
||||
'ec2-user').AndReturn(server_userdata)
|
||||
|
||||
|
@ -28,7 +28,6 @@ from heat.engine import parser
|
||||
from heat.engine import resource
|
||||
from heat.engine.resources import instance as instances
|
||||
from heat.engine.resources import network_interface
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.engine import scheduler
|
||||
from heat.tests.common import HeatTestCase
|
||||
from heat.tests import utils
|
||||
@ -1336,8 +1335,10 @@ class InstancesTest(HeatTestCase):
|
||||
"""The default value for instance_user in heat.conf is ec2-user."""
|
||||
return_server = self.fc.servers.list()[1]
|
||||
instance = self._setup_test_instance(return_server, 'default_user')
|
||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
||||
nova_utils.build_userdata(instance, 'wordpress', 'ec2-user')
|
||||
metadata = instance.metadata_get()
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||
nova.NovaClientPlugin.build_userdata(
|
||||
metadata, 'wordpress', 'ec2-user')
|
||||
self.m.ReplayAll()
|
||||
scheduler.TaskRunner(instance.create)()
|
||||
self.m.VerifyAll()
|
||||
@ -1354,8 +1355,10 @@ class InstancesTest(HeatTestCase):
|
||||
instance = self._setup_test_instance(return_server, 'custom_user')
|
||||
self.m.StubOutWithMock(instances.cfg.CONF, 'instance_user')
|
||||
instances.cfg.CONF.instance_user = 'custom_user'
|
||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
||||
nova_utils.build_userdata(instance, 'wordpress', 'custom_user')
|
||||
metadata = instance.metadata_get()
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||
nova.NovaClientPlugin.build_userdata(
|
||||
metadata, 'wordpress', 'custom_user')
|
||||
self.m.ReplayAll()
|
||||
scheduler.TaskRunner(instance.create)()
|
||||
self.m.VerifyAll()
|
||||
@ -1373,8 +1376,10 @@ class InstancesTest(HeatTestCase):
|
||||
instance = self._setup_test_instance(return_server, 'empty_user')
|
||||
self.m.StubOutWithMock(instances.cfg.CONF, 'instance_user')
|
||||
instances.cfg.CONF.instance_user = ''
|
||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
||||
nova_utils.build_userdata(instance, 'wordpress', 'ec2-user')
|
||||
metadata = instance.metadata_get()
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||
nova.NovaClientPlugin.build_userdata(
|
||||
metadata, 'wordpress', 'ec2-user')
|
||||
self.m.ReplayAll()
|
||||
scheduler.TaskRunner(instance.create)()
|
||||
self.m.VerifyAll()
|
||||
|
@ -20,7 +20,6 @@ from heat.engine import environment
|
||||
from heat.engine import parser
|
||||
from heat.engine.resources import instance as instances
|
||||
from heat.engine.resources import network_interface as network_interfaces
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.engine import scheduler
|
||||
from heat.tests.common import HeatTestCase
|
||||
from heat.tests import utils
|
||||
@ -170,6 +169,7 @@ class instancesTest(HeatTestCase):
|
||||
resource_defns = stack.t.resource_definitions(stack)
|
||||
instance = instances.Instance('%s_name' % name,
|
||||
resource_defns['WebServer'], stack)
|
||||
metadata = instance.metadata_get()
|
||||
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||
@ -180,13 +180,13 @@ class instancesTest(HeatTestCase):
|
||||
instance.neutron().MultipleTimes().AndReturn(FakeNeutron())
|
||||
|
||||
# need to resolve the template functions
|
||||
server_userdata = nova_utils.build_userdata(
|
||||
instance,
|
||||
server_userdata = instance.client_plugin().build_userdata(
|
||||
metadata,
|
||||
instance.t['Properties']['UserData'],
|
||||
'ec2-user')
|
||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
||||
nova_utils.build_userdata(
|
||||
instance,
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||
nova.NovaClientPlugin.build_userdata(
|
||||
metadata,
|
||||
instance.t['Properties']['UserData'],
|
||||
'ec2-user').AndReturn(server_userdata)
|
||||
|
||||
@ -225,6 +225,7 @@ class instancesTest(HeatTestCase):
|
||||
|
||||
instance = instances.Instance('%s_name' % name,
|
||||
resource_defns['WebServer'], stack)
|
||||
metadata = instance.metadata_get()
|
||||
|
||||
self._mock_get_image_id_success(image_id, 1)
|
||||
self.m.StubOutWithMock(nic, 'neutron')
|
||||
@ -234,13 +235,13 @@ class instancesTest(HeatTestCase):
|
||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||
|
||||
# need to resolve the template functions
|
||||
server_userdata = nova_utils.build_userdata(
|
||||
instance,
|
||||
server_userdata = instance.client_plugin().build_userdata(
|
||||
metadata,
|
||||
instance.t['Properties']['UserData'],
|
||||
'ec2-user')
|
||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
||||
nova_utils.build_userdata(
|
||||
instance,
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||
nova.NovaClientPlugin.build_userdata(
|
||||
metadata,
|
||||
instance.t['Properties']['UserData'],
|
||||
'ec2-user').AndReturn(server_userdata)
|
||||
|
||||
|
@ -20,10 +20,11 @@ from oslo.config import cfg
|
||||
|
||||
from heat.common import template_format
|
||||
from heat.db import api as db_api
|
||||
from heat.engine.clients.os import glance
|
||||
from heat.engine.clients.os import nova
|
||||
from heat.engine import environment
|
||||
from heat.engine import parser
|
||||
from heat.engine.resources import instance
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.engine import template
|
||||
from heat.tests.common import HeatTestCase
|
||||
from heat.tests import utils
|
||||
@ -123,11 +124,12 @@ class AutoScalingTest(HeatTestCase):
|
||||
self.m.StubOutWithMock(neutronclient.Client, 'create_member')
|
||||
self.m.StubOutWithMock(neutronclient.Client, 'list_members')
|
||||
|
||||
self.m.StubOutWithMock(nova_utils, 'server_to_ipaddress')
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'server_to_ipaddress')
|
||||
self.m.StubOutWithMock(parser.Stack, 'validate')
|
||||
|
||||
self.m.StubOutWithMock(instance.Instance, 'handle_create')
|
||||
self.m.StubOutWithMock(instance.Instance, 'check_create_complete')
|
||||
self.m.StubOutWithMock(glance.ImageConstraint, "validate")
|
||||
|
||||
def test_lb(self):
|
||||
|
||||
@ -276,10 +278,10 @@ class AutoScalingTest(HeatTestCase):
|
||||
instance.Instance.check_create_complete(mox.IgnoreArg())\
|
||||
.AndReturn(True)
|
||||
|
||||
self.stub_ImageConstraint_validate()
|
||||
glance.ImageConstraint.validate(
|
||||
mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(True)
|
||||
|
||||
nova_utils.server_to_ipaddress(
|
||||
mox.IgnoreArg(),
|
||||
nova.NovaClientPlugin.server_to_ipaddress(
|
||||
mox.IgnoreArg()).AndReturn('1.2.3.4')
|
||||
|
||||
neutronclient.Client.create_member(membera_block).\
|
||||
@ -304,15 +306,13 @@ class AutoScalingTest(HeatTestCase):
|
||||
instance.Instance.check_create_complete(mox.IgnoreArg())\
|
||||
.AndReturn(True)
|
||||
|
||||
nova_utils.server_to_ipaddress(
|
||||
mox.IgnoreArg(),
|
||||
nova.NovaClientPlugin.server_to_ipaddress(
|
||||
mox.IgnoreArg()).AndReturn('1.2.3.5')
|
||||
|
||||
neutronclient.Client.create_member(memberb_block).\
|
||||
AndReturn(memberb_ret_block)
|
||||
|
||||
nova_utils.server_to_ipaddress(
|
||||
mox.IgnoreArg(),
|
||||
nova.NovaClientPlugin.server_to_ipaddress(
|
||||
mox.IgnoreArg()).AndReturn('1.2.3.6')
|
||||
|
||||
neutronclient.Client.create_member(memberc_block).\
|
||||
|
@ -15,7 +15,6 @@ from heat.common import template_format
|
||||
from heat.engine.clients.os import glance
|
||||
from heat.engine.clients.os import nova
|
||||
from heat.engine.resources import instance as instances
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.engine import scheduler
|
||||
from heat.tests.common import HeatTestCase
|
||||
from heat.tests import utils
|
||||
@ -66,13 +65,14 @@ class nokeyTest(HeatTestCase):
|
||||
'CentOS 5.2').MultipleTimes().AndReturn(1)
|
||||
|
||||
# need to resolve the template functions
|
||||
server_userdata = nova_utils.build_userdata(
|
||||
instance,
|
||||
metadata = instance.metadata_get()
|
||||
server_userdata = instance.client_plugin().build_userdata(
|
||||
metadata,
|
||||
instance.t['Properties']['UserData'],
|
||||
'ec2-user')
|
||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
||||
nova_utils.build_userdata(
|
||||
instance,
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||
nova.NovaClientPlugin.build_userdata(
|
||||
metadata,
|
||||
instance.t['Properties']['UserData'],
|
||||
'ec2-user').AndReturn(server_userdata)
|
||||
|
||||
|
238
heat/tests/test_nova_client.py
Normal file
238
heat/tests/test_nova_client.py
Normal file
@ -0,0 +1,238 @@
|
||||
#
|
||||
# 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.
|
||||
"""Tests for :module:'heat.engine.resources.nova_utls'."""
|
||||
|
||||
import mock
|
||||
from novaclient import exceptions as nova_exceptions
|
||||
from oslo.config import cfg
|
||||
import uuid
|
||||
|
||||
from heat.common import exception
|
||||
from heat.engine.clients.os import nova
|
||||
from heat.tests.common import HeatTestCase
|
||||
from heat.tests import utils
|
||||
|
||||
|
||||
class NovaClientPluginTestCase(HeatTestCase):
|
||||
def setUp(self):
|
||||
super(NovaClientPluginTestCase, self).setUp()
|
||||
self.nova_client = self.m.CreateMockAnything()
|
||||
con = utils.dummy_context()
|
||||
c = con.clients
|
||||
self.nova_plugin = c.client_plugin('nova')
|
||||
self.nova_plugin._client = self.nova_client
|
||||
|
||||
|
||||
class NovaClientPluginTests(NovaClientPluginTestCase):
|
||||
"""
|
||||
Basic tests for the helper methods in
|
||||
:module:'heat.engine.resources.nova_utils'.
|
||||
"""
|
||||
|
||||
def test_get_ip(self):
|
||||
my_image = self.m.CreateMockAnything()
|
||||
my_image.addresses = {
|
||||
'public': [{'version': 4,
|
||||
'addr': '4.5.6.7'},
|
||||
{'version': 6,
|
||||
'addr': '2401:1801:7800:0101:c058:dd33:ff18:04e6'}],
|
||||
'private': [{'version': 4,
|
||||
'addr': '10.13.12.13'}]}
|
||||
|
||||
expected = '4.5.6.7'
|
||||
observed = self.nova_plugin.get_ip(my_image, 'public', 4)
|
||||
self.assertEqual(expected, observed)
|
||||
|
||||
expected = '10.13.12.13'
|
||||
observed = self.nova_plugin.get_ip(my_image, 'private', 4)
|
||||
self.assertEqual(expected, observed)
|
||||
|
||||
expected = '2401:1801:7800:0101:c058:dd33:ff18:04e6'
|
||||
observed = self.nova_plugin.get_ip(my_image, 'public', 6)
|
||||
self.assertEqual(expected, observed)
|
||||
|
||||
def test_get_flavor_id(self):
|
||||
"""Tests the get_flavor_id function."""
|
||||
flav_id = str(uuid.uuid4())
|
||||
flav_name = 'X-Large'
|
||||
my_flavor = self.m.CreateMockAnything()
|
||||
my_flavor.name = flav_name
|
||||
my_flavor.id = flav_id
|
||||
self.nova_client.flavors = self.m.CreateMockAnything()
|
||||
self.nova_client.flavors.list().MultipleTimes().AndReturn([my_flavor])
|
||||
self.m.ReplayAll()
|
||||
self.assertEqual(flav_id, self.nova_plugin.get_flavor_id(flav_name))
|
||||
self.assertEqual(flav_id, self.nova_plugin.get_flavor_id(flav_id))
|
||||
self.assertRaises(exception.FlavorMissing,
|
||||
self.nova_plugin.get_flavor_id, 'noflavor')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_get_keypair(self):
|
||||
"""Tests the get_keypair function."""
|
||||
my_pub_key = 'a cool public key string'
|
||||
my_key_name = 'mykey'
|
||||
my_key = self.m.CreateMockAnything()
|
||||
my_key.public_key = my_pub_key
|
||||
my_key.name = my_key_name
|
||||
self.nova_client.keypairs = self.m.CreateMockAnything()
|
||||
self.nova_client.keypairs.get(
|
||||
my_key_name).AndReturn(my_key)
|
||||
self.nova_client.keypairs.get(
|
||||
'notakey').AndRaise(nova_exceptions.NotFound(404))
|
||||
self.m.ReplayAll()
|
||||
self.assertEqual(my_key, self.nova_plugin.get_keypair(my_key_name))
|
||||
self.assertRaises(exception.UserKeyPairMissing,
|
||||
self.nova_plugin.get_keypair, 'notakey')
|
||||
self.m.VerifyAll()
|
||||
|
||||
|
||||
class NovaUtilsRefreshServerTests(NovaClientPluginTestCase):
|
||||
|
||||
def test_successful_refresh(self):
|
||||
server = self.m.CreateMockAnything()
|
||||
server.get().AndReturn(None)
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertIsNone(self.nova_plugin.refresh_server(server))
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_overlimit_error(self):
|
||||
server = mock.Mock()
|
||||
server.get.side_effect = nova_exceptions.OverLimit(
|
||||
413, "limit reached")
|
||||
self.assertIsNone(self.nova_plugin.refresh_server(server))
|
||||
|
||||
def test_500_error(self):
|
||||
server = self.m.CreateMockAnything()
|
||||
msg = ("ClientException: The server has either erred or is "
|
||||
"incapable of performing the requested operation.")
|
||||
server.get().AndRaise(
|
||||
nova_exceptions.ClientException(500, msg))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertIsNone(self.nova_plugin.refresh_server(server))
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_503_error(self):
|
||||
server = self.m.CreateMockAnything()
|
||||
msg = ("ClientException: The server has either erred or is "
|
||||
"incapable of performing the requested operation.")
|
||||
server.get().AndRaise(
|
||||
nova_exceptions.ClientException(503, msg))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertIsNone(self.nova_plugin.refresh_server(server))
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_unhandled_exception(self):
|
||||
server = self.m.CreateMockAnything()
|
||||
msg = ("ClientException: The server has either erred or is "
|
||||
"incapable of performing the requested operation.")
|
||||
server.get().AndRaise(
|
||||
nova_exceptions.ClientException(501, msg))
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertRaises(nova_exceptions.ClientException,
|
||||
self.nova_plugin.refresh_server, server)
|
||||
self.m.VerifyAll()
|
||||
|
||||
|
||||
class NovaUtilsUserdataTests(NovaClientPluginTestCase):
|
||||
|
||||
def test_build_userdata(self):
|
||||
"""Tests the build_userdata function."""
|
||||
cfg.CONF.set_override('heat_metadata_server_url',
|
||||
'http://server.test:123')
|
||||
cfg.CONF.set_override('heat_watch_server_url',
|
||||
'http://server.test:345')
|
||||
cfg.CONF.set_override('instance_connection_is_secure',
|
||||
False)
|
||||
cfg.CONF.set_override(
|
||||
'instance_connection_https_validate_certificates', False)
|
||||
data = self.nova_plugin.build_userdata({})
|
||||
self.assertIn("Content-Type: text/cloud-config;", data)
|
||||
self.assertIn("Content-Type: text/cloud-boothook;", data)
|
||||
self.assertIn("Content-Type: text/part-handler;", data)
|
||||
self.assertIn("Content-Type: text/x-cfninitdata;", data)
|
||||
self.assertIn("Content-Type: text/x-shellscript;", data)
|
||||
self.assertIn("http://server.test:345", data)
|
||||
self.assertIn("http://server.test:123", data)
|
||||
self.assertIn("[Boto]", data)
|
||||
|
||||
def test_build_userdata_without_instance_user(self):
|
||||
"""Don't add a custom instance user when not requested."""
|
||||
cfg.CONF.set_override('instance_user',
|
||||
'config_instance_user')
|
||||
cfg.CONF.set_override('heat_metadata_server_url',
|
||||
'http://server.test:123')
|
||||
cfg.CONF.set_override('heat_watch_server_url',
|
||||
'http://server.test:345')
|
||||
data = self.nova_plugin.build_userdata({}, instance_user=None)
|
||||
self.assertNotIn('user: ', data)
|
||||
self.assertNotIn('useradd', data)
|
||||
self.assertNotIn('config_instance_user', data)
|
||||
|
||||
def test_build_userdata_with_instance_user(self):
|
||||
"""Add the custom instance user when requested."""
|
||||
self.m.StubOutWithMock(nova.cfg, 'CONF')
|
||||
cnf = nova.cfg.CONF
|
||||
cnf.instance_user = 'config_instance_user'
|
||||
cnf.heat_metadata_server_url = 'http://server.test:123'
|
||||
cnf.heat_watch_server_url = 'http://server.test:345'
|
||||
data = self.nova_plugin.build_userdata(
|
||||
None, instance_user="custominstanceuser")
|
||||
self.assertNotIn('config_instance_user', data)
|
||||
self.assertIn("custominstanceuser", data)
|
||||
|
||||
|
||||
class NovaUtilsMetadataTests(NovaClientPluginTestCase):
|
||||
|
||||
def test_serialize_string(self):
|
||||
original = {'test_key': 'simple string value'}
|
||||
self.assertEqual(original, self.nova_plugin.meta_serialize(original))
|
||||
|
||||
def test_serialize_int(self):
|
||||
original = {'test_key': 123}
|
||||
expected = {'test_key': '123'}
|
||||
self.assertEqual(expected, self.nova_plugin.meta_serialize(original))
|
||||
|
||||
def test_serialize_list(self):
|
||||
original = {'test_key': [1, 2, 3]}
|
||||
expected = {'test_key': '[1, 2, 3]'}
|
||||
self.assertEqual(expected, self.nova_plugin.meta_serialize(original))
|
||||
|
||||
def test_serialize_dict(self):
|
||||
original = {'test_key': {'a': 'b', 'c': 'd'}}
|
||||
expected = {'test_key': '{"a": "b", "c": "d"}'}
|
||||
self.assertEqual(expected, self.nova_plugin.meta_serialize(original))
|
||||
|
||||
def test_serialize_none(self):
|
||||
original = {'test_key': None}
|
||||
expected = {'test_key': 'null'}
|
||||
self.assertEqual(expected, self.nova_plugin.meta_serialize(original))
|
||||
|
||||
def test_serialize_combined(self):
|
||||
original = {
|
||||
'test_key_1': 123,
|
||||
'test_key_2': 'a string',
|
||||
'test_key_3': {'a': 'b'},
|
||||
'test_key_4': None,
|
||||
}
|
||||
expected = {
|
||||
'test_key_1': '123',
|
||||
'test_key_2': 'a string',
|
||||
'test_key_3': '{"a": "b"}',
|
||||
'test_key_4': 'null',
|
||||
}
|
||||
|
||||
self.assertEqual(expected, self.nova_plugin.meta_serialize(original))
|
@ -35,6 +35,10 @@ class NovaUtilsTests(HeatTestCase):
|
||||
def setUp(self):
|
||||
super(NovaUtilsTests, self).setUp()
|
||||
self.nova_client = self.m.CreateMockAnything()
|
||||
self.mock_warnings = mock.patch(
|
||||
'heat.engine.resources.nova_utils.warnings')
|
||||
self.mock_warnings.start()
|
||||
self.addCleanup(self.mock_warnings.stop)
|
||||
|
||||
def test_get_ip(self):
|
||||
my_image = self.m.CreateMockAnything()
|
||||
@ -126,6 +130,13 @@ class NovaUtilsTests(HeatTestCase):
|
||||
|
||||
class NovaUtilsRefreshServerTests(HeatTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(NovaUtilsRefreshServerTests, self).setUp()
|
||||
self.mock_warnings = mock.patch(
|
||||
'heat.engine.resources.nova_utils.warnings')
|
||||
self.mock_warnings.start()
|
||||
self.addCleanup(self.mock_warnings.stop)
|
||||
|
||||
def test_successful_refresh(self):
|
||||
server = self.m.CreateMockAnything()
|
||||
server.get().AndReturn(None)
|
||||
@ -170,6 +181,10 @@ class NovaUtilsUserdataTests(HeatTestCase):
|
||||
def setUp(self):
|
||||
super(NovaUtilsUserdataTests, self).setUp()
|
||||
self.nova_client = self.m.CreateMockAnything()
|
||||
self.mock_warnings = mock.patch(
|
||||
'heat.engine.resources.nova_utils.warnings')
|
||||
self.mock_warnings.start()
|
||||
self.addCleanup(self.mock_warnings.stop)
|
||||
|
||||
def test_build_userdata(self):
|
||||
"""Tests the build_userdata function."""
|
||||
@ -228,6 +243,13 @@ class NovaUtilsUserdataTests(HeatTestCase):
|
||||
|
||||
class NovaUtilsMetadataTests(HeatTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(NovaUtilsMetadataTests, self).setUp()
|
||||
self.mock_warnings = mock.patch(
|
||||
'heat.engine.resources.nova_utils.warnings')
|
||||
self.mock_warnings.start()
|
||||
self.addCleanup(self.mock_warnings.stop)
|
||||
|
||||
def test_serialize_string(self):
|
||||
original = {'test_key': 'simple string value'}
|
||||
self.assertEqual(original, nova_utils.meta_serialize(original))
|
||||
|
@ -18,6 +18,7 @@ import six
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import template_format
|
||||
from heat.engine.clients.os import trove
|
||||
from heat.engine import parser
|
||||
from heat.engine.resources import os_database
|
||||
from heat.engine import scheduler
|
||||
@ -97,12 +98,10 @@ class OSDBInstanceTest(HeatTestCase):
|
||||
return instance
|
||||
|
||||
def _stubout_create(self, instance, fake_dbinstance):
|
||||
self.m.StubOutWithMock(instance, 'trove')
|
||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(self.fc, 'flavors')
|
||||
self.m.StubOutWithMock(self.fc.flavors, "list")
|
||||
self.fc.flavors.list().AndReturn([FakeFlavor(1, '1GB'),
|
||||
FakeFlavor(2, '2GB')])
|
||||
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(trove.TroveClientPlugin, 'get_flavor_id')
|
||||
trove.TroveClientPlugin.get_flavor_id('1GB').AndReturn(1)
|
||||
self.m.StubOutWithMock(self.fc, 'instances')
|
||||
self.m.StubOutWithMock(self.fc.instances, 'create')
|
||||
users = [{"name": "testuser", "password": "pass", "host": "%",
|
||||
@ -121,8 +120,8 @@ class OSDBInstanceTest(HeatTestCase):
|
||||
self.m.ReplayAll()
|
||||
|
||||
def _stubout_validate(self, instance):
|
||||
self.m.StubOutWithMock(instance, 'trove')
|
||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(self.fc, 'datastore_versions')
|
||||
self.m.StubOutWithMock(self.fc.datastore_versions, 'list')
|
||||
self.fc.datastore_versions.list(instance.properties['datastore_type']
|
||||
@ -144,8 +143,8 @@ class OSDBInstanceTest(HeatTestCase):
|
||||
t['Resources']['MySqlCloudDB']['Properties']['restore_point'] = "1234"
|
||||
instance = self._setup_test_clouddbinstance('dbinstance_create', t)
|
||||
|
||||
self.m.StubOutWithMock(instance, 'trove')
|
||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(self.fc, 'flavors')
|
||||
self.m.StubOutWithMock(self.fc.flavors, "list")
|
||||
self.fc.flavors.list().AndReturn([FakeFlavor(1, '1GB'),
|
||||
@ -281,8 +280,8 @@ class OSDBInstanceTest(HeatTestCase):
|
||||
t = template_format.parse(db_template)
|
||||
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
|
||||
instance.resource_id = 12345
|
||||
self.m.StubOutWithMock(instance, 'trove')
|
||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(self.fc, 'instances')
|
||||
self.m.StubOutWithMock(self.fc.instances, 'get')
|
||||
self.fc.instances.get(12345).AndReturn(fake_dbinstance)
|
||||
@ -296,8 +295,8 @@ class OSDBInstanceTest(HeatTestCase):
|
||||
t = template_format.parse(db_template)
|
||||
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
|
||||
instance.resource_id = 12345
|
||||
self.m.StubOutWithMock(instance, 'trove')
|
||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(self.fc, 'instances')
|
||||
self.m.StubOutWithMock(self.fc.instances, 'get')
|
||||
self.fc.instances.get(12345).AndReturn(fake_dbinstance)
|
||||
@ -312,8 +311,8 @@ class OSDBInstanceTest(HeatTestCase):
|
||||
t = template_format.parse(db_template)
|
||||
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
|
||||
instance.resource_id = 12345
|
||||
self.m.StubOutWithMock(instance, 'trove')
|
||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(self.fc, 'instances')
|
||||
self.m.StubOutWithMock(self.fc.instances, 'get')
|
||||
self.fc.instances.get(12345).AndReturn(fake_dbinstance)
|
||||
@ -419,8 +418,8 @@ class OSDBInstanceTest(HeatTestCase):
|
||||
'datastore_type'] = 'mysql'
|
||||
t['Resources']['MySqlCloudDB']['Properties'].pop('datastore_version')
|
||||
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
|
||||
self.m.StubOutWithMock(instance, 'trove')
|
||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(self.fc, 'datastore_versions')
|
||||
self.m.StubOutWithMock(self.fc.datastore_versions, 'list')
|
||||
self.fc.datastore_versions.list(
|
||||
|
@ -28,7 +28,6 @@ from heat.engine.clients.os import nova
|
||||
from heat.engine import environment
|
||||
from heat.engine import parser
|
||||
from heat.engine import resource
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.engine.resources import server as servers
|
||||
from heat.engine import scheduler
|
||||
from heat.openstack.common.gettextutils import _
|
||||
@ -175,12 +174,8 @@ class ServersTest(HeatTestCase):
|
||||
glance.GlanceClientPlugin.get_image_id(image_id).AndRaise(exp)
|
||||
|
||||
def _mock_get_keypair_success(self, keypair_input, keypair):
|
||||
n_cli_mock = self.m.CreateMockAnything()
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||
nova.NovaClientPlugin._create().AndReturn(
|
||||
n_cli_mock)
|
||||
self.m.StubOutWithMock(nova_utils, 'get_keypair')
|
||||
nova_utils.get_keypair(n_cli_mock, keypair_input).MultipleTimes().\
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'get_keypair')
|
||||
nova.NovaClientPlugin.get_keypair(keypair_input).MultipleTimes().\
|
||||
AndReturn(keypair)
|
||||
|
||||
def _server_validate_mock(self, server):
|
||||
@ -763,8 +758,11 @@ class ServersTest(HeatTestCase):
|
||||
web_server = tmpl.t['Resources']['WebServer']
|
||||
del web_server['Properties']['image']
|
||||
|
||||
def create_server(device_name, mock_create=True):
|
||||
self.m.UnsetStubs()
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||
self.m.ReplayAll()
|
||||
|
||||
def create_server(device_name):
|
||||
web_server['Properties']['block_device_mapping'] = [{
|
||||
"device_name": device_name,
|
||||
"volume_id": "5d7e27da-6703-4f7e-9f94-1f67abef734c",
|
||||
@ -773,17 +771,13 @@ class ServersTest(HeatTestCase):
|
||||
resource_defns = tmpl.resource_definitions(stack)
|
||||
server = servers.Server('server_with_bootable_volume',
|
||||
resource_defns['WebServer'], stack)
|
||||
if mock_create:
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||
self.m.ReplayAll()
|
||||
return server
|
||||
|
||||
server = create_server(u'vda')
|
||||
self.assertIsNone(server.validate())
|
||||
server = create_server('vda', mock_create=False)
|
||||
server = create_server('vda')
|
||||
self.assertIsNone(server.validate())
|
||||
server = create_server('vdb', mock_create=False)
|
||||
server = create_server('vdb')
|
||||
ex = self.assertRaises(exception.StackValidationFailed,
|
||||
server.validate)
|
||||
self.assertEqual('Neither image nor bootable volume is specified for '
|
||||
@ -825,7 +819,9 @@ class ServersTest(HeatTestCase):
|
||||
server = servers.Server('server_validate_test',
|
||||
resource_defns['WebServer'], stack)
|
||||
|
||||
self.stub_ImageConstraint_validate()
|
||||
self.m.StubOutWithMock(glance.ImageConstraint, "validate")
|
||||
glance.ImageConstraint.validate(
|
||||
mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(True)
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertIsNone(server.validate())
|
||||
@ -1015,7 +1011,7 @@ class ServersTest(HeatTestCase):
|
||||
new_meta = {'test': 123}
|
||||
self.m.StubOutWithMock(self.fc.servers, 'set_meta')
|
||||
self.fc.servers.set_meta(return_server,
|
||||
nova_utils.meta_serialize(
|
||||
server.client_plugin().meta_serialize(
|
||||
new_meta)).AndReturn(None)
|
||||
self.m.ReplayAll()
|
||||
update_template = copy.deepcopy(server.t)
|
||||
@ -1040,7 +1036,7 @@ class ServersTest(HeatTestCase):
|
||||
# If we're going to call set_meta() directly we
|
||||
# need to handle the serialization ourselves.
|
||||
self.fc.servers.set_meta(return_server,
|
||||
nova_utils.meta_serialize(
|
||||
server.client_plugin().meta_serialize(
|
||||
new_meta)).AndReturn(None)
|
||||
self.m.ReplayAll()
|
||||
update_template = copy.deepcopy(server.t)
|
||||
@ -1229,7 +1225,9 @@ class ServersTest(HeatTestCase):
|
||||
image_id = self.getUniqueString()
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||
self.stub_ImageConstraint_validate()
|
||||
self.m.StubOutWithMock(glance.ImageConstraint, "validate")
|
||||
glance.ImageConstraint.validate(
|
||||
mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(True)
|
||||
self.m.ReplayAll()
|
||||
|
||||
update_template = copy.deepcopy(server.t)
|
||||
@ -1237,8 +1235,6 @@ class ServersTest(HeatTestCase):
|
||||
updater = scheduler.TaskRunner(server.update, update_template)
|
||||
self.assertRaises(resource.UpdateReplace, updater)
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def _test_server_update_image_rebuild(self, status, policy='REBUILD'):
|
||||
# Server.handle_update supports changing the image, and makes
|
||||
# the change making a rebuild API call against Nova.
|
||||
@ -1339,7 +1335,9 @@ class ServersTest(HeatTestCase):
|
||||
server = self._create_test_server(return_server,
|
||||
'update_prop')
|
||||
|
||||
self.stub_ImageConstraint_validate()
|
||||
self.m.StubOutWithMock(glance.ImageConstraint, "validate")
|
||||
glance.ImageConstraint.validate(
|
||||
mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(True)
|
||||
self.m.ReplayAll()
|
||||
|
||||
update_template = copy.deepcopy(server.t)
|
||||
@ -1347,8 +1345,6 @@ class ServersTest(HeatTestCase):
|
||||
updater = scheduler.TaskRunner(server.update, update_template)
|
||||
self.assertRaises(resource.UpdateReplace, updater)
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_server_status_build(self):
|
||||
return_server = self.fc.servers.list()[0]
|
||||
server = self._setup_test_server(return_server,
|
||||
@ -1857,8 +1853,6 @@ class ServersTest(HeatTestCase):
|
||||
self.m.StubOutWithMock(self.fc.limits, 'get')
|
||||
self.fc.limits.get().MultipleTimes().AndReturn(self.limits)
|
||||
|
||||
self.m.StubOutWithMock(server, 'nova')
|
||||
server.nova().MultipleTimes().AndReturn(self.fc)
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||
self._mock_get_image_id_success('F17-x86_64-gold', 'image_id')
|
||||
@ -1985,8 +1979,10 @@ class ServersTest(HeatTestCase):
|
||||
"""The default value for instance_user in heat.conf is ec2-user."""
|
||||
return_server = self.fc.servers.list()[1]
|
||||
server = self._setup_test_server(return_server, 'default_user')
|
||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
||||
nova_utils.build_userdata(server,
|
||||
metadata = server.metadata_get()
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||
nova.NovaClientPlugin.build_userdata(
|
||||
metadata,
|
||||
'wordpress',
|
||||
instance_user='ec2-user',
|
||||
user_data_format='HEAT_CFNTOOLS')
|
||||
@ -2023,8 +2019,10 @@ class ServersTest(HeatTestCase):
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||
self._mock_get_image_id_success('F17-x86_64-gold', image_id)
|
||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
||||
nova_utils.build_userdata(server,
|
||||
metadata = server.metadata_get()
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||
nova.NovaClientPlugin.build_userdata(
|
||||
metadata,
|
||||
'wordpress',
|
||||
instance_user='custom_user',
|
||||
user_data_format='HEAT_CFNTOOLS')
|
||||
@ -2044,8 +2042,10 @@ class ServersTest(HeatTestCase):
|
||||
server = self._setup_test_server(return_server, 'custom_user')
|
||||
self.m.StubOutWithMock(servers.cfg.CONF, 'instance_user')
|
||||
servers.cfg.CONF.instance_user = 'custom_user'
|
||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
||||
nova_utils.build_userdata(server,
|
||||
metadata = server.metadata_get()
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||
nova.NovaClientPlugin.build_userdata(
|
||||
metadata,
|
||||
'wordpress',
|
||||
instance_user='custom_user',
|
||||
user_data_format='HEAT_CFNTOOLS')
|
||||
@ -2067,8 +2067,10 @@ class ServersTest(HeatTestCase):
|
||||
server = self._setup_test_server(return_server, 'custom_user')
|
||||
self.m.StubOutWithMock(servers.cfg.CONF, 'instance_user')
|
||||
servers.cfg.CONF.instance_user = ''
|
||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
||||
nova_utils.build_userdata(server,
|
||||
metadata = server.metadata_get()
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||
nova.NovaClientPlugin.build_userdata(
|
||||
metadata,
|
||||
'wordpress',
|
||||
instance_user=None,
|
||||
user_data_format='HEAT_CFNTOOLS')
|
||||
@ -2531,7 +2533,7 @@ class ServersTest(HeatTestCase):
|
||||
# is NOT called during call to server.validate().
|
||||
# This is the way to validate that no excessive calls to Nova
|
||||
# are made during validation.
|
||||
self.m.StubOutWithMock(nova_utils, 'absolute_limits')
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'absolute_limits')
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||
self._mock_get_image_id_success('F17-x86_64-gold', 'image_id')
|
||||
|
@ -22,7 +22,6 @@ from heat.engine.clients.os import nova
|
||||
from heat.engine import environment
|
||||
from heat.engine import parser
|
||||
from heat.engine.resources import instance as instances
|
||||
from heat.engine.resources import nova_utils
|
||||
from heat.engine import scheduler
|
||||
from heat.tests.common import HeatTestCase
|
||||
from heat.tests import utils
|
||||
@ -152,13 +151,14 @@ class ServerTagsTest(HeatTestCase):
|
||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||
self._mock_get_image_id_success('CentOS 5.2', 1)
|
||||
# need to resolve the template functions
|
||||
server_userdata = nova_utils.build_userdata(
|
||||
instance,
|
||||
metadata = instance.metadata_get()
|
||||
server_userdata = instance.client_plugin().build_userdata(
|
||||
metadata,
|
||||
instance.t['Properties']['UserData'],
|
||||
'ec2-user')
|
||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
||||
nova_utils.build_userdata(
|
||||
instance,
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||
nova.NovaClientPlugin.build_userdata(
|
||||
metadata,
|
||||
instance.t['Properties']['UserData'],
|
||||
'ec2-user').AndReturn(server_userdata)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user