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.common import exception
|
||||||
from heat.engine import attributes
|
from heat.engine import attributes
|
||||||
from heat.engine import properties
|
from heat.engine import properties
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.engine.resources import server
|
from heat.engine.resources import server
|
||||||
from heat.openstack.common.gettextutils import _
|
from heat.openstack.common.gettextutils import _
|
||||||
from heat.openstack.common import log as logging
|
from heat.openstack.common import log as logging
|
||||||
@ -200,7 +199,7 @@ class CloudServer(server.Server):
|
|||||||
if not self._check_active(server):
|
if not self._check_active(server):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
nova_utils.refresh_server(server)
|
self.client_plugin().refresh_server(server)
|
||||||
|
|
||||||
if 'rack_connect' in self.context.roles and not \
|
if 'rack_connect' in self.context.roles and not \
|
||||||
self._check_rack_connect_complete(server):
|
self._check_rack_connect_complete(server):
|
||||||
@ -216,7 +215,7 @@ class CloudServer(server.Server):
|
|||||||
if name == self.DISTRO:
|
if name == self.DISTRO:
|
||||||
return self.distro
|
return self.distro
|
||||||
if name == self.PRIVATE_IP_V4:
|
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:
|
if name == self.ADMIN_PASS_ATTR:
|
||||||
return self.data().get(self.ADMIN_PASS_ATTR, '')
|
return self.data().get(self.ADMIN_PASS_ATTR, '')
|
||||||
return super(CloudServer, self)._resolve_attribute(name)
|
return super(CloudServer, self)._resolve_attribute(name)
|
||||||
|
@ -11,15 +11,42 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# 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 client as nc
|
||||||
from novaclient import exceptions
|
from novaclient import exceptions
|
||||||
from novaclient import shell as novashell
|
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.clients import client_plugin
|
||||||
|
from heat.engine import scheduler
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NovaClientPlugin(client_plugin.ClientPlugin):
|
class NovaClientPlugin(client_plugin.ClientPlugin):
|
||||||
|
|
||||||
|
deferred_server_statuses = ['BUILD',
|
||||||
|
'HARD_REBOOT',
|
||||||
|
'PASSWORD',
|
||||||
|
'REBOOT',
|
||||||
|
'RESCUE',
|
||||||
|
'RESIZE',
|
||||||
|
'REVERT_RESIZE',
|
||||||
|
'SHUTOFF',
|
||||||
|
'SUSPENDED',
|
||||||
|
'VERIFY_RESIZE']
|
||||||
|
|
||||||
exceptions_module = exceptions
|
exceptions_module = exceptions
|
||||||
|
|
||||||
def _create(self):
|
def _create(self):
|
||||||
@ -58,3 +85,307 @@ class NovaClientPlugin(client_plugin.ClientPlugin):
|
|||||||
|
|
||||||
def is_bad_request(self, ex):
|
def is_bad_request(self, ex):
|
||||||
return isinstance(ex, exceptions.BadRequest)
|
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 import client as tc
|
||||||
from troveclient.openstack.common.apiclient import exceptions
|
from troveclient.openstack.common.apiclient import exceptions
|
||||||
|
|
||||||
|
from heat.common import exception
|
||||||
from heat.engine.clients import client_plugin
|
from heat.engine.clients import client_plugin
|
||||||
|
|
||||||
|
|
||||||
@ -49,3 +50,25 @@ class TroveClientPlugin(client_plugin.ClientPlugin):
|
|||||||
|
|
||||||
def is_over_limit(self, ex):
|
def is_over_limit(self, ex):
|
||||||
return isinstance(ex, exceptions.RequestEntityTooLarge)
|
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 import resource
|
||||||
from heat.engine.resources.network_interface import NetworkInterface
|
from heat.engine.resources.network_interface import NetworkInterface
|
||||||
from heat.engine.resources.neutron import neutron
|
from heat.engine.resources.neutron import neutron
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.engine.resources import volume
|
from heat.engine.resources import volume
|
||||||
from heat.engine import scheduler
|
from heat.engine import scheduler
|
||||||
from heat.engine import signal_responder
|
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
|
Return the server's IP address, fetching it from Nova if necessary
|
||||||
'''
|
'''
|
||||||
if self.ipaddress is None:
|
if self.ipaddress is None:
|
||||||
self.ipaddress = nova_utils.server_to_ipaddress(
|
self.ipaddress = self.client_plugin().server_to_ipaddress(
|
||||||
self.nova(), self.resource_id)
|
self.resource_id)
|
||||||
|
|
||||||
return self.ipaddress or '0.0.0.0'
|
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)
|
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 = {}
|
scheduler_hints = {}
|
||||||
if self.properties[self.NOVA_SCHEDULER_HINTS]:
|
if self.properties[self.NOVA_SCHEDULER_HINTS]:
|
||||||
@ -587,8 +586,8 @@ class Instance(resource.Resource):
|
|||||||
flavor=flavor_id,
|
flavor=flavor_id,
|
||||||
key_name=self.properties[self.KEY_NAME],
|
key_name=self.properties[self.KEY_NAME],
|
||||||
security_groups=security_groups,
|
security_groups=security_groups,
|
||||||
userdata=nova_utils.build_userdata(self, userdata,
|
userdata=self.client_plugin().build_userdata(
|
||||||
instance_user),
|
self.metadata_get(), userdata, instance_user),
|
||||||
meta=self._get_nova_metadata(self.properties),
|
meta=self._get_nova_metadata(self.properties),
|
||||||
scheduler_hints=scheduler_hints,
|
scheduler_hints=scheduler_hints,
|
||||||
nics=nics,
|
nics=nics,
|
||||||
@ -624,15 +623,16 @@ class Instance(resource.Resource):
|
|||||||
return volume_attach_task.step()
|
return volume_attach_task.step()
|
||||||
|
|
||||||
def _check_active(self, server):
|
def _check_active(self, server):
|
||||||
|
cp = self.client_plugin()
|
||||||
if server.status != 'ACTIVE':
|
if server.status != 'ACTIVE':
|
||||||
nova_utils.refresh_server(server)
|
cp.refresh_server(server)
|
||||||
|
|
||||||
if server.status == 'ACTIVE':
|
if server.status == 'ACTIVE':
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Some clouds append extra (STATUS) strings to the status
|
# Some clouds append extra (STATUS) strings to the status
|
||||||
short_server_status = server.status.split('(')[0]
|
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
|
return False
|
||||||
|
|
||||||
if server.status == 'ERROR':
|
if server.status == 'ERROR':
|
||||||
@ -671,17 +671,16 @@ class Instance(resource.Resource):
|
|||||||
server = None
|
server = None
|
||||||
if self.TAGS in prop_diff:
|
if self.TAGS in prop_diff:
|
||||||
server = self.nova().servers.get(self.resource_id)
|
server = self.nova().servers.get(self.resource_id)
|
||||||
nova_utils.meta_update(self.nova(),
|
self.client_plugin().meta_update(
|
||||||
server,
|
server, self._get_nova_metadata(prop_diff))
|
||||||
self._get_nova_metadata(prop_diff))
|
|
||||||
|
|
||||||
if self.INSTANCE_TYPE in prop_diff:
|
if self.INSTANCE_TYPE in prop_diff:
|
||||||
flavor = prop_diff[self.INSTANCE_TYPE]
|
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:
|
if not server:
|
||||||
server = self.nova().servers.get(self.resource_id)
|
server = self.nova().servers.get(self.resource_id)
|
||||||
checker = scheduler.TaskRunner(nova_utils.resize, server, flavor,
|
checker = scheduler.TaskRunner(self.client_plugin().resize,
|
||||||
flavor_id)
|
server, flavor, flavor_id)
|
||||||
checkers.append(checker)
|
checkers.append(checker)
|
||||||
if self.NETWORK_INTERFACES in prop_diff:
|
if self.NETWORK_INTERFACES in prop_diff:
|
||||||
new_network_ifaces = prop_diff.get(self.NETWORK_INTERFACES)
|
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)
|
server = self.nova().servers.get(self.resource_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.client_plugin().ignore_not_found(e)
|
self.client_plugin().ignore_not_found(e)
|
||||||
self.resource_id_set(None)
|
|
||||||
return
|
return
|
||||||
deleters = (
|
deleters = (
|
||||||
scheduler.TaskRunner(self._detach_volumes_task()),
|
scheduler.TaskRunner(self._detach_volumes_task()),
|
||||||
scheduler.TaskRunner(nova_utils.delete_server, server))
|
scheduler.TaskRunner(self.client_plugin().delete_server,
|
||||||
|
server))
|
||||||
deleters[0].start()
|
deleters[0].start()
|
||||||
return deleters
|
return deleters
|
||||||
|
|
||||||
@ -872,11 +871,12 @@ class Instance(resource.Resource):
|
|||||||
if server.status == 'SUSPENDED':
|
if server.status == 'SUSPENDED':
|
||||||
return True
|
return True
|
||||||
|
|
||||||
nova_utils.refresh_server(server)
|
cp = self.client_plugin()
|
||||||
|
cp.refresh_server(server)
|
||||||
LOG.debug("%(name)s check_suspend_complete "
|
LOG.debug("%(name)s check_suspend_complete "
|
||||||
"status = %(status)s",
|
"status = %(status)s",
|
||||||
{'name': self.name, 'status': server.status})
|
{'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']):
|
['ACTIVE']):
|
||||||
return server.status == 'SUSPENDED'
|
return server.status == 'SUSPENDED'
|
||||||
else:
|
else:
|
||||||
|
@ -19,7 +19,6 @@ from heat.common import template_format
|
|||||||
from heat.engine import attributes
|
from heat.engine import attributes
|
||||||
from heat.engine import constraints
|
from heat.engine import constraints
|
||||||
from heat.engine import properties
|
from heat.engine import properties
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.engine import stack_resource
|
from heat.engine import stack_resource
|
||||||
from heat.openstack.common.gettextutils import _
|
from heat.openstack.common.gettextutils import _
|
||||||
from heat.openstack.common import log as logging
|
from heat.openstack.common import log as logging
|
||||||
@ -422,9 +421,9 @@ class LoadBalancer(stack_resource.StackResource):
|
|||||||
|
|
||||||
servers = []
|
servers = []
|
||||||
n = 1
|
n = 1
|
||||||
client = self.nova()
|
nova_cp = self.client_plugin('nova')
|
||||||
for i in instances:
|
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)
|
LOG.debug('haproxy server:%s' % ip)
|
||||||
servers.append('%sserver server%d %s:%s %s' % (spaces, n,
|
servers.append('%sserver server%d %s:%s %s' % (spaces, n,
|
||||||
ip, inst_port,
|
ip, inst_port,
|
||||||
|
@ -18,7 +18,6 @@ from heat.engine import properties
|
|||||||
from heat.engine import resource
|
from heat.engine import resource
|
||||||
from heat.engine.resources.neutron import neutron
|
from heat.engine.resources.neutron import neutron
|
||||||
from heat.engine.resources.neutron import neutron_utils
|
from heat.engine.resources.neutron import neutron_utils
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.engine import scheduler
|
from heat.engine import scheduler
|
||||||
from heat.engine import support
|
from heat.engine import support
|
||||||
|
|
||||||
@ -647,11 +646,10 @@ class LoadBalancer(resource.Resource):
|
|||||||
def handle_create(self):
|
def handle_create(self):
|
||||||
pool = self.properties[self.POOL_ID]
|
pool = self.properties[self.POOL_ID]
|
||||||
client = self.neutron()
|
client = self.neutron()
|
||||||
nova_client = self.nova()
|
|
||||||
protocol_port = self.properties[self.PROTOCOL_PORT]
|
protocol_port = self.properties[self.PROTOCOL_PORT]
|
||||||
|
|
||||||
for member in self.properties.get(self.MEMBERS):
|
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({
|
lb_member = client.create_member({
|
||||||
'member': {
|
'member': {
|
||||||
'pool_id': pool,
|
'pool_id': pool,
|
||||||
@ -673,10 +671,10 @@ class LoadBalancer(resource.Resource):
|
|||||||
self.client_plugin().ignore_not_found(ex)
|
self.client_plugin().ignore_not_found(ex)
|
||||||
self.data_delete(member)
|
self.data_delete(member)
|
||||||
pool = self.properties[self.POOL_ID]
|
pool = self.properties[self.POOL_ID]
|
||||||
nova_client = self.nova()
|
|
||||||
protocol_port = self.properties[self.PROTOCOL_PORT]
|
protocol_port = self.properties[self.PROTOCOL_PORT]
|
||||||
for member in members - old_members:
|
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({
|
lb_member = client.create_member({
|
||||||
'member': {
|
'member': {
|
||||||
'pool_id': pool,
|
'pool_id': pool,
|
||||||
|
@ -16,7 +16,6 @@ from heat.engine import attributes
|
|||||||
from heat.engine import constraints
|
from heat.engine import constraints
|
||||||
from heat.engine import properties
|
from heat.engine import properties
|
||||||
from heat.engine import resource
|
from heat.engine import resource
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.openstack.common.gettextutils import _
|
from heat.openstack.common.gettextutils import _
|
||||||
|
|
||||||
|
|
||||||
@ -97,8 +96,7 @@ class KeyPair(resource.Resource):
|
|||||||
if self.properties[self.PUBLIC_KEY]:
|
if self.properties[self.PUBLIC_KEY]:
|
||||||
self._public_key = self.properties[self.PUBLIC_KEY]
|
self._public_key = self.properties[self.PUBLIC_KEY]
|
||||||
elif self.resource_id:
|
elif self.resource_id:
|
||||||
nova_key = nova_utils.get_keypair(self.nova(),
|
nova_key = self.client_plugin().get_keypair(self.resource_id)
|
||||||
self.resource_id)
|
|
||||||
self._public_key = nova_key.public_key
|
self._public_key = nova_key.public_key
|
||||||
return self._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
|
# Don't validate empty key, which can happen when you use a KeyPair
|
||||||
# resource
|
# resource
|
||||||
return True
|
return True
|
||||||
nova_client = client.client('nova')
|
client.client_plugin('nova').get_keypair(value)
|
||||||
nova_utils.get_keypair(nova_client, value)
|
|
||||||
|
|
||||||
|
|
||||||
def resource_mapping():
|
def resource_mapping():
|
||||||
|
@ -24,6 +24,7 @@ import string
|
|||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
import six
|
import six
|
||||||
from six.moves.urllib import parse as urlparse
|
from six.moves.urllib import parse as urlparse
|
||||||
|
import warnings
|
||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.engine import scheduler
|
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.
|
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:
|
try:
|
||||||
server.get()
|
server.get()
|
||||||
except nova_exceptions.OverLimit as exc:
|
except nova_exceptions.OverLimit as exc:
|
||||||
@ -72,6 +75,8 @@ def refresh_server(server):
|
|||||||
|
|
||||||
def get_ip(server, net_type, ip_version):
|
def get_ip(server, net_type, ip_version):
|
||||||
"""Return the server's IP of the given type and 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:
|
if net_type in server.addresses:
|
||||||
for ip in server.addresses[net_type]:
|
for ip in server.addresses[net_type]:
|
||||||
if ip['version'] == ip_version:
|
if ip['version'] == ip_version:
|
||||||
@ -79,6 +84,8 @@ def get_ip(server, net_type, ip_version):
|
|||||||
|
|
||||||
|
|
||||||
def get_flavor_id(nova_client, flavor):
|
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.
|
Get the id for the specified flavor name.
|
||||||
If the specified value is flavor id, just return it.
|
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):
|
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:
|
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,
|
def build_userdata(resource, userdata=None, instance_user=None,
|
||||||
user_data_format='HEAT_CFNTOOLS'):
|
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
|
Build multipart data blob for CloudInit which includes user-supplied
|
||||||
Metadata, user data, and the required Heat in-instance configuration.
|
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
|
A co-routine that deletes the server and waits for it to
|
||||||
disappear from Nova.
|
disappear from Nova.
|
||||||
'''
|
'''
|
||||||
|
warnings.warn('nova_utils.delete_server is deprecated. '
|
||||||
|
'Use self.client_plugin("nova").delete_server')
|
||||||
if not server:
|
if not server:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -274,12 +287,16 @@ def delete_server(server):
|
|||||||
@scheduler.wrappertask
|
@scheduler.wrappertask
|
||||||
def resize(server, flavor, flavor_id):
|
def resize(server, flavor, flavor_id):
|
||||||
"""Resize the server and then call check_resize task to verify."""
|
"""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)
|
server.resize(flavor_id)
|
||||||
yield check_resize(server, flavor, flavor_id)
|
yield check_resize(server, flavor, flavor_id)
|
||||||
|
|
||||||
|
|
||||||
def rename(server, name):
|
def rename(server, name):
|
||||||
"""Update the name for a server."""
|
"""Update the name for a server."""
|
||||||
|
warnings.warn('nova_utils.rename is deprecated. '
|
||||||
|
'Use self.client_plugin("nova").rename')
|
||||||
server.update(name)
|
server.update(name)
|
||||||
|
|
||||||
|
|
||||||
@ -288,6 +305,8 @@ def check_resize(server, flavor, flavor_id):
|
|||||||
Verify that a resizing server is properly resized.
|
Verify that a resizing server is properly resized.
|
||||||
If that's the case, confirm the resize, if not raise an error.
|
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)
|
refresh_server(server)
|
||||||
while server.status == 'RESIZE':
|
while server.status == 'RESIZE':
|
||||||
yield
|
yield
|
||||||
@ -303,6 +322,8 @@ def check_resize(server, flavor, flavor_id):
|
|||||||
@scheduler.wrappertask
|
@scheduler.wrappertask
|
||||||
def rebuild(server, image_id, preserve_ephemeral=False):
|
def rebuild(server, image_id, preserve_ephemeral=False):
|
||||||
"""Rebuild the server and call check_rebuild to verify."""
|
"""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)
|
server.rebuild(image_id, preserve_ephemeral=preserve_ephemeral)
|
||||||
yield check_rebuild(server, image_id)
|
yield check_rebuild(server, image_id)
|
||||||
|
|
||||||
@ -312,6 +333,8 @@ def check_rebuild(server, image_id):
|
|||||||
Verify that a rebuilding server is rebuilt.
|
Verify that a rebuilding server is rebuilt.
|
||||||
Raise error if it ends up in an ERROR state.
|
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)
|
refresh_server(server)
|
||||||
while server.status == 'REBUILD':
|
while server.status == 'REBUILD':
|
||||||
yield
|
yield
|
||||||
@ -326,6 +349,8 @@ def meta_serialize(metadata):
|
|||||||
Serialize non-string metadata values before sending them to
|
Serialize non-string metadata values before sending them to
|
||||||
Nova.
|
Nova.
|
||||||
"""
|
"""
|
||||||
|
warnings.warn('nova_utils.meta_serialize is deprecated. '
|
||||||
|
'Use self.client_plugin("nova").meta_serialize')
|
||||||
return dict((key, (value if isinstance(value,
|
return dict((key, (value if isinstance(value,
|
||||||
six.string_types)
|
six.string_types)
|
||||||
else json.dumps(value))
|
else json.dumps(value))
|
||||||
@ -334,6 +359,8 @@ def meta_serialize(metadata):
|
|||||||
|
|
||||||
def meta_update(client, server, metadata):
|
def meta_update(client, server, metadata):
|
||||||
"""Delete/Add the metadata in nova as needed."""
|
"""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)
|
metadata = meta_serialize(metadata)
|
||||||
current_md = server.metadata
|
current_md = server.metadata
|
||||||
to_del = [key for key in current_md.keys() if key not in 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.
|
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:
|
try:
|
||||||
server = client.servers.get(server)
|
server = client.servers.get(server)
|
||||||
except nova_exceptions.NotFound as ex:
|
except nova_exceptions.NotFound as ex:
|
||||||
@ -360,5 +389,7 @@ def server_to_ipaddress(client, server):
|
|||||||
|
|
||||||
def absolute_limits(nova_client):
|
def absolute_limits(nova_client):
|
||||||
"""Return the absolute limits as a dictionary."""
|
"""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()
|
limits = nova_client.limits.get()
|
||||||
return dict([(limit.name, limit.value) for limit in list(limits.absolute)])
|
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 constraints
|
||||||
from heat.engine import properties
|
from heat.engine import properties
|
||||||
from heat.engine import resource
|
from heat.engine import resource
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.openstack.common.gettextutils import _
|
from heat.openstack.common.gettextutils import _
|
||||||
from heat.openstack.common import log as logging
|
from heat.openstack.common import log as logging
|
||||||
|
|
||||||
@ -228,8 +227,8 @@ class OSDBInstance(resource.Resource):
|
|||||||
'''
|
'''
|
||||||
Create cloud database instance.
|
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.properties[self.FLAVOR])
|
||||||
self.volume = {'size': self.properties[self.SIZE]}
|
self.volume = {'size': self.properties[self.SIZE]}
|
||||||
self.databases = self.properties.get(self.DATABASES)
|
self.databases = self.properties.get(self.DATABASES)
|
||||||
self.users = self.properties.get(self.USERS)
|
self.users = self.properties.get(self.USERS)
|
||||||
|
@ -22,7 +22,6 @@ from heat.engine import constraints
|
|||||||
from heat.engine import properties
|
from heat.engine import properties
|
||||||
from heat.engine import resource
|
from heat.engine import resource
|
||||||
from heat.engine.resources.neutron import subnet
|
from heat.engine.resources.neutron import subnet
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.engine import scheduler
|
from heat.engine import scheduler
|
||||||
from heat.engine import stack_user
|
from heat.engine import stack_user
|
||||||
from heat.engine import support
|
from heat.engine import support
|
||||||
@ -471,8 +470,8 @@ class Server(stack_user.StackUser):
|
|||||||
else:
|
else:
|
||||||
instance_user = None
|
instance_user = None
|
||||||
|
|
||||||
userdata = nova_utils.build_userdata(
|
userdata = self.client_plugin().build_userdata(
|
||||||
self,
|
self.metadata_get(),
|
||||||
ud_content,
|
ud_content,
|
||||||
instance_user=instance_user,
|
instance_user=instance_user,
|
||||||
user_data_format=user_data_format)
|
user_data_format=user_data_format)
|
||||||
@ -484,11 +483,12 @@ class Server(stack_user.StackUser):
|
|||||||
if image:
|
if image:
|
||||||
image = self.client_plugin('glance').get_image_id(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)
|
instance_meta = self.properties.get(self.METADATA)
|
||||||
if instance_meta is not None:
|
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)
|
scheduler_hints = self.properties.get(self.SCHEDULER_HINTS)
|
||||||
nics = self._build_nics(self.properties.get(self.NETWORKS))
|
nics = self._build_nics(self.properties.get(self.NETWORKS))
|
||||||
@ -532,12 +532,13 @@ class Server(stack_user.StackUser):
|
|||||||
|
|
||||||
def _check_active(self, server):
|
def _check_active(self, server):
|
||||||
|
|
||||||
|
cp = self.client_plugin()
|
||||||
if server.status != 'ACTIVE':
|
if server.status != 'ACTIVE':
|
||||||
nova_utils.refresh_server(server)
|
cp.refresh_server(server)
|
||||||
|
|
||||||
# Some clouds append extra (STATUS) strings to the status
|
# Some clouds append extra (STATUS) strings to the status
|
||||||
short_server_status = server.status.split('(')[0]
|
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
|
return False
|
||||||
elif server.status == 'ACTIVE':
|
elif server.status == 'ACTIVE':
|
||||||
return True
|
return True
|
||||||
@ -621,8 +622,8 @@ class Server(stack_user.StackUser):
|
|||||||
|
|
||||||
def _resolve_attribute(self, name):
|
def _resolve_attribute(self, name):
|
||||||
if name == self.FIRST_ADDRESS:
|
if name == self.FIRST_ADDRESS:
|
||||||
return nova_utils.server_to_ipaddress(
|
return self.client_plugin().server_to_ipaddress(
|
||||||
self.nova(), self.resource_id) or ''
|
self.resource_id) or ''
|
||||||
try:
|
try:
|
||||||
server = self.nova().servers.get(self.resource_id)
|
server = self.nova().servers.get(self.resource_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -718,9 +719,8 @@ class Server(stack_user.StackUser):
|
|||||||
|
|
||||||
if self.METADATA in prop_diff:
|
if self.METADATA in prop_diff:
|
||||||
server = self.nova().servers.get(self.resource_id)
|
server = self.nova().servers.get(self.resource_id)
|
||||||
nova_utils.meta_update(self.nova(),
|
self.client_plugin().meta_update(server,
|
||||||
server,
|
prop_diff[self.METADATA])
|
||||||
prop_diff[self.METADATA])
|
|
||||||
|
|
||||||
if self.FLAVOR in prop_diff:
|
if self.FLAVOR in prop_diff:
|
||||||
|
|
||||||
@ -732,11 +732,11 @@ class Server(stack_user.StackUser):
|
|||||||
raise resource.UpdateReplace(self.name)
|
raise resource.UpdateReplace(self.name)
|
||||||
|
|
||||||
flavor = prop_diff[self.FLAVOR]
|
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:
|
if not server:
|
||||||
server = self.nova().servers.get(self.resource_id)
|
server = self.nova().servers.get(self.resource_id)
|
||||||
checker = scheduler.TaskRunner(nova_utils.resize, server, flavor,
|
checker = scheduler.TaskRunner(self.client_plugin().resize,
|
||||||
flavor_id)
|
server, flavor, flavor_id)
|
||||||
checkers.append(checker)
|
checkers.append(checker)
|
||||||
|
|
||||||
if self.IMAGE in prop_diff:
|
if self.IMAGE in prop_diff:
|
||||||
@ -752,14 +752,14 @@ class Server(stack_user.StackUser):
|
|||||||
preserve_ephemeral = (
|
preserve_ephemeral = (
|
||||||
image_update_policy == 'REBUILD_PRESERVE_EPHEMERAL')
|
image_update_policy == 'REBUILD_PRESERVE_EPHEMERAL')
|
||||||
checker = scheduler.TaskRunner(
|
checker = scheduler.TaskRunner(
|
||||||
nova_utils.rebuild, server, image_id,
|
self.client_plugin().rebuild, server, image_id,
|
||||||
preserve_ephemeral=preserve_ephemeral)
|
preserve_ephemeral=preserve_ephemeral)
|
||||||
checkers.append(checker)
|
checkers.append(checker)
|
||||||
|
|
||||||
if self.NAME in prop_diff:
|
if self.NAME in prop_diff:
|
||||||
if not server:
|
if not server:
|
||||||
server = self.nova().servers.get(self.resource_id)
|
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:
|
if self.NETWORKS in prop_diff:
|
||||||
new_networks = prop_diff.get(self.NETWORKS)
|
new_networks = prop_diff.get(self.NETWORKS)
|
||||||
@ -928,7 +928,7 @@ class Server(stack_user.StackUser):
|
|||||||
metadata = self.properties.get(self.METADATA)
|
metadata = self.properties.get(self.METADATA)
|
||||||
personality = self.properties.get(self.PERSONALITY)
|
personality = self.properties.get(self.PERSONALITY)
|
||||||
if metadata is not None or 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'
|
# if 'security_groups' present for the server and explict 'port'
|
||||||
# in one or more entries in 'networks', raise validation error
|
# in one or more entries in 'networks', raise validation error
|
||||||
@ -977,7 +977,8 @@ class Server(stack_user.StackUser):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.client_plugin().ignore_not_found(e)
|
self.client_plugin().ignore_not_found(e)
|
||||||
else:
|
else:
|
||||||
deleter = scheduler.TaskRunner(nova_utils.delete_server, server)
|
deleter = scheduler.TaskRunner(self.client_plugin().delete_server,
|
||||||
|
server)
|
||||||
deleter.start()
|
deleter.start()
|
||||||
return deleter
|
return deleter
|
||||||
|
|
||||||
@ -1022,10 +1023,11 @@ class Server(stack_user.StackUser):
|
|||||||
if server.status == 'SUSPENDED':
|
if server.status == 'SUSPENDED':
|
||||||
return True
|
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'
|
LOG.debug('%(name)s check_suspend_complete status = %(status)s'
|
||||||
% {'name': self.name, 'status': server.status})
|
% {'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']):
|
['ACTIVE']):
|
||||||
return server.status == 'SUSPENDED'
|
return server.status == 'SUSPENDED'
|
||||||
else:
|
else:
|
||||||
@ -1067,8 +1069,7 @@ class FlavorConstraint(constraints.BaseCustomConstraint):
|
|||||||
expected_exceptions = (exception.FlavorMissing,)
|
expected_exceptions = (exception.FlavorMissing,)
|
||||||
|
|
||||||
def validate_with_client(self, client, value):
|
def validate_with_client(self, client, value):
|
||||||
nova_client = client.client('nova')
|
client.client_plugin('nova').get_flavor_id(value)
|
||||||
nova_utils.get_flavor_id(nova_client, value)
|
|
||||||
|
|
||||||
|
|
||||||
def resource_mapping():
|
def resource_mapping():
|
||||||
|
@ -40,7 +40,6 @@ from heat.engine import parser
|
|||||||
from heat.engine.properties import Properties
|
from heat.engine.properties import Properties
|
||||||
from heat.engine import resource as res
|
from heat.engine import resource as res
|
||||||
from heat.engine.resources import instance as instances
|
from heat.engine.resources import instance as instances
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.engine import service
|
from heat.engine import service
|
||||||
from heat.engine import stack_lock
|
from heat.engine import stack_lock
|
||||||
from heat.engine import watchrule
|
from heat.engine import watchrule
|
||||||
@ -209,6 +208,7 @@ def setup_mocks(mocks, stack, mock_image_constraint=True):
|
|||||||
mocks.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
mocks.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||||
nova.NovaClientPlugin._create().AndReturn(fc)
|
nova.NovaClientPlugin._create().AndReturn(fc)
|
||||||
instance = stack['WebServer']
|
instance = stack['WebServer']
|
||||||
|
metadata = instance.metadata_get()
|
||||||
if mock_image_constraint:
|
if mock_image_constraint:
|
||||||
setup_mock_for_image_constraint(mocks,
|
setup_mock_for_image_constraint(mocks,
|
||||||
instance.t['Properties']['ImageId'])
|
instance.t['Properties']['ImageId'])
|
||||||
@ -216,11 +216,11 @@ def setup_mocks(mocks, stack, mock_image_constraint=True):
|
|||||||
setup_keystone_mocks(mocks, stack)
|
setup_keystone_mocks(mocks, stack)
|
||||||
|
|
||||||
user_data = instance.properties['UserData']
|
user_data = instance.properties['UserData']
|
||||||
server_userdata = nova_utils.build_userdata(instance, user_data,
|
server_userdata = instance.client_plugin().build_userdata(
|
||||||
'ec2-user')
|
metadata, user_data, 'ec2-user')
|
||||||
mocks.StubOutWithMock(nova_utils, 'build_userdata')
|
mocks.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||||
nova_utils.build_userdata(
|
nova.NovaClientPlugin.build_userdata(
|
||||||
instance,
|
metadata,
|
||||||
instance.t['Properties']['UserData'],
|
instance.t['Properties']['UserData'],
|
||||||
'ec2-user').AndReturn(server_userdata)
|
'ec2-user').AndReturn(server_userdata)
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ from heat.engine import parser
|
|||||||
from heat.engine import resource
|
from heat.engine import resource
|
||||||
from heat.engine.resources import instance as instances
|
from heat.engine.resources import instance as instances
|
||||||
from heat.engine.resources import network_interface
|
from heat.engine.resources import network_interface
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.engine import scheduler
|
from heat.engine import scheduler
|
||||||
from heat.tests.common import HeatTestCase
|
from heat.tests.common import HeatTestCase
|
||||||
from heat.tests import utils
|
from heat.tests import utils
|
||||||
@ -1336,8 +1335,10 @@ class InstancesTest(HeatTestCase):
|
|||||||
"""The default value for instance_user in heat.conf is ec2-user."""
|
"""The default value for instance_user in heat.conf is ec2-user."""
|
||||||
return_server = self.fc.servers.list()[1]
|
return_server = self.fc.servers.list()[1]
|
||||||
instance = self._setup_test_instance(return_server, 'default_user')
|
instance = self._setup_test_instance(return_server, 'default_user')
|
||||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
metadata = instance.metadata_get()
|
||||||
nova_utils.build_userdata(instance, 'wordpress', 'ec2-user')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||||
|
nova.NovaClientPlugin.build_userdata(
|
||||||
|
metadata, 'wordpress', 'ec2-user')
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
scheduler.TaskRunner(instance.create)()
|
scheduler.TaskRunner(instance.create)()
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
@ -1354,8 +1355,10 @@ class InstancesTest(HeatTestCase):
|
|||||||
instance = self._setup_test_instance(return_server, 'custom_user')
|
instance = self._setup_test_instance(return_server, 'custom_user')
|
||||||
self.m.StubOutWithMock(instances.cfg.CONF, 'instance_user')
|
self.m.StubOutWithMock(instances.cfg.CONF, 'instance_user')
|
||||||
instances.cfg.CONF.instance_user = 'custom_user'
|
instances.cfg.CONF.instance_user = 'custom_user'
|
||||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
metadata = instance.metadata_get()
|
||||||
nova_utils.build_userdata(instance, 'wordpress', 'custom_user')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||||
|
nova.NovaClientPlugin.build_userdata(
|
||||||
|
metadata, 'wordpress', 'custom_user')
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
scheduler.TaskRunner(instance.create)()
|
scheduler.TaskRunner(instance.create)()
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
@ -1373,8 +1376,10 @@ class InstancesTest(HeatTestCase):
|
|||||||
instance = self._setup_test_instance(return_server, 'empty_user')
|
instance = self._setup_test_instance(return_server, 'empty_user')
|
||||||
self.m.StubOutWithMock(instances.cfg.CONF, 'instance_user')
|
self.m.StubOutWithMock(instances.cfg.CONF, 'instance_user')
|
||||||
instances.cfg.CONF.instance_user = ''
|
instances.cfg.CONF.instance_user = ''
|
||||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
metadata = instance.metadata_get()
|
||||||
nova_utils.build_userdata(instance, 'wordpress', 'ec2-user')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||||
|
nova.NovaClientPlugin.build_userdata(
|
||||||
|
metadata, 'wordpress', 'ec2-user')
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
scheduler.TaskRunner(instance.create)()
|
scheduler.TaskRunner(instance.create)()
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
@ -20,7 +20,6 @@ from heat.engine import environment
|
|||||||
from heat.engine import parser
|
from heat.engine import parser
|
||||||
from heat.engine.resources import instance as instances
|
from heat.engine.resources import instance as instances
|
||||||
from heat.engine.resources import network_interface as network_interfaces
|
from heat.engine.resources import network_interface as network_interfaces
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.engine import scheduler
|
from heat.engine import scheduler
|
||||||
from heat.tests.common import HeatTestCase
|
from heat.tests.common import HeatTestCase
|
||||||
from heat.tests import utils
|
from heat.tests import utils
|
||||||
@ -170,6 +169,7 @@ class instancesTest(HeatTestCase):
|
|||||||
resource_defns = stack.t.resource_definitions(stack)
|
resource_defns = stack.t.resource_definitions(stack)
|
||||||
instance = instances.Instance('%s_name' % name,
|
instance = instances.Instance('%s_name' % name,
|
||||||
resource_defns['WebServer'], stack)
|
resource_defns['WebServer'], stack)
|
||||||
|
metadata = instance.metadata_get()
|
||||||
|
|
||||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||||
@ -180,13 +180,13 @@ class instancesTest(HeatTestCase):
|
|||||||
instance.neutron().MultipleTimes().AndReturn(FakeNeutron())
|
instance.neutron().MultipleTimes().AndReturn(FakeNeutron())
|
||||||
|
|
||||||
# need to resolve the template functions
|
# need to resolve the template functions
|
||||||
server_userdata = nova_utils.build_userdata(
|
server_userdata = instance.client_plugin().build_userdata(
|
||||||
instance,
|
metadata,
|
||||||
instance.t['Properties']['UserData'],
|
instance.t['Properties']['UserData'],
|
||||||
'ec2-user')
|
'ec2-user')
|
||||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||||
nova_utils.build_userdata(
|
nova.NovaClientPlugin.build_userdata(
|
||||||
instance,
|
metadata,
|
||||||
instance.t['Properties']['UserData'],
|
instance.t['Properties']['UserData'],
|
||||||
'ec2-user').AndReturn(server_userdata)
|
'ec2-user').AndReturn(server_userdata)
|
||||||
|
|
||||||
@ -225,6 +225,7 @@ class instancesTest(HeatTestCase):
|
|||||||
|
|
||||||
instance = instances.Instance('%s_name' % name,
|
instance = instances.Instance('%s_name' % name,
|
||||||
resource_defns['WebServer'], stack)
|
resource_defns['WebServer'], stack)
|
||||||
|
metadata = instance.metadata_get()
|
||||||
|
|
||||||
self._mock_get_image_id_success(image_id, 1)
|
self._mock_get_image_id_success(image_id, 1)
|
||||||
self.m.StubOutWithMock(nic, 'neutron')
|
self.m.StubOutWithMock(nic, 'neutron')
|
||||||
@ -234,13 +235,13 @@ class instancesTest(HeatTestCase):
|
|||||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||||
|
|
||||||
# need to resolve the template functions
|
# need to resolve the template functions
|
||||||
server_userdata = nova_utils.build_userdata(
|
server_userdata = instance.client_plugin().build_userdata(
|
||||||
instance,
|
metadata,
|
||||||
instance.t['Properties']['UserData'],
|
instance.t['Properties']['UserData'],
|
||||||
'ec2-user')
|
'ec2-user')
|
||||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||||
nova_utils.build_userdata(
|
nova.NovaClientPlugin.build_userdata(
|
||||||
instance,
|
metadata,
|
||||||
instance.t['Properties']['UserData'],
|
instance.t['Properties']['UserData'],
|
||||||
'ec2-user').AndReturn(server_userdata)
|
'ec2-user').AndReturn(server_userdata)
|
||||||
|
|
||||||
|
@ -20,10 +20,11 @@ from oslo.config import cfg
|
|||||||
|
|
||||||
from heat.common import template_format
|
from heat.common import template_format
|
||||||
from heat.db import api as db_api
|
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 environment
|
||||||
from heat.engine import parser
|
from heat.engine import parser
|
||||||
from heat.engine.resources import instance
|
from heat.engine.resources import instance
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.engine import template
|
from heat.engine import template
|
||||||
from heat.tests.common import HeatTestCase
|
from heat.tests.common import HeatTestCase
|
||||||
from heat.tests import utils
|
from heat.tests import utils
|
||||||
@ -123,11 +124,12 @@ class AutoScalingTest(HeatTestCase):
|
|||||||
self.m.StubOutWithMock(neutronclient.Client, 'create_member')
|
self.m.StubOutWithMock(neutronclient.Client, 'create_member')
|
||||||
self.m.StubOutWithMock(neutronclient.Client, 'list_members')
|
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(parser.Stack, 'validate')
|
||||||
|
|
||||||
self.m.StubOutWithMock(instance.Instance, 'handle_create')
|
self.m.StubOutWithMock(instance.Instance, 'handle_create')
|
||||||
self.m.StubOutWithMock(instance.Instance, 'check_create_complete')
|
self.m.StubOutWithMock(instance.Instance, 'check_create_complete')
|
||||||
|
self.m.StubOutWithMock(glance.ImageConstraint, "validate")
|
||||||
|
|
||||||
def test_lb(self):
|
def test_lb(self):
|
||||||
|
|
||||||
@ -276,10 +278,10 @@ class AutoScalingTest(HeatTestCase):
|
|||||||
instance.Instance.check_create_complete(mox.IgnoreArg())\
|
instance.Instance.check_create_complete(mox.IgnoreArg())\
|
||||||
.AndReturn(True)
|
.AndReturn(True)
|
||||||
|
|
||||||
self.stub_ImageConstraint_validate()
|
glance.ImageConstraint.validate(
|
||||||
|
mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(True)
|
||||||
|
|
||||||
nova_utils.server_to_ipaddress(
|
nova.NovaClientPlugin.server_to_ipaddress(
|
||||||
mox.IgnoreArg(),
|
|
||||||
mox.IgnoreArg()).AndReturn('1.2.3.4')
|
mox.IgnoreArg()).AndReturn('1.2.3.4')
|
||||||
|
|
||||||
neutronclient.Client.create_member(membera_block).\
|
neutronclient.Client.create_member(membera_block).\
|
||||||
@ -304,15 +306,13 @@ class AutoScalingTest(HeatTestCase):
|
|||||||
instance.Instance.check_create_complete(mox.IgnoreArg())\
|
instance.Instance.check_create_complete(mox.IgnoreArg())\
|
||||||
.AndReturn(True)
|
.AndReturn(True)
|
||||||
|
|
||||||
nova_utils.server_to_ipaddress(
|
nova.NovaClientPlugin.server_to_ipaddress(
|
||||||
mox.IgnoreArg(),
|
|
||||||
mox.IgnoreArg()).AndReturn('1.2.3.5')
|
mox.IgnoreArg()).AndReturn('1.2.3.5')
|
||||||
|
|
||||||
neutronclient.Client.create_member(memberb_block).\
|
neutronclient.Client.create_member(memberb_block).\
|
||||||
AndReturn(memberb_ret_block)
|
AndReturn(memberb_ret_block)
|
||||||
|
|
||||||
nova_utils.server_to_ipaddress(
|
nova.NovaClientPlugin.server_to_ipaddress(
|
||||||
mox.IgnoreArg(),
|
|
||||||
mox.IgnoreArg()).AndReturn('1.2.3.6')
|
mox.IgnoreArg()).AndReturn('1.2.3.6')
|
||||||
|
|
||||||
neutronclient.Client.create_member(memberc_block).\
|
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 glance
|
||||||
from heat.engine.clients.os import nova
|
from heat.engine.clients.os import nova
|
||||||
from heat.engine.resources import instance as instances
|
from heat.engine.resources import instance as instances
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.engine import scheduler
|
from heat.engine import scheduler
|
||||||
from heat.tests.common import HeatTestCase
|
from heat.tests.common import HeatTestCase
|
||||||
from heat.tests import utils
|
from heat.tests import utils
|
||||||
@ -66,13 +65,14 @@ class nokeyTest(HeatTestCase):
|
|||||||
'CentOS 5.2').MultipleTimes().AndReturn(1)
|
'CentOS 5.2').MultipleTimes().AndReturn(1)
|
||||||
|
|
||||||
# need to resolve the template functions
|
# need to resolve the template functions
|
||||||
server_userdata = nova_utils.build_userdata(
|
metadata = instance.metadata_get()
|
||||||
instance,
|
server_userdata = instance.client_plugin().build_userdata(
|
||||||
|
metadata,
|
||||||
instance.t['Properties']['UserData'],
|
instance.t['Properties']['UserData'],
|
||||||
'ec2-user')
|
'ec2-user')
|
||||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||||
nova_utils.build_userdata(
|
nova.NovaClientPlugin.build_userdata(
|
||||||
instance,
|
metadata,
|
||||||
instance.t['Properties']['UserData'],
|
instance.t['Properties']['UserData'],
|
||||||
'ec2-user').AndReturn(server_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):
|
def setUp(self):
|
||||||
super(NovaUtilsTests, self).setUp()
|
super(NovaUtilsTests, self).setUp()
|
||||||
self.nova_client = self.m.CreateMockAnything()
|
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):
|
def test_get_ip(self):
|
||||||
my_image = self.m.CreateMockAnything()
|
my_image = self.m.CreateMockAnything()
|
||||||
@ -126,6 +130,13 @@ class NovaUtilsTests(HeatTestCase):
|
|||||||
|
|
||||||
class NovaUtilsRefreshServerTests(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):
|
def test_successful_refresh(self):
|
||||||
server = self.m.CreateMockAnything()
|
server = self.m.CreateMockAnything()
|
||||||
server.get().AndReturn(None)
|
server.get().AndReturn(None)
|
||||||
@ -170,6 +181,10 @@ class NovaUtilsUserdataTests(HeatTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(NovaUtilsUserdataTests, self).setUp()
|
super(NovaUtilsUserdataTests, self).setUp()
|
||||||
self.nova_client = self.m.CreateMockAnything()
|
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):
|
def test_build_userdata(self):
|
||||||
"""Tests the build_userdata function."""
|
"""Tests the build_userdata function."""
|
||||||
@ -228,6 +243,13 @@ class NovaUtilsUserdataTests(HeatTestCase):
|
|||||||
|
|
||||||
class NovaUtilsMetadataTests(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):
|
def test_serialize_string(self):
|
||||||
original = {'test_key': 'simple string value'}
|
original = {'test_key': 'simple string value'}
|
||||||
self.assertEqual(original, nova_utils.meta_serialize(original))
|
self.assertEqual(original, nova_utils.meta_serialize(original))
|
||||||
|
@ -18,6 +18,7 @@ import six
|
|||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.common import template_format
|
from heat.common import template_format
|
||||||
|
from heat.engine.clients.os import trove
|
||||||
from heat.engine import parser
|
from heat.engine import parser
|
||||||
from heat.engine.resources import os_database
|
from heat.engine.resources import os_database
|
||||||
from heat.engine import scheduler
|
from heat.engine import scheduler
|
||||||
@ -97,12 +98,10 @@ class OSDBInstanceTest(HeatTestCase):
|
|||||||
return instance
|
return instance
|
||||||
|
|
||||||
def _stubout_create(self, instance, fake_dbinstance):
|
def _stubout_create(self, instance, fake_dbinstance):
|
||||||
self.m.StubOutWithMock(instance, 'trove')
|
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||||
self.m.StubOutWithMock(self.fc, 'flavors')
|
self.m.StubOutWithMock(trove.TroveClientPlugin, 'get_flavor_id')
|
||||||
self.m.StubOutWithMock(self.fc.flavors, "list")
|
trove.TroveClientPlugin.get_flavor_id('1GB').AndReturn(1)
|
||||||
self.fc.flavors.list().AndReturn([FakeFlavor(1, '1GB'),
|
|
||||||
FakeFlavor(2, '2GB')])
|
|
||||||
self.m.StubOutWithMock(self.fc, 'instances')
|
self.m.StubOutWithMock(self.fc, 'instances')
|
||||||
self.m.StubOutWithMock(self.fc.instances, 'create')
|
self.m.StubOutWithMock(self.fc.instances, 'create')
|
||||||
users = [{"name": "testuser", "password": "pass", "host": "%",
|
users = [{"name": "testuser", "password": "pass", "host": "%",
|
||||||
@ -121,8 +120,8 @@ class OSDBInstanceTest(HeatTestCase):
|
|||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
|
|
||||||
def _stubout_validate(self, instance):
|
def _stubout_validate(self, instance):
|
||||||
self.m.StubOutWithMock(instance, 'trove')
|
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||||
self.m.StubOutWithMock(self.fc, 'datastore_versions')
|
self.m.StubOutWithMock(self.fc, 'datastore_versions')
|
||||||
self.m.StubOutWithMock(self.fc.datastore_versions, 'list')
|
self.m.StubOutWithMock(self.fc.datastore_versions, 'list')
|
||||||
self.fc.datastore_versions.list(instance.properties['datastore_type']
|
self.fc.datastore_versions.list(instance.properties['datastore_type']
|
||||||
@ -144,8 +143,8 @@ class OSDBInstanceTest(HeatTestCase):
|
|||||||
t['Resources']['MySqlCloudDB']['Properties']['restore_point'] = "1234"
|
t['Resources']['MySqlCloudDB']['Properties']['restore_point'] = "1234"
|
||||||
instance = self._setup_test_clouddbinstance('dbinstance_create', t)
|
instance = self._setup_test_clouddbinstance('dbinstance_create', t)
|
||||||
|
|
||||||
self.m.StubOutWithMock(instance, 'trove')
|
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||||
self.m.StubOutWithMock(self.fc, 'flavors')
|
self.m.StubOutWithMock(self.fc, 'flavors')
|
||||||
self.m.StubOutWithMock(self.fc.flavors, "list")
|
self.m.StubOutWithMock(self.fc.flavors, "list")
|
||||||
self.fc.flavors.list().AndReturn([FakeFlavor(1, '1GB'),
|
self.fc.flavors.list().AndReturn([FakeFlavor(1, '1GB'),
|
||||||
@ -281,8 +280,8 @@ class OSDBInstanceTest(HeatTestCase):
|
|||||||
t = template_format.parse(db_template)
|
t = template_format.parse(db_template)
|
||||||
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
|
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
|
||||||
instance.resource_id = 12345
|
instance.resource_id = 12345
|
||||||
self.m.StubOutWithMock(instance, 'trove')
|
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||||
self.m.StubOutWithMock(self.fc, 'instances')
|
self.m.StubOutWithMock(self.fc, 'instances')
|
||||||
self.m.StubOutWithMock(self.fc.instances, 'get')
|
self.m.StubOutWithMock(self.fc.instances, 'get')
|
||||||
self.fc.instances.get(12345).AndReturn(fake_dbinstance)
|
self.fc.instances.get(12345).AndReturn(fake_dbinstance)
|
||||||
@ -296,8 +295,8 @@ class OSDBInstanceTest(HeatTestCase):
|
|||||||
t = template_format.parse(db_template)
|
t = template_format.parse(db_template)
|
||||||
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
|
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
|
||||||
instance.resource_id = 12345
|
instance.resource_id = 12345
|
||||||
self.m.StubOutWithMock(instance, 'trove')
|
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||||
self.m.StubOutWithMock(self.fc, 'instances')
|
self.m.StubOutWithMock(self.fc, 'instances')
|
||||||
self.m.StubOutWithMock(self.fc.instances, 'get')
|
self.m.StubOutWithMock(self.fc.instances, 'get')
|
||||||
self.fc.instances.get(12345).AndReturn(fake_dbinstance)
|
self.fc.instances.get(12345).AndReturn(fake_dbinstance)
|
||||||
@ -312,8 +311,8 @@ class OSDBInstanceTest(HeatTestCase):
|
|||||||
t = template_format.parse(db_template)
|
t = template_format.parse(db_template)
|
||||||
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
|
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
|
||||||
instance.resource_id = 12345
|
instance.resource_id = 12345
|
||||||
self.m.StubOutWithMock(instance, 'trove')
|
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||||
self.m.StubOutWithMock(self.fc, 'instances')
|
self.m.StubOutWithMock(self.fc, 'instances')
|
||||||
self.m.StubOutWithMock(self.fc.instances, 'get')
|
self.m.StubOutWithMock(self.fc.instances, 'get')
|
||||||
self.fc.instances.get(12345).AndReturn(fake_dbinstance)
|
self.fc.instances.get(12345).AndReturn(fake_dbinstance)
|
||||||
@ -419,8 +418,8 @@ class OSDBInstanceTest(HeatTestCase):
|
|||||||
'datastore_type'] = 'mysql'
|
'datastore_type'] = 'mysql'
|
||||||
t['Resources']['MySqlCloudDB']['Properties'].pop('datastore_version')
|
t['Resources']['MySqlCloudDB']['Properties'].pop('datastore_version')
|
||||||
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
|
instance = self._setup_test_clouddbinstance('dbinstance_test', t)
|
||||||
self.m.StubOutWithMock(instance, 'trove')
|
self.m.StubOutWithMock(trove.TroveClientPlugin, '_create')
|
||||||
instance.trove().MultipleTimes().AndReturn(self.fc)
|
trove.TroveClientPlugin._create().AndReturn(self.fc)
|
||||||
self.m.StubOutWithMock(self.fc, 'datastore_versions')
|
self.m.StubOutWithMock(self.fc, 'datastore_versions')
|
||||||
self.m.StubOutWithMock(self.fc.datastore_versions, 'list')
|
self.m.StubOutWithMock(self.fc.datastore_versions, 'list')
|
||||||
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 environment
|
||||||
from heat.engine import parser
|
from heat.engine import parser
|
||||||
from heat.engine import resource
|
from heat.engine import resource
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.engine.resources import server as servers
|
from heat.engine.resources import server as servers
|
||||||
from heat.engine import scheduler
|
from heat.engine import scheduler
|
||||||
from heat.openstack.common.gettextutils import _
|
from heat.openstack.common.gettextutils import _
|
||||||
@ -175,12 +174,8 @@ class ServersTest(HeatTestCase):
|
|||||||
glance.GlanceClientPlugin.get_image_id(image_id).AndRaise(exp)
|
glance.GlanceClientPlugin.get_image_id(image_id).AndRaise(exp)
|
||||||
|
|
||||||
def _mock_get_keypair_success(self, keypair_input, keypair):
|
def _mock_get_keypair_success(self, keypair_input, keypair):
|
||||||
n_cli_mock = self.m.CreateMockAnything()
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'get_keypair')
|
||||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
nova.NovaClientPlugin.get_keypair(keypair_input).MultipleTimes().\
|
||||||
nova.NovaClientPlugin._create().AndReturn(
|
|
||||||
n_cli_mock)
|
|
||||||
self.m.StubOutWithMock(nova_utils, 'get_keypair')
|
|
||||||
nova_utils.get_keypair(n_cli_mock, keypair_input).MultipleTimes().\
|
|
||||||
AndReturn(keypair)
|
AndReturn(keypair)
|
||||||
|
|
||||||
def _server_validate_mock(self, server):
|
def _server_validate_mock(self, server):
|
||||||
@ -763,8 +758,11 @@ class ServersTest(HeatTestCase):
|
|||||||
web_server = tmpl.t['Resources']['WebServer']
|
web_server = tmpl.t['Resources']['WebServer']
|
||||||
del web_server['Properties']['image']
|
del web_server['Properties']['image']
|
||||||
|
|
||||||
def create_server(device_name, mock_create=True):
|
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||||
self.m.UnsetStubs()
|
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||||
|
self.m.ReplayAll()
|
||||||
|
|
||||||
|
def create_server(device_name):
|
||||||
web_server['Properties']['block_device_mapping'] = [{
|
web_server['Properties']['block_device_mapping'] = [{
|
||||||
"device_name": device_name,
|
"device_name": device_name,
|
||||||
"volume_id": "5d7e27da-6703-4f7e-9f94-1f67abef734c",
|
"volume_id": "5d7e27da-6703-4f7e-9f94-1f67abef734c",
|
||||||
@ -773,17 +771,13 @@ class ServersTest(HeatTestCase):
|
|||||||
resource_defns = tmpl.resource_definitions(stack)
|
resource_defns = tmpl.resource_definitions(stack)
|
||||||
server = servers.Server('server_with_bootable_volume',
|
server = servers.Server('server_with_bootable_volume',
|
||||||
resource_defns['WebServer'], stack)
|
resource_defns['WebServer'], stack)
|
||||||
if mock_create:
|
|
||||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
|
||||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
|
||||||
self.m.ReplayAll()
|
|
||||||
return server
|
return server
|
||||||
|
|
||||||
server = create_server(u'vda')
|
server = create_server(u'vda')
|
||||||
self.assertIsNone(server.validate())
|
self.assertIsNone(server.validate())
|
||||||
server = create_server('vda', mock_create=False)
|
server = create_server('vda')
|
||||||
self.assertIsNone(server.validate())
|
self.assertIsNone(server.validate())
|
||||||
server = create_server('vdb', mock_create=False)
|
server = create_server('vdb')
|
||||||
ex = self.assertRaises(exception.StackValidationFailed,
|
ex = self.assertRaises(exception.StackValidationFailed,
|
||||||
server.validate)
|
server.validate)
|
||||||
self.assertEqual('Neither image nor bootable volume is specified for '
|
self.assertEqual('Neither image nor bootable volume is specified for '
|
||||||
@ -825,7 +819,9 @@ class ServersTest(HeatTestCase):
|
|||||||
server = servers.Server('server_validate_test',
|
server = servers.Server('server_validate_test',
|
||||||
resource_defns['WebServer'], stack)
|
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.m.ReplayAll()
|
||||||
|
|
||||||
self.assertIsNone(server.validate())
|
self.assertIsNone(server.validate())
|
||||||
@ -1015,7 +1011,7 @@ class ServersTest(HeatTestCase):
|
|||||||
new_meta = {'test': 123}
|
new_meta = {'test': 123}
|
||||||
self.m.StubOutWithMock(self.fc.servers, 'set_meta')
|
self.m.StubOutWithMock(self.fc.servers, 'set_meta')
|
||||||
self.fc.servers.set_meta(return_server,
|
self.fc.servers.set_meta(return_server,
|
||||||
nova_utils.meta_serialize(
|
server.client_plugin().meta_serialize(
|
||||||
new_meta)).AndReturn(None)
|
new_meta)).AndReturn(None)
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
update_template = copy.deepcopy(server.t)
|
update_template = copy.deepcopy(server.t)
|
||||||
@ -1040,7 +1036,7 @@ class ServersTest(HeatTestCase):
|
|||||||
# If we're going to call set_meta() directly we
|
# If we're going to call set_meta() directly we
|
||||||
# need to handle the serialization ourselves.
|
# need to handle the serialization ourselves.
|
||||||
self.fc.servers.set_meta(return_server,
|
self.fc.servers.set_meta(return_server,
|
||||||
nova_utils.meta_serialize(
|
server.client_plugin().meta_serialize(
|
||||||
new_meta)).AndReturn(None)
|
new_meta)).AndReturn(None)
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
update_template = copy.deepcopy(server.t)
|
update_template = copy.deepcopy(server.t)
|
||||||
@ -1229,7 +1225,9 @@ class ServersTest(HeatTestCase):
|
|||||||
image_id = self.getUniqueString()
|
image_id = self.getUniqueString()
|
||||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
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()
|
self.m.ReplayAll()
|
||||||
|
|
||||||
update_template = copy.deepcopy(server.t)
|
update_template = copy.deepcopy(server.t)
|
||||||
@ -1237,8 +1235,6 @@ class ServersTest(HeatTestCase):
|
|||||||
updater = scheduler.TaskRunner(server.update, update_template)
|
updater = scheduler.TaskRunner(server.update, update_template)
|
||||||
self.assertRaises(resource.UpdateReplace, updater)
|
self.assertRaises(resource.UpdateReplace, updater)
|
||||||
|
|
||||||
self.m.VerifyAll()
|
|
||||||
|
|
||||||
def _test_server_update_image_rebuild(self, status, policy='REBUILD'):
|
def _test_server_update_image_rebuild(self, status, policy='REBUILD'):
|
||||||
# Server.handle_update supports changing the image, and makes
|
# Server.handle_update supports changing the image, and makes
|
||||||
# the change making a rebuild API call against Nova.
|
# the change making a rebuild API call against Nova.
|
||||||
@ -1339,7 +1335,9 @@ class ServersTest(HeatTestCase):
|
|||||||
server = self._create_test_server(return_server,
|
server = self._create_test_server(return_server,
|
||||||
'update_prop')
|
'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()
|
self.m.ReplayAll()
|
||||||
|
|
||||||
update_template = copy.deepcopy(server.t)
|
update_template = copy.deepcopy(server.t)
|
||||||
@ -1347,8 +1345,6 @@ class ServersTest(HeatTestCase):
|
|||||||
updater = scheduler.TaskRunner(server.update, update_template)
|
updater = scheduler.TaskRunner(server.update, update_template)
|
||||||
self.assertRaises(resource.UpdateReplace, updater)
|
self.assertRaises(resource.UpdateReplace, updater)
|
||||||
|
|
||||||
self.m.VerifyAll()
|
|
||||||
|
|
||||||
def test_server_status_build(self):
|
def test_server_status_build(self):
|
||||||
return_server = self.fc.servers.list()[0]
|
return_server = self.fc.servers.list()[0]
|
||||||
server = self._setup_test_server(return_server,
|
server = self._setup_test_server(return_server,
|
||||||
@ -1857,8 +1853,6 @@ class ServersTest(HeatTestCase):
|
|||||||
self.m.StubOutWithMock(self.fc.limits, 'get')
|
self.m.StubOutWithMock(self.fc.limits, 'get')
|
||||||
self.fc.limits.get().MultipleTimes().AndReturn(self.limits)
|
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')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||||
self._mock_get_image_id_success('F17-x86_64-gold', 'image_id')
|
self._mock_get_image_id_success('F17-x86_64-gold', 'image_id')
|
||||||
@ -1985,11 +1979,13 @@ class ServersTest(HeatTestCase):
|
|||||||
"""The default value for instance_user in heat.conf is ec2-user."""
|
"""The default value for instance_user in heat.conf is ec2-user."""
|
||||||
return_server = self.fc.servers.list()[1]
|
return_server = self.fc.servers.list()[1]
|
||||||
server = self._setup_test_server(return_server, 'default_user')
|
server = self._setup_test_server(return_server, 'default_user')
|
||||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
metadata = server.metadata_get()
|
||||||
nova_utils.build_userdata(server,
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||||
'wordpress',
|
nova.NovaClientPlugin.build_userdata(
|
||||||
instance_user='ec2-user',
|
metadata,
|
||||||
user_data_format='HEAT_CFNTOOLS')
|
'wordpress',
|
||||||
|
instance_user='ec2-user',
|
||||||
|
user_data_format='HEAT_CFNTOOLS')
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
scheduler.TaskRunner(server.create)()
|
scheduler.TaskRunner(server.create)()
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
@ -2023,11 +2019,13 @@ class ServersTest(HeatTestCase):
|
|||||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||||
self._mock_get_image_id_success('F17-x86_64-gold', image_id)
|
self._mock_get_image_id_success('F17-x86_64-gold', image_id)
|
||||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
metadata = server.metadata_get()
|
||||||
nova_utils.build_userdata(server,
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||||
'wordpress',
|
nova.NovaClientPlugin.build_userdata(
|
||||||
instance_user='custom_user',
|
metadata,
|
||||||
user_data_format='HEAT_CFNTOOLS')
|
'wordpress',
|
||||||
|
instance_user='custom_user',
|
||||||
|
user_data_format='HEAT_CFNTOOLS')
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
scheduler.TaskRunner(server.create)()
|
scheduler.TaskRunner(server.create)()
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
@ -2044,11 +2042,13 @@ class ServersTest(HeatTestCase):
|
|||||||
server = self._setup_test_server(return_server, 'custom_user')
|
server = self._setup_test_server(return_server, 'custom_user')
|
||||||
self.m.StubOutWithMock(servers.cfg.CONF, 'instance_user')
|
self.m.StubOutWithMock(servers.cfg.CONF, 'instance_user')
|
||||||
servers.cfg.CONF.instance_user = 'custom_user'
|
servers.cfg.CONF.instance_user = 'custom_user'
|
||||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
metadata = server.metadata_get()
|
||||||
nova_utils.build_userdata(server,
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||||
'wordpress',
|
nova.NovaClientPlugin.build_userdata(
|
||||||
instance_user='custom_user',
|
metadata,
|
||||||
user_data_format='HEAT_CFNTOOLS')
|
'wordpress',
|
||||||
|
instance_user='custom_user',
|
||||||
|
user_data_format='HEAT_CFNTOOLS')
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
scheduler.TaskRunner(server.create)()
|
scheduler.TaskRunner(server.create)()
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
@ -2067,11 +2067,13 @@ class ServersTest(HeatTestCase):
|
|||||||
server = self._setup_test_server(return_server, 'custom_user')
|
server = self._setup_test_server(return_server, 'custom_user')
|
||||||
self.m.StubOutWithMock(servers.cfg.CONF, 'instance_user')
|
self.m.StubOutWithMock(servers.cfg.CONF, 'instance_user')
|
||||||
servers.cfg.CONF.instance_user = ''
|
servers.cfg.CONF.instance_user = ''
|
||||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
metadata = server.metadata_get()
|
||||||
nova_utils.build_userdata(server,
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||||
'wordpress',
|
nova.NovaClientPlugin.build_userdata(
|
||||||
instance_user=None,
|
metadata,
|
||||||
user_data_format='HEAT_CFNTOOLS')
|
'wordpress',
|
||||||
|
instance_user=None,
|
||||||
|
user_data_format='HEAT_CFNTOOLS')
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
scheduler.TaskRunner(server.create)()
|
scheduler.TaskRunner(server.create)()
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
@ -2531,7 +2533,7 @@ class ServersTest(HeatTestCase):
|
|||||||
# is NOT called during call to server.validate().
|
# is NOT called during call to server.validate().
|
||||||
# This is the way to validate that no excessive calls to Nova
|
# This is the way to validate that no excessive calls to Nova
|
||||||
# are made during validation.
|
# are made during validation.
|
||||||
self.m.StubOutWithMock(nova_utils, 'absolute_limits')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'absolute_limits')
|
||||||
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
|
||||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||||
self._mock_get_image_id_success('F17-x86_64-gold', 'image_id')
|
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 environment
|
||||||
from heat.engine import parser
|
from heat.engine import parser
|
||||||
from heat.engine.resources import instance as instances
|
from heat.engine.resources import instance as instances
|
||||||
from heat.engine.resources import nova_utils
|
|
||||||
from heat.engine import scheduler
|
from heat.engine import scheduler
|
||||||
from heat.tests.common import HeatTestCase
|
from heat.tests.common import HeatTestCase
|
||||||
from heat.tests import utils
|
from heat.tests import utils
|
||||||
@ -152,13 +151,14 @@ class ServerTagsTest(HeatTestCase):
|
|||||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||||
self._mock_get_image_id_success('CentOS 5.2', 1)
|
self._mock_get_image_id_success('CentOS 5.2', 1)
|
||||||
# need to resolve the template functions
|
# need to resolve the template functions
|
||||||
server_userdata = nova_utils.build_userdata(
|
metadata = instance.metadata_get()
|
||||||
instance,
|
server_userdata = instance.client_plugin().build_userdata(
|
||||||
|
metadata,
|
||||||
instance.t['Properties']['UserData'],
|
instance.t['Properties']['UserData'],
|
||||||
'ec2-user')
|
'ec2-user')
|
||||||
self.m.StubOutWithMock(nova_utils, 'build_userdata')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'build_userdata')
|
||||||
nova_utils.build_userdata(
|
nova.NovaClientPlugin.build_userdata(
|
||||||
instance,
|
metadata,
|
||||||
instance.t['Properties']['UserData'],
|
instance.t['Properties']['UserData'],
|
||||||
'ec2-user').AndReturn(server_userdata)
|
'ec2-user').AndReturn(server_userdata)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user