summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSoren Hansen <soren@linux2go.dk>2011-07-28 15:54:27 -0700
committerSoren Hansen <soren@linux2go.dk>2011-07-28 15:54:27 -0700
commit1d269ad0b9a8bc7d30ff1f91faa9afe465f87e98 (patch)
treec55f34b82c5fe7d09bc66f017140f7034733635a
parent00171c3f50d333a1771efc048b064e1fd73614b0 (diff)
parent8c099960a0938f168fe8ca85c63988d697228512 (diff)
Merge trunk
-rwxr-xr-xbin/nova-manage118
-rw-r--r--nova/api/ec2/cloud.py70
-rw-r--r--nova/api/openstack/common.py82
-rw-r--r--nova/api/openstack/create_instance_helper.py36
-rw-r--r--nova/api/openstack/image_metadata.py88
-rw-r--r--nova/api/openstack/images.py2
-rw-r--r--nova/api/openstack/servers.py142
-rw-r--r--nova/api/openstack/views/servers.py15
-rw-r--r--nova/api/openstack/wsgi.py9
-rw-r--r--nova/auth/dbdriver.py2
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/034_change_instance_id_in_migrations.py9
-rw-r--r--nova/exception.py7
-rw-r--r--nova/flags.py2
-rw-r--r--nova/log.py1
-rw-r--r--nova/network/manager.py18
-rw-r--r--nova/tests/api/openstack/test_common.py201
-rw-r--r--nova/tests/api/openstack/test_image_metadata.py201
-rw-r--r--nova/tests/api/openstack/test_servers.py831
-rw-r--r--nova/tests/fake_flags.py1
-rw-r--r--nova/tests/integrated/test_servers.py1
-rw-r--r--nova/tests/test_api.py6
-rw-r--r--nova/tests/test_cloud.py51
-rw-r--r--nova/tests/test_compute.py3
-rw-r--r--nova/tests/test_libvirt.py163
-rw-r--r--nova/tests/test_quota.py3
-rw-r--r--nova/tests/test_vmwareapi.py107
-rw-r--r--nova/tests/test_xenapi.py58
-rw-r--r--nova/tests/vmwareapi/db_fakes.py10
-rw-r--r--nova/tests/vmwareapi/stubs.py7
-rw-r--r--nova/virt/libvirt/connection.py6
-rw-r--r--nova/virt/libvirt/netutils.py10
-rw-r--r--nova/virt/libvirt/vif.py2
-rw-r--r--nova/virt/vmwareapi/fake.py10
-rw-r--r--nova/virt/vmwareapi/network_utils.py1
-rw-r--r--nova/virt/vmwareapi/vm_util.py3
-rw-r--r--nova/virt/vmwareapi/vmops.py7
-rw-r--r--nova/virt/xenapi/vmops.py8
-rw-r--r--nova/virt/xenapi_conn.py9
38 files changed, 1599 insertions, 701 deletions
diff --git a/bin/nova-manage b/bin/nova-manage
index b63bd326f..75d74903c 100755
--- a/bin/nova-manage
+++ b/bin/nova-manage
@@ -631,40 +631,75 @@ class NetworkCommands(object):
"""Class for managing networks."""
@args('--label', dest="label", metavar='<label>',
- help='Label(ex: public)')
- @args('--network', dest="fixed_range", metavar='<x.x.x.x/yy>',
- help='Network')
+ help='Label for network (ex: public)')
+ @args('--fixed_range_v4', dest="fixed_range_v4", metavar='<x.x.x.x/yy>',
+ help='IPv4 subnet (ex: 10.0.0.0/8)')
@args('--num_networks', dest="num_networks", metavar='<number>',
- help='How many networks create')
+ help='Number of networks to create')
@args('--network_size', dest="network_size", metavar='<number>',
- help='How many hosts in network')
+ help='Number of IPs per network')
@args('--vlan', dest="vlan_start", metavar='<vlan id>', help='vlan id')
@args('--vpn', dest="vpn_start", help='vpn start')
- @args('--fixed_range_v6', dest="fixed_range_v6", help='fixed ipv6 range')
+ @args('--fixed_range_v6', dest="fixed_range_v6",
+ help='IPv6 subnet (ex: fe80::/64')
@args('--gateway_v6', dest="gateway_v6", help='ipv6 gateway')
- @args('--flat_network_bridge', dest="flat_network_bridge",
- metavar='<flat network bridge>', help='Flat_network_bridge')
+ @args('--bridge', dest="bridge",
+ metavar='<bridge>',
+ help='VIFs on this network are connected to this bridge')
@args('--bridge_interface', dest="bridge_interface",
- metavar='<bridge interface>', help='Bridge_interface')
+ metavar='<bridge interface>',
+ help='the bridge is connected to this interface')
@args('--multi_host', dest="multi_host", metavar="<'T'|'F'>",
help='Multi host')
@args('--dns1', dest="dns1", metavar="<DNS Address>", help='First DNS')
@args('--dns2', dest="dns2", metavar="<DNS Address>", help='Second DNS')
- def create(self, label=None, fixed_range=None, num_networks=None,
+ def create(self, label=None, fixed_range_v4=None, num_networks=None,
network_size=None, multi_host=None, vlan_start=None,
vpn_start=None, fixed_range_v6=None, gateway_v6=None,
- flat_network_bridge=None, bridge_interface=None,
- dns1=None, dns2=None):
+ bridge=None, bridge_interface=None, dns1=None, dns2=None):
"""Creates fixed ips for host by range"""
+
+ # check for certain required inputs
if not label:
- msg = _('a label (ex: public) is required to create networks.')
- print msg
- raise TypeError(msg)
- if not fixed_range:
- msg = _('Fixed range in the form of 10.0.0.0/8 is '
- 'required to create networks.')
- print msg
- raise TypeError(msg)
+ raise exception.NetworkNotCreated(req='--label')
+ if not fixed_range_v4:
+ raise exception.NetworkNotCreated(req='--fixed_range_v4')
+
+ bridge = bridge or FLAGS.flat_network_bridge
+ if not bridge:
+ bridge_required = ['nova.network.manager.FlatManager',
+ 'nova.network.manager.FlatDHCPManager']
+ if FLAGS.network_manager in bridge_required:
+ # TODO(tr3buchet) - swap print statement and following line for
+ # raise statement in diablo 4
+ print _('--bridge parameter required or FLAG '
+ 'flat_network_bridge must be set to create networks\n'
+ 'WARNING! ACHTUNG! Setting the bridge to br100 '
+ 'automatically is deprecated and will be removed in '
+ 'Diablo milestone 4. Prepare yourself accordingly.')
+ time.sleep(10)
+ bridge = 'br100'
+ #raise exception.NetworkNotCreated(req='--bridge')
+
+ bridge_interface = bridge_interface or FLAGS.flat_interface or \
+ FLAGS.vlan_interface
+ if not bridge_interface:
+ interface_required = ['nova.network.manager.FlatDHCPManager',
+ 'nova.network.manager.VlanManager']
+ if FLAGS.network_manager in interface_required:
+ raise exception.NetworkNotCreated(req='--bridge_interface')
+
+ if FLAGS.use_ipv6:
+ fixed_range_v6 = fixed_range_v6 or FLAGS.fixed_range_v6
+ if not fixed_range_v6:
+ raise exception.NetworkNotCreated(req='with use_ipv6, '
+ '--fixed_range_v6')
+ gateway_v6 = gateway_v6 or FLAGS.gateway_v6
+ if not gateway_v6:
+ raise exception.NetworkNotCreated(req='with use_ipv6, '
+ '--gateway_v6')
+
+ # sanitize other input using FLAGS if necessary
if not num_networks:
num_networks = FLAGS.num_networks
if not network_size:
@@ -677,36 +712,25 @@ class NetworkCommands(object):
vlan_start = FLAGS.vlan_start
if not vpn_start:
vpn_start = FLAGS.vpn_start
- if not fixed_range_v6:
- fixed_range_v6 = FLAGS.fixed_range_v6
- if not flat_network_bridge:
- flat_network_bridge = FLAGS.flat_network_bridge
- if not bridge_interface:
- bridge_interface = FLAGS.flat_interface or FLAGS.vlan_interface
- if not gateway_v6:
- gateway_v6 = FLAGS.gateway_v6
if not dns1 and FLAGS.flat_network_dns:
dns1 = FLAGS.flat_network_dns
- net_manager = utils.import_object(FLAGS.network_manager)
- try:
- net_manager.create_networks(context.get_admin_context(),
- label=label,
- cidr=fixed_range,
- multi_host=multi_host,
- num_networks=int(num_networks),
- network_size=int(network_size),
- vlan_start=int(vlan_start),
- vpn_start=int(vpn_start),
- cidr_v6=fixed_range_v6,
- gateway_v6=gateway_v6,
- bridge=flat_network_bridge,
- bridge_interface=bridge_interface,
- dns1=dns1,
- dns2=dns2)
- except ValueError, e:
- print e
- raise e
+ # create the network
+ net_manager = utils.import_object(FLAGS.network_manager)
+ net_manager.create_networks(context.get_admin_context(),
+ label=label,
+ cidr=fixed_range_v4,
+ multi_host=multi_host,
+ num_networks=int(num_networks),
+ network_size=int(network_size),
+ vlan_start=int(vlan_start),
+ vpn_start=int(vpn_start),
+ cidr_v6=fixed_range_v6,
+ gateway_v6=gateway_v6,
+ bridge=bridge,
+ bridge_interface=bridge_interface,
+ dns1=dns1,
+ dns2=dns2)
def list(self):
"""List all created networks"""
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 10720a804..0294c09c5 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -539,15 +539,18 @@ class CloudController(object):
return rules
if 'ip_ranges' in kwargs:
rules = self._cidr_args_split(kwargs)
+ else:
+ rules = [kwargs]
finalset = []
for rule in rules:
if 'groups' in rule:
groups_values = self._groups_args_split(rule)
for groups_value in groups_values:
- finalset.append(groups_value)
+ final = self._rule_dict_last_step(context, **groups_value)
+ finalset.append(final)
else:
- if rule:
- finalset.append(rule)
+ final = self._rule_dict_last_step(context, **rule)
+ finalset.append(final)
return finalset
def _cidr_args_split(self, kwargs):
@@ -590,6 +593,9 @@ class CloudController(object):
db.security_group_get_by_name(context.elevated(),
source_project_id,
source_security_group_name)
+ notfound = exception.SecurityGroupNotFound
+ if not source_security_group:
+ raise notfound(security_group_id=source_security_group_name)
values['group_id'] = source_security_group['id']
elif cidr_ip:
# If this fails, it throws an exception. This is what we want.
@@ -628,7 +634,7 @@ class CloudController(object):
for rule in security_group.rules:
if 'group_id' in values:
if rule['group_id'] == values['group_id']:
- return True
+ return rule['id']
else:
is_duplicate = True
for key in ('cidr', 'from_port', 'to_port', 'protocol'):
@@ -636,7 +642,7 @@ class CloudController(object):
is_duplicate = False
break
if is_duplicate:
- return True
+ return rule['id']
return False
def revoke_security_group_ingress(self, context, group_name=None,
@@ -659,22 +665,30 @@ class CloudController(object):
msg = "Revoke security group ingress %s"
LOG.audit(_(msg), security_group['name'], context=context)
+ prevalues = []
+ try:
+ prevalues = kwargs['ip_permissions']
+ except KeyError:
+ prevalues.append(kwargs)
+ rule_id = None
+ for values in prevalues:
+ rulesvalues = self._rule_args_to_dict(context, values)
+ if not rulesvalues:
+ err = "%s Not enough parameters to build a valid rule"
+ raise exception.ApiError(_(err % rulesvalues))
- criteria = self._rule_args_to_dict(context, kwargs)[0]
- if criteria is None:
- raise exception.ApiError(_("Not enough parameters to build a "
- "valid rule."))
-
- for rule in security_group.rules:
- match = True
- for (k, v) in criteria.iteritems():
- if getattr(rule, k, False) != v:
- match = False
- if match:
- db.security_group_rule_destroy(context, rule['id'])
- self.compute_api.trigger_security_group_rules_refresh(context,
- security_group_id=security_group['id'])
- return True
+ for values_for_rule in rulesvalues:
+ values_for_rule['parent_group_id'] = security_group.id
+ rule_id = self._security_group_rule_exists(security_group,
+ values_for_rule)
+ if rule_id:
+ db.security_group_rule_destroy(context, rule_id)
+ if rule_id:
+ # NOTE(vish): we removed a rule, so refresh
+ self.compute_api.trigger_security_group_rules_refresh(
+ context,
+ security_group_id=security_group['id'])
+ return True
raise exception.ApiError(_("No rule for the specified parameters."))
# TODO(soren): This has only been tested with Boto as the client.
@@ -721,15 +735,17 @@ class CloudController(object):
postvalues.append(values_for_rule)
for values_for_rule in postvalues:
- security_group_rule = db.security_group_rule_create(context,
- values_for_rule)
+ security_group_rule = db.security_group_rule_create(
+ context,
+ values_for_rule)
- self.compute_api.trigger_security_group_rules_refresh(context,
- security_group_id=security_group['id'])
+ if postvalues:
+ self.compute_api.trigger_security_group_rules_refresh(
+ context,
+ security_group_id=security_group['id'])
+ return True
- group = db.security_group_get_by_name(context, context.project_id,
- security_group['name'])
- return True
+ raise exception.ApiError(_("No rule for the specified parameters."))
def _get_source_project_id(self, context, source_security_group_owner_id):
if source_security_group_owner_id:
diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
index bd14a1389..efa4ab385 100644
--- a/nova/api/openstack/common.py
+++ b/nova/api/openstack/common.py
@@ -17,12 +17,14 @@
import re
from urlparse import urlparse
+from xml.dom import minidom
import webob
from nova import exception
from nova import flags
from nova import log as logging
+from nova.api.openstack import wsgi
LOG = logging.getLogger('nova.api.openstack.common')
@@ -192,3 +194,83 @@ def get_version_from_href(href):
except IndexError:
version = '1.0'
return version
+
+
+class MetadataXMLDeserializer(wsgi.MetadataXMLDeserializer):
+
+ def _extract_metadata_container(self, datastring):
+ dom = minidom.parseString(datastring)
+ metadata_node = self.find_first_child_named(dom, "metadata")
+ metadata = self.extract_metadata(metadata_node)
+ return {'body': {'metadata': metadata}}
+
+ def create(self, datastring):
+ return self._extract_metadata_container(datastring)
+
+ def update_all(self, datastring):
+ return self._extract_metadata_container(datastring)
+
+ def update(self, datastring):
+ dom = minidom.parseString(datastring)
+ metadata_item = self.extract_metadata(dom)
+ return {'body': {'meta': metadata_item}}
+
+
+class MetadataHeadersSerializer(wsgi.ResponseHeadersSerializer):
+
+ def delete(self, response, data):
+ response.status_int = 204
+
+
+class MetadataXMLSerializer(wsgi.XMLDictSerializer):
+ def __init__(self, xmlns=wsgi.XMLNS_V11):
+ super(MetadataXMLSerializer, self).__init__(xmlns=xmlns)
+
+ def _meta_item_to_xml(self, doc, key, value):
+ node = doc.createElement('meta')
+ doc.appendChild(node)
+ node.setAttribute('key', '%s' % key)
+ text = doc.createTextNode('%s' % value)
+ node.appendChild(text)
+ return node
+
+ def meta_list_to_xml(self, xml_doc, meta_items):
+ container_node = xml_doc.createElement('metadata')
+ for (key, value) in meta_items:
+ item_node = self._meta_item_to_xml(xml_doc, key, value)
+ container_node.appendChild(item_node)
+ return container_node
+
+ def _meta_list_to_xml_string(self, metadata_dict):
+ xml_doc = minidom.Document()
+ items = metadata_dict['metadata'].items()
+ container_node = self.meta_list_to_xml(xml_doc, items)
+ xml_doc.appendChild(container_node)
+ self._add_xmlns(container_node)
+ return xml_doc.toprettyxml(indent=' ', encoding='UTF-8')
+
+ def index(self, metadata_dict):
+ return self._meta_list_to_xml_string(metadata_dict)
+
+ def create(self, metadata_dict):
+ return self._meta_list_to_xml_string(metadata_dict)
+
+ def update_all(self, metadata_dict):
+ return self._meta_list_to_xml_string(metadata_dict)
+
+ def _meta_item_to_xml_string(self, meta_item_dict):
+ xml_doc = minidom.Document()
+ item_key, item_value = meta_item_dict.items()[0]
+ item_node = self._meta_item_to_xml(xml_doc, item_key, item_value)
+ xml_doc.appendChild(item_node)
+ self._add_xmlns(item_node)
+ return xml_doc.toprettyxml(indent=' ', encoding='UTF-8')
+
+ def show(self, meta_item_dict):
+ return self._meta_item_to_xml_string(meta_item_dict['meta'])
+
+ def update(self, meta_item_dict):
+ return self._meta_item_to_xml_string(meta_item_dict['meta'])
+
+ def default(self, *args, **kwargs):
+ return ''
diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py
index f8317565e..1342397c4 100644
--- a/nova/api/openstack/create_instance_helper.py
+++ b/nova/api/openstack/create_instance_helper.py
@@ -188,7 +188,7 @@ class CreateInstanceHelper(object):
Overrides normal behavior in the case of xml content
"""
if request.content_type == "application/xml":
- deserializer = ServerCreateRequestXMLDeserializer()
+ deserializer = ServerXMLDeserializer()
return deserializer.deserialize(request.body)
else:
return self._deserialize(request.body, request.get_content_type())
@@ -303,29 +303,29 @@ class ServerXMLDeserializer(wsgi.MetadataXMLDeserializer):
"""Marshal the server attribute of a parsed request"""
server = {}
server_node = self.find_first_child_named(node, 'server')
- for attr in ["name", "imageId", "flavorId", "imageRef", "flavorRef"]:
+
+ attributes = ["name", "imageId", "flavorId", "imageRef",
+ "flavorRef", "adminPass"]
+ for attr in attributes:
if server_node.getAttribute(attr):
server[attr] = server_node.getAttribute(attr)
+
metadata_node = self.find_first_child_named(server_node, "metadata")
- metadata = self.extract_metadata(metadata_node)
- if metadata is not None:
- server["metadata"] = metadata
- personality = self._extract_personality(server_node)
- if personality is not None:
- server["personality"] = personality
+ server["metadata"] = self.extract_metadata(metadata_node)
+
+ server["personality"] = self._extract_personality(server_node)
+
return server
def _extract_personality(self, server_node):
"""Marshal the personality attribute of a parsed request"""
- personality_node = \
- self.find_first_child_named(server_node, "personality")
- if personality_node is None:
- return None
+ node = self.find_first_child_named(server_node, "personality")
personality = []
- for file_node in self.find_children_named(personality_node, "file"):
- item = {}
- if file_node.hasAttribute("path"):
- item["path"] = file_node.getAttribute("path")
- item["contents"] = self.extract_text(file_node)
- personality.append(item)
+ if node is not None:
+ for file_node in self.find_children_named(node, "file"):
+ item = {}
+ if file_node.hasAttribute("path"):
+ item["path"] = file_node.getAttribute("path")
+ item["contents"] = self.extract_text(file_node)
+ personality.append(item)
return personality
diff --git a/nova/api/openstack/image_metadata.py b/nova/api/openstack/image_metadata.py
index ee181c924..aaf64a123 100644
--- a/nova/api/openstack/image_metadata.py
+++ b/nova/api/openstack/image_metadata.py
@@ -16,12 +16,12 @@
# under the License.
from webob import exc
-from xml.dom import minidom
from nova import flags
from nova import image
from nova import quota
from nova import utils
+from nova.api.openstack import common
from nova.api.openstack import wsgi
@@ -118,95 +118,15 @@ class Controller(object):
self.image_service.update(context, image_id, img, None)
-class ImageMetadataXMLDeserializer(wsgi.MetadataXMLDeserializer):
-
- def _extract_metadata_container(self, datastring):
- dom = minidom.parseString(datastring)
- metadata_node = self.find_first_child_named(dom, "metadata")
- metadata = self.extract_metadata(metadata_node)
- return {'body': {'metadata': metadata}}
-
- def create(self, datastring):
- return self._extract_metadata_container(datastring)
-
- def update_all(self, datastring):
- return self._extract_metadata_container(datastring)
-
- def update(self, datastring):
- dom = minidom.parseString(datastring)
- metadata_item = self.extract_metadata(dom)
- return {'body': {'meta': metadata_item}}
-
-
-class HeadersSerializer(wsgi.ResponseHeadersSerializer):
-
- def delete(self, response, data):
- response.status_int = 204
-
-
-class ImageMetadataXMLSerializer(wsgi.XMLDictSerializer):
- def __init__(self, xmlns=wsgi.XMLNS_V11):
- super(ImageMetadataXMLSerializer, self).__init__(xmlns=xmlns)
-
- def _meta_item_to_xml(self, doc, key, value):
- node = doc.createElement('meta')
- doc.appendChild(node)
- node.setAttribute('key', '%s' % key)
- text = doc.createTextNode('%s' % value)
- node.appendChild(text)
- return node
-
- def meta_list_to_xml(self, xml_doc, meta_items):
- container_node = xml_doc.createElement('metadata')
- for (key, value) in meta_items:
- item_node = self._meta_item_to_xml(xml_doc, key, value)
- container_node.appendChild(item_node)
- return container_node
-
- def _meta_list_to_xml_string(self, metadata_dict):
- xml_doc = minidom.Document()
- items = metadata_dict['metadata'].items()
- container_node = self.meta_list_to_xml(xml_doc, items)
- xml_doc.appendChild(container_node)
- self._add_xmlns(container_node)
- return xml_doc.toprettyxml(indent=' ', encoding='UTF-8')
-
- def index(self, metadata_dict):
- return self._meta_list_to_xml_string(metadata_dict)
-
- def create(self, metadata_dict):
- return self._meta_list_to_xml_string(metadata_dict)
-
- def update_all(self, metadata_dict):
- return self._meta_list_to_xml_string(metadata_dict)
-
- def _meta_item_to_xml_string(self, meta_item_dict):
- xml_doc = minidom.Document()
- item_key, item_value = meta_item_dict.items()[0]
- item_node = self._meta_item_to_xml(xml_doc, item_key, item_value)
- xml_doc.appendChild(item_node)
- self._add_xmlns(item_node)
- return xml_doc.toprettyxml(indent=' ', encoding='UTF-8')
-
- def show(self, meta_item_dict):
- return self._meta_item_to_xml_string(meta_item_dict['meta'])
-
- def update(self, meta_item_dict):
- return self._meta_item_to_xml_string(meta_item_dict['meta'])
-
- def default(self, *args, **kwargs):
- return ''
-
-
def create_resource():
- headers_serializer = HeadersSerializer()
+ headers_serializer = common.MetadataHeadersSerializer()
body_deserializers = {
- 'application/xml': ImageMetadataXMLDeserializer(),
+ 'application/xml': common.MetadataXMLDeserializer(),
}
body_serializers = {
- 'application/xml': ImageMetadataXMLSerializer(),
+ 'application/xml': common.MetadataXMLSerializer(),
}
serializer = wsgi.ResponseSerializer(body_serializers, headers_serializer)
deserializer = wsgi.RequestDeserializer(body_deserializers)
diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py
index 30e4fd389..9ba8b639e 100644
--- a/nova/api/openstack/images.py
+++ b/nova/api/openstack/images.py
@@ -284,7 +284,7 @@ class ImageXMLSerializer(wsgi.XMLDictSerializer):
xmlns = wsgi.XMLNS_V11
def __init__(self):
- self.metadata_serializer = image_metadata.ImageMetadataXMLSerializer()
+ self.metadata_serializer = common.MetadataXMLSerializer()
def _image_to_xml(self, xml_doc, image):
image_node = xml_doc.createElement('image')
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index d7cabb067..f6841318d 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -18,6 +18,7 @@ import traceback
from webob import exc
import webob
+from xml.dom import minidom
from nova import compute
from nova import db
@@ -27,6 +28,7 @@ from nova import log as logging
from nova import utils
from nova.api.openstack import common
from nova.api.openstack import create_instance_helper as helper
+from nova.api.openstack import ips
import nova.api.openstack.views.addresses
import nova.api.openstack.views.flavors
import nova.api.openstack.views.images
@@ -480,11 +482,20 @@ class ControllerV11(Controller):
raise exc.HTTPNotFound()
def _image_ref_from_req_data(self, data):
- return data['server']['imageRef']
+ try:
+ return data['server']['imageRef']
+ except (TypeError, KeyError):
+ msg = _("Missing imageRef attribute")
+ raise exc.HTTPBadRequest(explanation=msg)
def _flavor_id_from_req_data(self, data):
- href = data['server']['flavorRef']
- return common.get_id_from_href(href)
+ try:
+ flavor_ref = data['server']['flavorRef']
+ except (TypeError, KeyError):
+ msg = _("Missing flavorRef attribute")
+ raise exc.HTTPBadRequest(explanation=msg)
+
+ return common.get_id_from_href(flavor_ref)
def _build_view(self, req, instance, is_detail=False):
base_url = req.application_url
@@ -599,6 +610,123 @@ class HeadersSerializer(wsgi.ResponseHeadersSerializer):
response.status_int = 204
+class ServerXMLSerializer(wsgi.XMLDictSerializer):
+
+ xmlns = wsgi.XMLNS_V11
+
+ def __init__(self):
+ self.metadata_serializer = common.MetadataXMLSerializer()
+ self.addresses_serializer = ips.IPXMLSerializer()
+
+ def _create_basic_entity_node(self, xml_doc, id, links, name):
+ basic_node = xml_doc.createElement(name)
+ basic_node.setAttribute('id', str(id))
+ link_nodes = self._create_link_nodes(xml_doc, links)
+ for link_node in link_nodes:
+ basic_node.appendChild(link_node)
+ return basic_node
+
+ def _create_metadata_node(self, xml_doc, metadata):
+ return self.metadata_serializer.meta_list_to_xml(xml_doc, metadata)
+
+ def _create_addresses_node(self, xml_doc, addresses):
+ return self.addresses_serializer.networks_to_xml(xml_doc, addresses)
+
+ def _add_server_attributes(self, node, server):
+ node.setAttribute('id', str(server['id']))
+ node.setAttribute('uuid', str(server['uuid']))
+ node.setAttribute('hostId', str(server['hostId']))
+ node.setAttribute('name', server['name'])
+ node.setAttribute('created', str(server['created']))
+ node.setAttribute('updated', str(server['updated']))
+ node.setAttribute('status', server['status'])
+ if 'progress' in server:
+ node.setAttribute('progress', str(server['progress']))
+
+ def _server_to_xml(self, xml_doc, server):
+ server_node = xml_doc.createElement('server')
+ server_node.setAttribute('id', str(server['id']))
+ server_node.setAttribute('name', server['name'])
+ link_nodes = self._create_link_nodes(xml_doc,
+ server['links'])
+ for link_node in link_nodes:
+ server_node.appendChild(link_node)
+ return server_node
+
+ def _server_to_xml_detailed(self, xml_doc, server):
+ server_node = xml_doc.createElement('server')
+ self._add_server_attributes(server_node, server)
+
+ link_nodes = self._create_link_nodes(xml_doc,
+ server['links'])
+ for link_node in link_nodes:
+ server_node.appendChild(link_node)
+
+ if 'image' in server:
+ image_node = self._create_basic_entity_node(xml_doc,
+ server['image']['id'],
+ server['image']['links'],
+ 'image')
+ server_node.appendChild(image_node)
+
+ if 'flavor' in server:
+ flavor_node = self._create_basic_entity_node(xml_doc,
+ server['flavor']['id'],
+ server['flavor']['links'],
+ 'flavor')
+ server_node.appendChild(flavor_node)
+
+ metadata = server.get('metadata', {}).items()
+ if len(metadata) > 0:
+ metadata_node = self._create_metadata_node(xml_doc, metadata)
+ server_node.appendChild(metadata_node)
+
+ addresses_node = self._create_addresses_node(xml_doc,
+ server['addresses'])
+ server_node.appendChild(addresses_node)
+
+ return server_node
+
+ def _server_list_to_xml(self, xml_doc, servers, detailed):
+ container_node = xml_doc.createElement('servers')
+ if detailed:
+ server_to_xml = self._server_to_xml_detailed
+ else:
+ server_to_xml = self._server_to_xml
+
+ for server in servers:
+ item_node = server_to_xml(xml_doc, server)
+ container_node.appendChild(item_node)
+ return container_node
+
+ def index(self, servers_dict):
+ xml_doc = minidom.Document()
+ node = self._server_list_to_xml(xml_doc,
+ servers_dict['servers'],
+ detailed=False)
+ return self.to_xml_string(node, True)
+
+ def detail(self, servers_dict):
+ xml_doc = minidom.Document()
+ node = self._server_list_to_xml(xml_doc,
+ servers_dict['servers'],
+ detailed=True)
+ return self.to_xml_string(node, True)
+
+ def show(self, server_dict):
+ xml_doc = minidom.Document()
+ node = self._server_to_xml_detailed(xml_doc,
+ server_dict['server'])
+ return self.to_xml_string(node, True)
+
+ def create(self, server_dict):
+ xml_doc = minidom.Document()
+ node = self._server_to_xml_detailed(xml_doc,
+ server_dict['server'])
+ node.setAttribute('adminPass', server_dict['server']['adminPass'])
+ return self.to_xml_string(node, True)
+
+
def create_resource(version='1.0'):
controller = {
'1.0': ControllerV10,
@@ -628,9 +756,13 @@ def create_resource(version='1.0'):
headers_serializer = HeadersSerializer()
+ xml_serializer = {
+ '1.0': wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V10),
+ '1.1': ServerXMLSerializer(),
+ }[version]
+
body_serializers = {
- 'application/xml': wsgi.XMLDictSerializer(metadata=metadata,
- xmlns=xmlns),
+ 'application/xml': xml_serializer,
}
body_deserializers = {
diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py
index be25e1e40..659a43522 100644
--- a/nova/api/openstack/views/servers.py
+++ b/nova/api/openstack/views/servers.py
@@ -15,6 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import datetime
import hashlib
import os
@@ -149,8 +150,10 @@ class ViewBuilderV11(ViewBuilder):
def _build_detail(self, inst):
response = super(ViewBuilderV11, self)._build_detail(inst)
- response['server']['created'] = inst['created_at']
- response['server']['updated'] = inst['updated_at']
+ response['server']['created'] = \
+ self._convert_timeformat(inst['created_at'])
+ response['server']['updated'] = \
+ self._convert_timeformat(inst['updated_at'])
if 'status' in response['server']:
if response['server']['status'] == "ACTIVE":
response['server']['progress'] = 100
@@ -221,3 +224,11 @@ class ViewBuilderV11(ViewBuilder):
"""Create an url that refers to a specific flavor id."""
return os.path.join(common.remove_version_from_href(self.base_url),
"servers", str(server_id))
+
+ def _convert_timeformat(self, date_time):
+ """Converts the given time into the common time format
+
+ :param date_time: the datetime object to convert
+
+ """
+ return date_time.strftime(utils.TIME_FORMAT)
diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py
index a28443d12..53dab22e8 100644
--- a/nova/api/openstack/wsgi.py
+++ b/nova/api/openstack/wsgi.py
@@ -165,12 +165,11 @@ class MetadataXMLDeserializer(XMLDeserializer):
def extract_metadata(self, metadata_node):
"""Marshal the metadata attribute of a parsed request"""
- if metadata_node is None:
- return None
metadata = {}
- for meta_node in self.find_children_named(metadata_node, "meta"):
- key = meta_node.getAttribute("key")
- metadata[key] = self.extract_text(meta_node)
+ if metadata_node is not None:
+ for meta_node in self.find_children_named(metadata_node, "meta"):
+ key = meta_node.getAttribute("key")
+ metadata[key] = self.extract_text(meta_node)
return metadata
diff --git a/nova/auth/dbdriver.py b/nova/auth/dbdriver.py
index a429b7812..c6d81ee04 100644
--- a/nova/auth/dbdriver.py
+++ b/nova/auth/dbdriver.py
@@ -127,7 +127,7 @@ class DbDriver(object):
try:
project = db.project_create(context.get_admin_context(), values)
- except exception.Duplicate:
+ except exception.DBError:
raise exception.ProjectExists(project=name)
for member in members:
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/034_change_instance_id_in_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/034_change_instance_id_in_migrations.py
index b002ba064..4e8eaf0fd 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/034_change_instance_id_in_migrations.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/034_change_instance_id_in_migrations.py
@@ -17,6 +17,7 @@
from sqlalchemy import Column, Integer, String, MetaData, Table
+
meta = MetaData()
@@ -33,6 +34,14 @@ def upgrade(migrate_engine):
meta.bind = migrate_engine
migrations = Table('migrations', meta, autoload=True)
migrations.create_column(instance_uuid)
+
+ if migrate_engine.name == "mysql":
+ try:
+ migrate_engine.execute("ALTER TABLE migrations DROP FOREIGN KEY " \
+ "`migrations_ibfk_1`;")
+ except Exception: # Don't care, just fail silently.
+ pass
+
migrations.c.instance_id.drop()
diff --git a/nova/exception.py b/nova/exception.py
index 38e705417..8c9b45a80 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -116,7 +116,8 @@ def wrap_exception(notifier=None, publisher_id=None, event_type=None,
notifier.notify(publisher_id, temp_type, temp_level,
payload)
- if not isinstance(e, Error):
+ if (not isinstance(e, Error) and
+ not isinstance(e, NovaException)):
#exc_type, exc_value, exc_traceback = sys.exc_info()
LOG.exception(_('Uncaught exception'))
#logging.error(traceback.extract_stack(exc_traceback))
@@ -372,6 +373,10 @@ class StorageRepositoryNotFound(NotFound):
message = _("Cannot find SR to read/write VDI.")
+class NetworkNotCreated(NovaException):
+ message = _("%(req)s is required to create a network.")
+
+
class NetworkNotFound(NotFound):
message = _("Network %(network_id)s could not be found.")
diff --git a/nova/flags.py b/nova/flags.py
index 49355b436..fa6d8860a 100644
--- a/nova/flags.py
+++ b/nova/flags.py
@@ -343,7 +343,7 @@ DEFINE_string('lock_path', os.path.join(os.path.dirname(__file__), '../'),
'Directory for lock files')
DEFINE_string('logdir', None, 'output to a per-service log file in named '
'directory')
-
+DEFINE_integer('logfile_mode', 0644, 'Default file mode of the logs.')
DEFINE_string('sqlite_db', 'nova.sqlite', 'file name for sqlite')
DEFINE_string('sql_connection',
'sqlite:///$state_path/$sqlite_db',
diff --git a/nova/log.py b/nova/log.py
index f8c0ba68d..133ee45f8 100644
--- a/nova/log.py
+++ b/nova/log.py
@@ -257,6 +257,7 @@ class NovaRootLogger(NovaLogger):
self.filelog = WatchedFileHandler(logpath)
self.addHandler(self.filelog)
self.logpath = logpath
+ os.chmod(self.logpath, FLAGS.logfile_mode)
else:
self.removeHandler(self.filelog)
self.addHandler(self.streamlog)
diff --git a/nova/network/manager.py b/nova/network/manager.py
index e380a12a8..75fcb0310 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -69,7 +69,7 @@ LOG = logging.getLogger("nova.network.manager")
FLAGS = flags.FLAGS
-flags.DEFINE_string('flat_network_bridge', 'br100',
+flags.DEFINE_string('flat_network_bridge', None,
'Bridge for simple network instances')
flags.DEFINE_string('flat_network_dns', '8.8.4.4',
'Dns for simple network')
@@ -632,12 +632,13 @@ class NetworkManager(manager.SchedulerDependentManager):
bridge_interface, dns1=None, dns2=None, **kwargs):
"""Create networks based on parameters."""
fixed_net = netaddr.IPNetwork(cidr)
- fixed_net_v6 = netaddr.IPNetwork(cidr_v6)
- significant_bits_v6 = 64
- network_size_v6 = 1 << 64
+ if FLAGS.use_ipv6:
+ fixed_net_v6 = netaddr.IPNetwork(cidr_v6)
+ significant_bits_v6 = 64
+ network_size_v6 = 1 << 64
+
for index in range(num_networks):
start = index * network_size
- start_v6 = index * network_size_v6
significant_bits = 32 - int(math.log(network_size, 2))
cidr = '%s/%s' % (fixed_net[start], significant_bits)
project_net = netaddr.IPNetwork(cidr)
@@ -658,6 +659,7 @@ class NetworkManager(manager.SchedulerDependentManager):
net['label'] = label
if FLAGS.use_ipv6:
+ start_v6 = index * network_size_v6
cidr_v6 = '%s/%s' % (fixed_net_v6[start_v6],
significant_bits_v6)
net['cidr_v6'] = cidr_v6
@@ -738,9 +740,9 @@ class FlatManager(NetworkManager):
"""Basic network where no vlans are used.
FlatManager does not do any bridge or vlan creation. The user is
- responsible for setting up whatever bridge is specified in
- flat_network_bridge (br100 by default). This bridge needs to be created
- on all compute hosts.
+ responsible for setting up whatever bridges are specified when creating
+ networks through nova-manage. This bridge needs to be created on all
+ compute hosts.
The idea is to create a single network for the host with a command like:
nova-manage network create 192.168.0.0/24 1 256. Creating multiple
diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py
index f09270b34..0b76841f0 100644
--- a/nova/tests/api/openstack/test_common.py
+++ b/nova/tests/api/openstack/test_common.py
@@ -20,6 +20,7 @@ Test suites for 'common' code used throughout the OpenStack HTTP API.
"""
import webob.exc
+import xml.dom.minidom as minidom
from webob import Request
@@ -265,3 +266,203 @@ class MiscFunctionsTest(test.TestCase):
expected = '1.0'
actual = common.get_version_from_href(fixture)
self.assertEqual(actual, expected)
+
+
+class MetadataXMLDeserializationTest(test.TestCase):
+
+ deserializer = common.MetadataXMLDeserializer()
+
+ def test_create(self):
+ request_body = """
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key='123'>asdf</meta>
+ <meta key='567'>jkl;</meta>
+ </metadata>"""
+ output = self.deserializer.deserialize(request_body, 'create')
+ expected = {"body": {"metadata": {"123": "asdf", "567": "jkl;"}}}
+ self.assertEquals(output, expected)
+
+ def test_create_empty(self):
+ request_body = """
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"/>"""
+ output = self.deserializer.deserialize(request_body, 'create')
+ expected = {"body": {"metadata": {}}}
+ self.assertEquals(output, expected)
+
+ def test_update_all(self):
+ request_body = """
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key='123'>asdf</meta>
+ <meta key='567'>jkl;</meta>
+ </metadata>"""
+ output = self.deserializer.deserialize(request_body, 'update_all')
+ expected = {"body": {"metadata": {"123": "asdf", "567": "jkl;"}}}
+ self.assertEquals(output, expected)
+
+ def test_update(self):
+ request_body = """
+ <meta xmlns="http://docs.openstack.org/compute/api/v1.1"
+ key='123'>asdf</meta>"""
+ output = self.deserializer.deserialize(request_body, 'update')
+ expected = {"body": {"meta": {"123": "asdf"}}}
+ self.assertEquals(output, expected)
+
+
+class MetadataXMLSerializationTest(test.TestCase):
+
+ def test_index(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'metadata': {
+ 'one': 'two',
+ 'three': 'four',
+ },
+ }
+ output = serializer.serialize(fixture, 'index')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key="three">
+ four
+ </meta>
+ <meta key="one">
+ two
+ </meta>
+ </metadata>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_index_null(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'metadata': {
+ None: None,
+ },
+ }
+ output = serializer.serialize(fixture, 'index')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key="None">
+ None
+ </meta>
+ </metadata>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_index_unicode(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'metadata': {
+ u'three': u'Jos\xe9',
+ },
+ }
+ output = serializer.serialize(fixture, 'index')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString(u"""
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key="three">
+ Jos\xe9
+ </meta>
+ </metadata>
+ """.encode("UTF-8").replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_show(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'meta': {
+ 'one': 'two',
+ },
+ }
+ output = serializer.serialize(fixture, 'show')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one">
+ two
+ </meta>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_update_all(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'metadata': {
+ 'key6': 'value6',
+ 'key4': 'value4',
+ },
+ }
+ output = serializer.serialize(fixture, 'update_all')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key="key6">
+ value6
+ </meta>
+ <meta key="key4">
+ value4
+ </meta>
+ </metadata>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_update_item(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'meta': {
+ 'one': 'two',
+ },
+ }
+ output = serializer.serialize(fixture, 'update')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one">
+ two
+ </meta>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_create(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'metadata': {
+ 'key9': 'value9',
+ 'key2': 'value2',
+ 'key1': 'value1',
+ },
+ }
+ output = serializer.serialize(fixture, 'create')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key="key2">
+ value2
+ </meta>
+ <meta key="key9">
+ value9
+ </meta>
+ <meta key="key1">
+ value1
+ </meta>
+ </metadata>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_delete(self):
+ serializer = common.MetadataXMLSerializer()
+ output = serializer.serialize(None, 'delete')
+ self.assertEqual(output, '')
diff --git a/nova/tests/api/openstack/test_image_metadata.py b/nova/tests/api/openstack/test_image_metadata.py
index 31ca18497..c9137cc24 100644
--- a/nova/tests/api/openstack/test_image_metadata.py
+++ b/nova/tests/api/openstack/test_image_metadata.py
@@ -19,7 +19,6 @@ import json
import stubout
import unittest
import webob
-import xml.dom.minidom as minidom
from nova import flags
@@ -252,203 +251,3 @@ class ImageMetaDataTest(test.TestCase):
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(400, res.status_int)
-
-
-class ImageMetadataXMLDeserializationTest(test.TestCase):
-
- deserializer = openstack.image_metadata.ImageMetadataXMLDeserializer()
-
- def test_create(self):
- request_body = """
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key='123'>asdf</meta>
- <meta key='567'>jkl;</meta>
- </metadata>"""
- output = self.deserializer.deserialize(request_body, 'create')
- expected = {"body": {"metadata": {"123": "asdf", "567": "jkl;"}}}
- self.assertEquals(output, expected)
-
- def test_create_empty(self):
- request_body = """
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"/>"""
- output = self.deserializer.deserialize(request_body, 'create')
- expected = {"body": {"metadata": {}}}
- self.assertEquals(output, expected)
-
- def test_update_all(self):
- request_body = """
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key='123'>asdf</meta>
- <meta key='567'>jkl;</meta>
- </metadata>"""
- output = self.deserializer.deserialize(request_body, 'update_all')
- expected = {"body": {"metadata": {"123": "asdf", "567": "jkl;"}}}
- self.assertEquals(output, expected)
-
- def test_update(self):
- request_body = """
- <meta xmlns="http://docs.openstack.org/compute/api/v1.1"
- key='123'>asdf</meta>"""
- output = self.deserializer.deserialize(request_body, 'update')
- expected = {"body": {"meta": {"123": "asdf"}}}
- self.assertEquals(output, expected)
-
-
-class ImageMetadataXMLSerializationTest(test.TestCase):
-
- def test_index(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'metadata': {
- 'one': 'two',
- 'three': 'four',
- },
- }
- output = serializer.serialize(fixture, 'index')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString("""
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key="three">
- four
- </meta>
- <meta key="one">
- two
- </meta>
- </metadata>
- """.replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_index_null(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'metadata': {
- None: None,
- },
- }
- output = serializer.serialize(fixture, 'index')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString("""
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key="None">
- None
- </meta>
- </metadata>
- """.replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_index_unicode(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'metadata': {
- u'three': u'Jos\xe9',
- },
- }
- output = serializer.serialize(fixture, 'index')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString(u"""
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key="three">
- Jos\xe9
- </meta>
- </metadata>
- """.encode("UTF-8").replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_show(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'meta': {
- 'one': 'two',
- },
- }
- output = serializer.serialize(fixture, 'show')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString("""
- <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one">
- two
- </meta>
- """.replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_update_all(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'metadata': {
- 'key6': 'value6',
- 'key4': 'value4',
- },
- }
- output = serializer.serialize(fixture, 'update_all')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString("""
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key="key6">
- value6
- </meta>
- <meta key="key4">
- value4
- </meta>
- </metadata>
- """.replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_update_item(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'meta': {
- 'one': 'two',
- },
- }
- output = serializer.serialize(fixture, 'update')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString("""
- <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one">
- two
- </meta>
- """.replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_create(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'metadata': {
- 'key9': 'value9',
- 'key2': 'value2',
- 'key1': 'value1',
- },
- }
- output = serializer.serialize(fixture, 'create')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString("""
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key="key2">
- value2
- </meta>
- <meta key="key9">
- value9
- </meta>
- <meta key="key1">
- value1
- </meta>
- </metadata>
- """.replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_delete(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- output = serializer.serialize(None, 'delete')
- self.assertEqual(output, '')
diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py
index 4ca79434f..4027ef829 100644
--- a/nova/tests/api/openstack/test_servers.py
+++ b/nova/tests/api/openstack/test_servers.py
@@ -16,6 +16,7 @@
# under the License.
import base64
+import datetime
import json
import unittest
from xml.dom import minidom
@@ -172,8 +173,8 @@ def stub_instance(id, user_id=1, private_address=None, public_addresses=None,
instance = {
"id": int(id),
- "created_at": "2010-10-10T12:00:00Z",
- "updated_at": "2010-11-11T11:00:00Z",
+ "created_at": datetime.datetime(2010, 10, 10, 12, 0, 0),
+ "updated_at": datetime.datetime(2010, 11, 11, 11, 0, 0),
"admin_pass": "",
"user_id": user_id,
"project_id": "",
@@ -399,6 +400,78 @@ class ServersTest(test.TestCase):
self.assertDictMatch(res_dict, expected_server)
+ def test_get_server_by_id_v1_1_xml(self):
+ image_bookmark = "http://localhost/images/10"
+ flavor_ref = "http://localhost/v1.1/flavors/1"
+ flavor_id = "1"
+ flavor_bookmark = "http://localhost/flavors/1"
+ server_href = "http://localhost/v1.1/servers/1"
+ server_bookmark = "http://localhost/servers/1"
+
+ public_ip = '192.168.0.3'
+ private_ip = '172.19.0.1'
+ interfaces = [
+ {
+ 'network': {'label': 'public'},
+ 'fixed_ips': [
+ {'address': public_ip},
+ ],
+ },
+ {
+ 'network': {'label': 'private'},
+ 'fixed_ips': [
+ {'address': private_ip},
+ ],
+ },
+ ]
+ new_return_server = return_server_with_attributes(
+ interfaces=interfaces)
+ self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
+
+ req = webob.Request.blank('/v1.1/servers/1')
+ req.headers['Accept'] = 'application/xml'
+ res = req.get_response(fakes.wsgi_app())
+ actual = minidom.parseString(res.body.replace(' ', ''))
+ expected_uuid = FAKE_UUID
+ expected_updated = "2010-11-11T11:00:00Z"
+ expected_created = "2010-10-10T12:00:00Z"
+ expected = minidom.parseString("""
+ <server id="1"
+ uuid="%(expected_uuid)s"
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom"
+ name="server1"
+ updated="%(expected_updated)s"
+ created="%(expected_created)s"
+ hostId=""
+ status="BUILD"
+ progress="0">
+ <atom:link href="%(server_href)s" rel="self"/>
+ <atom:link href="%(server_bookmark)s" rel="bookmark"/>
+ <image id="10">
+ <atom:link rel="bookmark" href="%(image_bookmark)s"/>
+ </image>
+ <flavor id="1">
+ <atom:link rel="bookmark" href="%(flavor_bookmark)s"/>
+ </flavor>
+ <metadata>
+ <meta key="seq">
+ 1
+ </meta>
+ </metadata>
+ <addresses>
+ <network id="public">
+ <ip version="4" addr="%(public_ip)s"/>
+ </network>
+ <network id="private">
+ <ip version="4" addr="%(private_ip)s"/>
+ </network>
+ </addresses>
+ </server>
+ """.replace(" ", "") % (locals()))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
def test_get_server_with_active_status_by_id_v1_1(self):
image_bookmark = "http://localhost/images/10"
flavor_ref = "http://localhost/v1.1/flavors/1"
@@ -1048,8 +1121,8 @@ class ServersTest(test.TestCase):
'uuid': FAKE_UUID,
'instance_type': dict(inst_type),
'image_ref': image_ref,
- 'created_at': '2010-10-10T12:00:00Z',
- 'updated_at': '2010-11-11T11:00:00Z',
+ "created_at": datetime.datetime(2010, 10, 10, 12, 0, 0),
+ "updated_at": datetime.datetime(2010, 11, 11, 11, 0, 0),
}
def server_update(context, id, params):
@@ -1099,6 +1172,7 @@ class ServersTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 200)
server = json.loads(res.body)['server']
self.assertEqual(16, len(server['adminPass']))
self.assertEqual('server_test', server['name'])
@@ -1106,7 +1180,6 @@ class ServersTest(test.TestCase):
self.assertEqual(2, server['flavorId'])
self.assertEqual(3, server['imageId'])
self.assertEqual(FAKE_UUID, server['uuid'])
- self.assertEqual(res.status_int, 200)
def test_create_instance(self):
self._test_create_instance_helper()
@@ -1279,7 +1352,12 @@ class ServersTest(test.TestCase):
'hello': 'world',
'open': 'stack',
},
- 'personality': {},
+ 'personality': [
+ {
+ "path": "/etc/banner.txt",
+ "contents": "MQ==",
+ },
+ ],
},
}
@@ -1293,11 +1371,11 @@ class ServersTest(test.TestCase):
self.assertEqual(res.status_int, 200)
server = json.loads(res.body)['server']
self.assertEqual(16, len(server['adminPass']))
+ self.assertEqual(1, server['id'])
+ self.assertEqual(0, server['progress'])
self.assertEqual('server_test', server['name'])
self.assertEqual(expected_flavor, server['flavor'])
self.assertEqual(expected_image, server['image'])
- self.assertEqual(res.status_int, 200)
- #self.assertEqual(1, server['id'])
def test_create_instance_v1_1_invalid_flavor_href(self):
self._setup_for_create_instance()
@@ -1351,7 +1429,7 @@ class ServersTest(test.TestCase):
self._setup_for_create_instance()
image_id = "2"
- flavor_ref = 'http://localhost/flavors/3'
+ flavor_ref = 'http://localhost/v1.1/flavors/3'
expected_flavor = {
"id": "3",
"links": [
@@ -1385,10 +1463,10 @@ class ServersTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 200)
server = json.loads(res.body)['server']
self.assertEqual(expected_flavor, server['flavor'])
self.assertEqual(expected_image, server['image'])
- self.assertEqual(res.status_int, 200)
def test_create_instance_with_admin_pass_v1_0(self):
self._setup_for_create_instance()
@@ -1411,7 +1489,7 @@ class ServersTest(test.TestCase):
self.assertNotEqual(res['server']['adminPass'],
body['server']['adminPass'])
- def test_create_instance_with_admin_pass_v1_1(self):
+ def test_create_instance_v1_1_admin_pass(self):
self._setup_for_create_instance()
image_href = 'http://localhost/v1.1/images/2'
@@ -1419,8 +1497,8 @@ class ServersTest(test.TestCase):
body = {
'server': {
'name': 'server_test',
- 'imageRef': image_href,
- 'flavorRef': flavor_ref,
+ 'imageRef': 3,
+ 'flavorRef': 3,
'adminPass': 'testpass',
},
}
@@ -1430,19 +1508,18 @@ class ServersTest(test.TestCase):
req.body = json.dumps(body)
req.headers['content-type'] = "application/json"
res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 200)
server = json.loads(res.body)['server']
self.assertEqual(server['adminPass'], body['server']['adminPass'])
- def test_create_instance_with_empty_admin_pass_v1_1(self):
+ def test_create_instance_v1_1_admin_pass_empty(self):
self._setup_for_create_instance()
- image_href = 'http://localhost/v1.1/images/2'
- flavor_ref = 'http://localhost/v1.1/flavors/3'
body = {
'server': {
'name': 'server_test',
- 'imageRef': image_href,
- 'flavorRef': flavor_ref,
+ 'imageRef': 3,
+ 'flavorRef': 3,
'adminPass': '',
},
}
@@ -2235,7 +2312,7 @@ class ServersTest(test.TestCase):
self.assertEqual(res_dict['server']['status'], 'SHUTOFF')
-class TestServerCreateRequestXMLDeserializer(unittest.TestCase):
+class TestServerCreateRequestXMLDeserializerV10(unittest.TestCase):
def setUp(self):
self.deserializer = create_instance_helper.ServerXMLDeserializer()
@@ -2249,6 +2326,8 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase):
"name": "new-server-test",
"imageId": "1",
"flavorId": "1",
+ "metadata": {},
+ "personality": [],
}}
self.assertEquals(request['body'], expected)
@@ -2264,6 +2343,7 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase):
"imageId": "1",
"flavorId": "1",
"metadata": {},
+ "personality": [],
}}
self.assertEquals(request['body'], expected)
@@ -2278,6 +2358,7 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase):
"name": "new-server-test",
"imageId": "1",
"flavorId": "1",
+ "metadata": {},
"personality": [],
}}
self.assertEquals(request['body'], expected)
@@ -2515,18 +2596,188 @@ b25zLiINCg0KLVJpY2hhcmQgQmFjaA==""",
request = self.deserializer.deserialize(serial_request, 'create')
self.assertEqual(request['body'], expected)
- def test_request_xmlser_with_flavor_image_href(self):
+
+class TestServerCreateRequestXMLDeserializerV11(unittest.TestCase):
+
+ def setUp(self):
+ self.deserializer = create_instance_helper.ServerXMLDeserializer()
+
+ def test_minimal_request(self):
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="1"
+ flavorRef="2"/>"""
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "1",
+ "flavorRef": "2",
+ "metadata": {},
+ "personality": [],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_admin_pass(self):
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="1"
+ flavorRef="2"
+ adminPass="1234"/>"""
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "1",
+ "flavorRef": "2",
+ "adminPass": "1234",
+ "metadata": {},
+ "personality": [],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_image_link(self):
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="http://localhost:8774/v1.1/images/2"
+ flavorRef="3"/>"""
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "http://localhost:8774/v1.1/images/2",
+ "flavorRef": "3",
+ "metadata": {},
+ "personality": [],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_flavor_link(self):
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="1"
+ flavorRef="http://localhost:8774/v1.1/flavors/3"/>"""
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "1",
+ "flavorRef": "http://localhost:8774/v1.1/flavors/3",
+ "metadata": {},
+ "personality": [],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_empty_metadata_personality(self):
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="1"
+ flavorRef="2">
+ <metadata/>
+ <personality/>
+</server>"""
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "1",
+ "flavorRef": "2",
+ "metadata": {},
+ "personality": [],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_multiple_metadata_items(self):
serial_request = """
- <server xmlns="http://docs.openstack.org/compute/api/v1.1"
- name="new-server-test"
- imageRef="http://localhost:8774/v1.1/images/1"
- flavorRef="http://localhost:8774/v1.1/flavors/1">
- </server>"""
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="1"
+ flavorRef="2">
+ <metadata>
+ <meta key="one">two</meta>
+ <meta key="open">snack</meta>
+ </metadata>
+</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
- self.assertEquals(request['body']["server"]["flavorRef"],
- "http://localhost:8774/v1.1/flavors/1")
- self.assertEquals(request['body']["server"]["imageRef"],
- "http://localhost:8774/v1.1/images/1")
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "1",
+ "flavorRef": "2",
+ "metadata": {"one": "two", "open": "snack"},
+ "personality": [],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_multiple_personality_files(self):
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="1"
+ flavorRef="2">
+ <personality>
+ <file path="/etc/banner.txt">MQ==</file>
+ <file path="/etc/hosts">Mg==</file>
+ </personality>
+</server>"""
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "1",
+ "flavorRef": "2",
+ "metadata": {},
+ "personality": [
+ {"path": "/etc/banner.txt", "contents": "MQ=="},
+ {"path": "/etc/hosts", "contents": "Mg=="},
+ ],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_spec_request(self):
+ image_bookmark_link = "http://servers.api.openstack.org/1234/" + \
+ "images/52415800-8b69-11e0-9b19-734f6f006e54"
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ imageRef="%s"
+ flavorRef="52415800-8b69-11e0-9b19-734f1195ff37"
+ name="new-server-test">
+ <metadata>
+ <meta key="My Server Name">Apache1</meta>
+ </metadata>
+ <personality>
+ <file path="/etc/banner.txt">Mg==</file>
+ </personality>
+</server>""" % (image_bookmark_link)
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "http://servers.api.openstack.org/1234/" + \
+ "images/52415800-8b69-11e0-9b19-734f6f006e54",
+ "flavorRef": "52415800-8b69-11e0-9b19-734f1195ff37",
+ "metadata": {"My Server Name": "Apache1"},
+ "personality": [
+ {
+ "path": "/etc/banner.txt",
+ "contents": "Mg==",
+ },
+ ],
+ },
+ }
+ self.assertEquals(request['body'], expected)
class TextAddressesXMLSerialization(test.TestCase):
@@ -2899,10 +3150,12 @@ class ServersViewBuilderV11Test(test.TestCase):
pass
def _get_instance(self):
+ created_at = datetime.datetime(2010, 10, 10, 12, 0, 0)
+ updated_at = datetime.datetime(2010, 11, 11, 11, 0, 0)
instance = {
"id": 1,
- "created_at": "2010-10-10T12:00:00Z",
- "updated_at": "2010-11-11T11:00:00Z",
+ "created_at": created_at,
+ "updated_at": updated_at,
"admin_pass": "",
"user_id": "",
"project_id": "",
@@ -2950,7 +3203,7 @@ class ServersViewBuilderV11Test(test.TestCase):
address_builder,
flavor_builder,
image_builder,
- base_url
+ base_url,
)
return view_builder
@@ -3106,12 +3359,12 @@ class ServersViewBuilderV11Test(test.TestCase):
},
"flavor": {
"id": "1",
- "links": [
- {
- "rel": "bookmark",
- "href": flavor_bookmark,
- },
- ],
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": flavor_bookmark,
+ },
+ ],
},
"addresses": {},
"metadata": {
@@ -3133,3 +3386,505 @@ class ServersViewBuilderV11Test(test.TestCase):
output = self.view_builder.build(self.instance, True)
self.assertDictMatch(output, expected_server)
+
+
+class ServerXMLSerializationTest(test.TestCase):
+
+ TIMESTAMP = "2010-10-11T10:30:22Z"
+ SERVER_HREF = 'http://localhost/v1.1/servers/123'
+ SERVER_BOOKMARK = 'http://localhost/servers/123'
+ IMAGE_BOOKMARK = 'http://localhost/images/5'
+ FLAVOR_BOOKMARK = 'http://localhost/flavors/1'
+
+ def setUp(self):
+ self.maxDiff = None
+ test.TestCase.setUp(self)
+
+ def test_show(self):
+ serializer = servers.ServerXMLSerializer()
+
+ fixture = {
+ "server": {
+ "id": 1,
+ "uuid": FAKE_UUID,
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ "progress": 0,
+ "name": "test_server",
+ "status": "BUILD",
+ "hostId": 'e4d909c290d0fb1ca068ffaddf22cbd0',
+ "image": {
+ "id": "5",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": self.IMAGE_BOOKMARK,
+ },
+ ],
+ },
+ "flavor": {
+ "id": "1",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": self.FLAVOR_BOOKMARK,
+ },
+ ],
+ },
+ "addresses": {
+ "network_one": [
+ {
+ "version": 4,
+ "addr": "67.23.10.138",
+ },
+ {
+ "version": 6,
+ "addr": "::babe:67.23.10.138",
+ },
+ ],
+ "network_two": [
+ {
+ "version": 4,
+ "addr": "67.23.10.139",
+ },
+ {
+ "version": 6,
+ "addr": "::babe:67.23.10.139",
+ },
+ ],
+ },
+ "metadata": {
+ "Open": "Stack",
+ "Number": "1",
+ },
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ }
+ }
+
+ output = serializer.serialize(fixture, 'show')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected_server_href = self.SERVER_HREF
+ expected_server_bookmark = self.SERVER_BOOKMARK
+ expected_image_bookmark = self.IMAGE_BOOKMARK
+ expected_flavor_bookmark = self.FLAVOR_BOOKMARK
+ expected_now = self.TIMESTAMP
+ expected_uuid = FAKE_UUID
+ expected = minidom.parseString("""
+ <server id="1"
+ uuid="%(expected_uuid)s"
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom"
+ name="test_server"
+ updated="%(expected_now)s"
+ created="%(expected_now)s"
+ hostId="e4d909c290d0fb1ca068ffaddf22cbd0"
+ status="BUILD"
+ progress="0">
+ <atom:link href="%(expected_server_href)s" rel="self"/>
+ <atom:link href="%(expected_server_bookmark)s" rel="bookmark"/>
+ <image id="5">
+ <atom:link rel="bookmark" href="%(expected_image_bookmark)s"/>
+ </image>
+ <flavor id="1">
+ <atom:link rel="bookmark" href="%(expected_flavor_bookmark)s"/>
+ </flavor>
+ <metadata>
+ <meta key="Open">
+ Stack
+ </meta>
+ <meta key="Number">
+ 1
+ </meta>
+ </metadata>
+ <addresses>
+ <network id="network_one">
+ <ip version="4" addr="67.23.10.138"/>
+ <ip version="6" addr="::babe:67.23.10.138"/>
+ </network>
+ <network id="network_two">
+ <ip version="4" addr="67.23.10.139"/>
+ <ip version="6" addr="::babe:67.23.10.139"/>
+ </network>
+ </addresses>
+ </server>
+ """.replace(" ", "") % (locals()))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_create(self):
+ serializer = servers.ServerXMLSerializer()
+
+ fixture = {
+ "server": {
+ "id": 1,
+ "uuid": FAKE_UUID,
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ "progress": 0,
+ "name": "test_server",
+ "status": "BUILD",
+ "hostId": "e4d909c290d0fb1ca068ffaddf22cbd0",
+ "adminPass": "test_password",
+ "image": {
+ "id": "5",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": self.IMAGE_BOOKMARK,
+ },
+ ],
+ },
+ "flavor": {
+ "id": "1",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": self.FLAVOR_BOOKMARK,
+ },
+ ],
+ },
+ "addresses": {
+ "network_one": [
+ {
+ "version": 4,
+ "addr": "67.23.10.138",
+ },
+ {
+ "version": 6,
+ "addr": "::babe:67.23.10.138",
+ },
+ ],
+ "network_two": [
+ {
+ "version": 4,
+ "addr": "67.23.10.139",
+ },
+ {
+ "version": 6,
+ "addr": "::babe:67.23.10.139",
+ },
+ ],
+ },
+ "metadata": {
+ "Open": "Stack",
+ "Number": "1",
+ },
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ }
+ }
+
+ output = serializer.serialize(fixture, 'create')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected_server_href = self.SERVER_HREF
+ expected_server_bookmark = self.SERVER_BOOKMARK
+ expected_image_bookmark = self.IMAGE_BOOKMARK
+ expected_flavor_bookmark = self.FLAVOR_BOOKMARK
+ expected_now = self.TIMESTAMP
+ expected_uuid = FAKE_UUID
+ expected = minidom.parseString("""
+ <server id="1"
+ uuid="%(expected_uuid)s"
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom"
+ name="test_server"
+ updated="%(expected_now)s"
+ created="%(expected_now)s"
+ hostId="e4d909c290d0fb1ca068ffaddf22cbd0"
+ status="BUILD"
+ adminPass="test_password"
+ progress="0">
+ <atom:link href="%(expected_server_href)s" rel="self"/>
+ <atom:link href="%(expected_server_bookmark)s" rel="bookmark"/>
+ <image id="5">
+ <atom:link rel="bookmark" href="%(expected_image_bookmark)s"/>
+ </image>
+ <flavor id="1">
+ <atom:link rel="bookmark" href="%(expected_flavor_bookmark)s"/>
+ </flavor>
+ <metadata>
+ <meta key="Open">
+ Stack
+ </meta>
+ <meta key="Number">
+ 1
+ </meta>
+ </metadata>
+ <addresses>
+ <network id="network_one">
+ <ip version="4" addr="67.23.10.138"/>
+ <ip version="6" addr="::babe:67.23.10.138"/>
+ </network>
+ <network id="network_two">
+ <ip version="4" addr="67.23.10.139"/>
+ <ip version="6" addr="::babe:67.23.10.139"/>
+ </network>
+ </addresses>
+ </server>
+ """.replace(" ", "") % (locals()))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_index(self):
+ serializer = servers.ServerXMLSerializer()
+
+ expected_server_href = 'http://localhost/v1.1/servers/1'
+ expected_server_bookmark = 'http://localhost/servers/1'
+ expected_server_href_2 = 'http://localhost/v1.1/servers/2'
+ expected_server_bookmark_2 = 'http://localhost/servers/2'
+ fixture = {"servers": [
+ {
+ "id": 1,
+ "name": "test_server",
+ 'links': [
+ {
+ 'href': expected_server_href,
+ 'rel': 'self',
+ },
+ {
+ 'href': expected_server_bookmark,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ {
+ "id": 2,
+ "name": "test_server_2",
+ 'links': [
+ {
+ 'href': expected_server_href_2,
+ 'rel': 'self',
+ },
+ {
+ 'href': expected_server_bookmark_2,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ ]}
+
+ output = serializer.serialize(fixture, 'index')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <servers xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom">
+ <server id="1" name="test_server">
+ <atom:link href="%(expected_server_href)s" rel="self"/>
+ <atom:link href="%(expected_server_bookmark)s" rel="bookmark"/>
+ </server>
+ <server id="2" name="test_server_2">
+ <atom:link href="%(expected_server_href_2)s" rel="self"/>
+ <atom:link href="%(expected_server_bookmark_2)s" rel="bookmark"/>
+ </server>
+ </servers>
+ """.replace(" ", "") % (locals()))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_detail(self):
+ serializer = servers.ServerXMLSerializer()
+
+ expected_server_href = 'http://localhost/v1.1/servers/1'
+ expected_server_bookmark = 'http://localhost/servers/1'
+ expected_image_bookmark = self.IMAGE_BOOKMARK
+ expected_flavor_bookmark = self.FLAVOR_BOOKMARK
+ expected_now = self.TIMESTAMP
+ expected_uuid = FAKE_UUID
+
+ expected_server_href_2 = 'http://localhost/v1.1/servers/2'
+ expected_server_bookmark_2 = 'http://localhost/servers/2'
+ fixture = {"servers": [
+ {
+ "id": 1,
+ "uuid": FAKE_UUID,
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ "progress": 0,
+ "name": "test_server",
+ "status": "BUILD",
+ "hostId": 'e4d909c290d0fb1ca068ffaddf22cbd0',
+ "image": {
+ "id": "5",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": expected_image_bookmark,
+ },
+ ],
+ },
+ "flavor": {
+ "id": "1",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": expected_flavor_bookmark,
+ },
+ ],
+ },
+ "addresses": {
+ "network_one": [
+ {
+ "version": 4,
+ "addr": "67.23.10.138",
+ },
+ {
+ "version": 6,
+ "addr": "::babe:67.23.10.138",
+ },
+ ],
+ },
+ "metadata": {
+ "Number": "1",
+ },
+ "links": [
+ {
+ "href": expected_server_href,
+ "rel": "self",
+ },
+ {
+ "href": expected_server_bookmark,
+ "rel": "bookmark",
+ },
+ ],
+ },
+ {
+ "id": 2,
+ "uuid": FAKE_UUID,
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ "progress": 100,
+ "name": "test_server_2",
+ "status": "ACTIVE",
+ "hostId": 'e4d909c290d0fb1ca068ffaddf22cbd0',
+ "image": {
+ "id": "5",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": expected_image_bookmark,
+ },
+ ],
+ },
+ "flavor": {
+ "id": "1",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": expected_flavor_bookmark,
+ },
+ ],
+ },
+ "addresses": {
+ "network_one": [
+ {
+ "version": 4,
+ "addr": "67.23.10.138",
+ },
+ {
+ "version": 6,
+ "addr": "::babe:67.23.10.138",
+ },
+ ],
+ },
+ "metadata": {
+ "Number": "2",
+ },
+ "links": [
+ {
+ "href": expected_server_href_2,
+ "rel": "self",
+ },
+ {
+ "href": expected_server_bookmark_2,
+ "rel": "bookmark",
+ },
+ ],
+ },
+ ]}
+
+ output = serializer.serialize(fixture, 'detail')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <servers xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom">
+ <server id="1"
+ uuid="%(expected_uuid)s"
+ name="test_server"
+ updated="%(expected_now)s"
+ created="%(expected_now)s"
+ hostId="e4d909c290d0fb1ca068ffaddf22cbd0"
+ status="BUILD"
+ progress="0">
+ <atom:link href="%(expected_server_href)s" rel="self"/>
+ <atom:link href="%(expected_server_bookmark)s" rel="bookmark"/>
+ <image id="5">
+ <atom:link rel="bookmark" href="%(expected_image_bookmark)s"/>
+ </image>
+ <flavor id="1">
+ <atom:link rel="bookmark" href="%(expected_flavor_bookmark)s"/>
+ </flavor>
+ <metadata>
+ <meta key="Number">
+ 1
+ </meta>
+ </metadata>
+ <addresses>
+ <network id="network_one">
+ <ip version="4" addr="67.23.10.138"/>
+ <ip version="6" addr="::babe:67.23.10.138"/>
+ </network>
+ </addresses>
+ </server>
+ <server id="2"
+ uuid="%(expected_uuid)s"
+ name="test_server_2"
+ updated="%(expected_now)s"
+ created="%(expected_now)s"
+ hostId="e4d909c290d0fb1ca068ffaddf22cbd0"
+ status="ACTIVE"
+ progress="100">
+ <atom:link href="%(expected_server_href_2)s" rel="self"/>
+ <atom:link href="%(expected_server_bookmark_2)s" rel="bookmark"/>
+ <image id="5">
+ <atom:link rel="bookmark" href="%(expected_image_bookmark)s"/>
+ </image>
+ <flavor id="1">
+ <atom:link rel="bookmark" href="%(expected_flavor_bookmark)s"/>
+ </flavor>
+ <metadata>
+ <meta key="Number">
+ 2
+ </meta>
+ </metadata>
+ <addresses>
+ <network id="network_one">
+ <ip version="4" addr="67.23.10.138"/>
+ <ip version="6" addr="::babe:67.23.10.138"/>
+ </network>
+ </addresses>
+ </server>
+ </servers>
+ """.replace(" ", "") % (locals()))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py
index 2297d2f0e..073216495 100644
--- a/nova/tests/fake_flags.py
+++ b/nova/tests/fake_flags.py
@@ -42,3 +42,4 @@ FLAGS['iscsi_num_targets'].SetDefault(8)
FLAGS['verbose'].SetDefault(True)
FLAGS['sqlite_db'].SetDefault("tests.sqlite")
FLAGS['use_ipv6'].SetDefault(True)
+FLAGS['flat_network_bridge'].SetDefault('br100')
diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py
index 4e8e85c7b..67b3c485a 100644
--- a/nova/tests/integrated/test_servers.py
+++ b/nova/tests/integrated/test_servers.py
@@ -305,5 +305,6 @@ class ServersTest(integrated_helpers._IntegratedTestBase):
# Cleanup
self._delete_server(server_id)
+
if __name__ == "__main__":
unittest.main()
diff --git a/nova/tests/test_api.py b/nova/tests/test_api.py
index 26ac5ff24..fe7fd8402 100644
--- a/nova/tests/test_api.py
+++ b/nova/tests/test_api.py
@@ -213,7 +213,11 @@ class ApiEc2TestCase(test.TestCase):
self.http = FakeHttplibConnection(
self.app, '%s:8773' % (self.host), False)
# pylint: disable=E1103
- self.ec2.new_http_connection(host, is_secure).AndReturn(self.http)
+ if boto.Version >= '2':
+ self.ec2.new_http_connection(host or '%s:8773' % (self.host),
+ is_secure).AndReturn(self.http)
+ else:
+ self.ec2.new_http_connection(host, is_secure).AndReturn(self.http)
return self.http
def test_return_valid_isoformat(self):
diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py
index 136082cc1..e419e7a50 100644
--- a/nova/tests/test_cloud.py
+++ b/nova/tests/test_cloud.py
@@ -121,7 +121,6 @@ class CloudTestCase(test.TestCase):
public_ip=address)
db.floating_ip_destroy(self.context, address)
- @test.skip_test("Skipping this pending future merge")
def test_allocate_address(self):
address = "10.10.10.10"
allocate = self.cloud.allocate_address
@@ -161,13 +160,10 @@ class CloudTestCase(test.TestCase):
# ApiError: Floating ip is in use. Disassociate it before releasing.
self.assertRaises(exception.ApiError, release, self.context, address)
- @test.skip_test("Skipping this pending future merge")
def test_associate_disassociate_address(self):
"""Verifies associate runs cleanly without raising an exception"""
address = "10.10.10.10"
- db.floating_ip_create(self.context,
- {'address': address,
- 'host': self.network.host})
+ db.floating_ip_create(self.context, {'address': address})
self.cloud.allocate_address(self.context)
# TODO(jkoelker) Probably need to query for instance_type_id and
# make sure we get a valid one
@@ -175,11 +171,14 @@ class CloudTestCase(test.TestCase):
'instance_type_id': 1})
networks = db.network_get_all(self.context)
for network in networks:
- self.network.set_network_host(self.context, network['id'])
+ db.network_update(self.context, network['id'],
+ {'host': self.network.host})
project_id = self.context.project_id
type_id = inst['instance_type_id']
ips = self.network.allocate_for_instance(self.context,
instance_id=inst['id'],
+ host=inst['host'],
+ vpn=None,
instance_type_id=type_id,
project_id=project_id)
# TODO(jkoelker) Make this mas bueno
@@ -287,7 +286,7 @@ class CloudTestCase(test.TestCase):
'ip_protocol': u'tcp'}]}
self.assertTrue(authz(self.context, group_name=sec['name'], **kwargs))
- def test_authorize_security_group_ingress_ip_permissions_groups(self):
+ def test_authorize_security_group_fail_missing_source_group(self):
kwargs = {'project_id': self.context.project_id, 'name': 'test'}
sec = db.security_group_create(self.context, kwargs)
authz = self.cloud.authorize_security_group_ingress
@@ -295,6 +294,23 @@ class CloudTestCase(test.TestCase):
'ip_ranges':{'1': {'cidr_ip': u'0.0.0.0/0'},
'2': {'cidr_ip': u'10.10.10.10/32'}},
'groups': {'1': {'user_id': u'someuser',
+ 'group_name': u'somegroup1'}},
+ 'ip_protocol': u'tcp'}]}
+ self.assertRaises(exception.SecurityGroupNotFound, authz,
+ self.context, group_name=sec['name'], **kwargs)
+
+ def test_authorize_security_group_ingress_ip_permissions_groups(self):
+ kwargs = {'project_id': self.context.project_id, 'name': 'test'}
+ sec = db.security_group_create(self.context,
+ {'project_id': 'someuser',
+ 'name': 'somegroup1'})
+ sec = db.security_group_create(self.context,
+ {'project_id': 'someuser',
+ 'name': 'othergroup2'})
+ sec = db.security_group_create(self.context, kwargs)
+ authz = self.cloud.authorize_security_group_ingress
+ kwargs = {'ip_permissions': [{'to_port': 81, 'from_port': 81,
+ 'groups': {'1': {'user_id': u'someuser',
'group_name': u'somegroup1'},
'2': {'user_id': u'someuser',
'group_name': u'othergroup2'}},
@@ -405,8 +421,6 @@ class CloudTestCase(test.TestCase):
db.service_destroy(self.context, service1['id'])
db.service_destroy(self.context, service2['id'])
- # NOTE(jkoelker): this test relies on fixed_ip being in instances
- @test.skip_test("EC2 stuff needs fixed_ip in instance_ref")
def test_describe_snapshots(self):
"""Makes sure describe_snapshots works and filters results."""
vol = db.volume_create(self.context, {})
@@ -1041,12 +1055,6 @@ class CloudTestCase(test.TestCase):
self.cloud.delete_key_pair(self.context, 'test')
def test_run_instances(self):
- # stub out the rpc call
- def stub_cast(*args, **kwargs):
- pass
-
- self.stubs.Set(rpc, 'cast', stub_cast)
-
kwargs = {'image_id': FLAGS.default_image,
'instance_type': FLAGS.default_instance_type,
'max_count': 1}
@@ -1056,7 +1064,7 @@ class CloudTestCase(test.TestCase):
self.assertEqual(instance['imageId'], 'ami-00000001')
self.assertEqual(instance['displayName'], 'Server 1')
self.assertEqual(instance['instanceId'], 'i-00000001')
- self.assertEqual(instance['instanceState']['name'], 'scheduling')
+ self.assertEqual(instance['instanceState']['name'], 'running')
self.assertEqual(instance['instanceType'], 'm1.small')
def test_run_instances_image_state_none(self):
@@ -1128,16 +1136,15 @@ class CloudTestCase(test.TestCase):
self.assertEqual('c00l 1m4g3', inst['display_name'])
db.instance_destroy(self.context, inst['id'])
- # NOTE(jkoelker): This test relies on mac_address in instance
- @test.skip_test("EC2 stuff needs mac_address in instance_ref")
def test_update_of_instance_wont_update_private_fields(self):
inst = db.instance_create(self.context, {})
+ host = inst['host']
ec2_id = ec2utils.id_to_ec2_id(inst['id'])
self.cloud.update_instance(self.context, ec2_id,
display_name='c00l 1m4g3',
- mac_address='DE:AD:BE:EF')
+ host='otherhost')
inst = db.instance_get(self.context, inst['id'])
- self.assertEqual(None, inst['mac_address'])
+ self.assertEqual(host, inst['host'])
db.instance_destroy(self.context, inst['id'])
def test_update_of_volume_display_fields(self):
@@ -1193,7 +1200,6 @@ class CloudTestCase(test.TestCase):
elevated = self.context.elevated(read_deleted=True)
self._wait_for_state(elevated, instance_id, is_deleted)
- @test.skip_test("skipping, test is hanging with multinic for rpc reasons")
def test_stop_start_instance(self):
"""Makes sure stop/start instance works"""
# enforce periodic tasks run in short time to avoid wait for 60s.
@@ -1251,7 +1257,6 @@ class CloudTestCase(test.TestCase):
self.assertEqual(vol['status'], "available")
self.assertEqual(vol['attach_status'], "detached")
- @test.skip_test("skipping, test is hanging with multinic for rpc reasons")
def test_stop_start_with_volume(self):
"""Make sure run instance with block device mapping works"""
@@ -1320,7 +1325,6 @@ class CloudTestCase(test.TestCase):
self._restart_compute_service()
- @test.skip_test("skipping, test is hanging with multinic for rpc reasons")
def test_stop_with_attached_volume(self):
"""Make sure attach info is reflected to block device mapping"""
# enforce periodic tasks run in short time to avoid wait for 60s.
@@ -1396,7 +1400,6 @@ class CloudTestCase(test.TestCase):
greenthread.sleep(0.3)
return result['snapshotId']
- @test.skip_test("skipping, test is hanging with multinic for rpc reasons")
def test_run_with_snapshot(self):
"""Makes sure run/stop/start instance with snapshot works."""
vol = self._volume_create()
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index 2a8f33dd3..0ede4f469 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -583,8 +583,9 @@ class ComputeTestCase(test.TestCase):
the same host"""
instance_id = self._create_instance()
self.compute.run_instance(self.context, instance_id)
+ inst_ref = db.instance_get(self.context, instance_id)
self.assertRaises(exception.Error, self.compute.prep_resize,
- self.context, instance_id, 1)
+ self.context, inst_ref['uuid'], 1)
self.compute.terminate_instance(self.context, instance_id)
def test_migrate(self):
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index e3c884238..de7f22925 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -73,12 +73,12 @@ def _create_network_info(count=1, ipv6=None):
return [(network, mapping) for x in xrange(0, count)]
-def _setup_networking(instance_id, ip='1.2.3.4'):
+def _setup_networking(instance_id, ip='1.2.3.4', mac='56:12:12:12:12:12'):
ctxt = context.get_admin_context()
network_ref = db.project_get_networks(ctxt,
'fake',
associate=True)[0]
- vif = {'address': '56:12:12:12:12:12',
+ vif = {'address': mac,
'network_id': network_ref['id'],
'instance_id': instance_id}
vif_ref = db.virtual_interface_create(ctxt, vif)
@@ -88,7 +88,7 @@ def _setup_networking(instance_id, ip='1.2.3.4'):
'virtual_interface_id': vif_ref['id']}
db.fixed_ip_create(ctxt, fixed_ip)
db.fixed_ip_update(ctxt, ip, {'allocated': True,
- 'instance_id': instance_id})
+ 'instance_id': instance_id})
class CacheConcurrencyTestCase(test.TestCase):
@@ -177,13 +177,13 @@ class LibvirtConnTestCase(test.TestCase):
self.context = context.get_admin_context()
FLAGS.instances_path = ''
self.call_libvirt_dependant_setup = False
+ self.test_ip = '10.11.12.13'
def tearDown(self):
self.manager.delete_project(self.project)
self.manager.delete_user(self.user)
super(LibvirtConnTestCase, self).tearDown()
- test_ip = '10.11.12.13'
test_instance = {'memory_kb': '1024000',
'basepath': '/some/path',
'bridge_name': 'br100',
@@ -232,6 +232,16 @@ class LibvirtConnTestCase(test.TestCase):
def setattr(self, key, val):
self.__setattr__(key, val)
+ def plug(self, instance, network, mapping):
+ return {
+ 'id': 'fake',
+ 'bridge_name': 'fake',
+ 'mac_address': 'fake',
+ 'ip_address': 'fake',
+ 'dhcp_server': 'fake',
+ 'extra_params': 'fake'
+ }
+
# Creating mocks
fake = FakeLibvirtConnection()
fakeip = FakeIptablesFirewallDriver
@@ -280,7 +290,6 @@ class LibvirtConnTestCase(test.TestCase):
return db.service_create(context.get_admin_context(), service_ref)
- @test.skip_test("Please review this test to ensure intent")
def test_preparing_xml_info(self):
conn = connection.LibvirtConnection(True)
instance_ref = db.instance_create(self.context, self.test_instance)
@@ -296,27 +305,23 @@ class LibvirtConnTestCase(test.TestCase):
_create_network_info(2))
self.assertTrue(len(result['nics']) == 2)
- @test.skip_test("skipping libvirt tests depends on get_network_info shim")
def test_xml_and_uri_no_ramdisk_no_kernel(self):
instance_data = dict(self.test_instance)
self._check_xml_and_uri(instance_data,
expect_kernel=False, expect_ramdisk=False)
- @test.skip_test("skipping libvirt tests depends on get_network_info shim")
def test_xml_and_uri_no_ramdisk(self):
instance_data = dict(self.test_instance)
instance_data['kernel_id'] = 'aki-deadbeef'
self._check_xml_and_uri(instance_data,
expect_kernel=True, expect_ramdisk=False)
- @test.skip_test("skipping libvirt tests depends on get_network_info shim")
def test_xml_and_uri_no_kernel(self):
instance_data = dict(self.test_instance)
instance_data['ramdisk_id'] = 'ari-deadbeef'
self._check_xml_and_uri(instance_data,
expect_kernel=False, expect_ramdisk=False)
- @test.skip_test("skipping libvirt tests depends on get_network_info shim")
def test_xml_and_uri(self):
instance_data = dict(self.test_instance)
instance_data['ramdisk_id'] = 'ari-deadbeef'
@@ -324,7 +329,6 @@ class LibvirtConnTestCase(test.TestCase):
self._check_xml_and_uri(instance_data,
expect_kernel=True, expect_ramdisk=True)
- @test.skip_test("skipping libvirt tests depends on get_network_info shim")
def test_xml_and_uri_rescue(self):
instance_data = dict(self.test_instance)
instance_data['ramdisk_id'] = 'ari-deadbeef'
@@ -332,7 +336,6 @@ class LibvirtConnTestCase(test.TestCase):
self._check_xml_and_uri(instance_data, expect_kernel=True,
expect_ramdisk=True, rescue=True)
- @test.skip_test("skipping libvirt tests depends on get_network_info shim")
def test_lxc_container_and_uri(self):
instance_data = dict(self.test_instance)
self._check_xml_and_container(instance_data)
@@ -412,6 +415,15 @@ class LibvirtConnTestCase(test.TestCase):
self.assertEquals(snapshot['status'], 'active')
self.assertEquals(snapshot['name'], snapshot_name)
+ def test_attach_invalid_device(self):
+ self.create_fake_libvirt_mock()
+ connection.LibvirtConnection._conn.lookupByName = self.fake_lookup
+ self.mox.ReplayAll()
+ conn = connection.LibvirtConnection(False)
+ self.assertRaises(exception.InvalidDevicePath,
+ conn.attach_volume,
+ "fake", "bad/device/path", "/dev/fake")
+
def test_multi_nic(self):
instance_data = dict(self.test_instance)
network_info = _create_network_info(2)
@@ -432,24 +444,7 @@ class LibvirtConnTestCase(test.TestCase):
user_context = context.RequestContext(project=self.project,
user=self.user)
instance_ref = db.instance_create(user_context, instance)
- # Re-get the instance so it's bound to an actual session
- instance_ref = db.instance_get(user_context, instance_ref['id'])
- network_ref = db.project_get_networks(context.get_admin_context(),
- self.project.id)[0]
-
- vif = {'address': '56:12:12:12:12:12',
- 'network_id': network_ref['id'],
- 'instance_id': instance_ref['id']}
- vif_ref = db.virtual_interface_create(self.context, vif)
- fixed_ip = {'address': self.test_ip,
- 'network_id': network_ref['id'],
- 'virtual_interface_id': vif_ref['id']}
-
- ctxt = context.get_admin_context()
- fixed_ip_ref = db.fixed_ip_create(ctxt, fixed_ip)
- db.fixed_ip_update(ctxt, self.test_ip,
- {'allocated': True,
- 'instance_id': instance_ref['id']})
+ _setup_networking(instance_ref['id'], self.test_ip)
self.flags(libvirt_type='lxc')
conn = connection.LibvirtConnection(True)
@@ -481,7 +476,7 @@ class LibvirtConnTestCase(test.TestCase):
network_ref = db.project_get_networks(context.get_admin_context(),
self.project.id)[0]
- _setup_networking(instance_ref['id'], ip=self.test_ip)
+ _setup_networking(instance_ref['id'], self.test_ip)
type_uri_map = {'qemu': ('qemu:///system',
[(lambda t: t.find('.').get('type'), 'qemu'),
@@ -743,7 +738,6 @@ class LibvirtConnTestCase(test.TestCase):
db.volume_destroy(self.context, volume_ref['id'])
db.instance_destroy(self.context, instance_ref['id'])
- @test.skip_test("test needs rewrite: instance no longer has mac_address")
def test_spawn_with_network_info(self):
# Skip if non-libvirt environment
if not self.lazy_load_library_exists():
@@ -762,17 +756,7 @@ class LibvirtConnTestCase(test.TestCase):
conn.firewall_driver.setattr('setup_basic_filtering', fake_none)
conn.firewall_driver.setattr('prepare_instance_filter', fake_none)
- network = db.project_get_networks(context.get_admin_context(),
- self.project.id)[0]
- ip_dict = {'ip': self.test_ip,
- 'netmask': network['netmask'],
- 'enabled': '1'}
- mapping = {'label': network['label'],
- 'gateway': network['gateway'],
- 'mac': instance['mac_address'],
- 'dns': [network['dns']],
- 'ips': [ip_dict]}
- network_info = [(network, mapping)]
+ network_info = _create_network_info()
try:
conn.spawn(instance, network_info)
@@ -830,6 +814,7 @@ class IptablesFirewallTestCase(test.TestCase):
"""setup_basic_rules in nwfilter calls this."""
pass
self.fake_libvirt_connection = FakeLibvirtConnection()
+ self.test_ip = '10.11.12.13'
self.fw = firewall.IptablesFirewallDriver(
get_connection=lambda: self.fake_libvirt_connection)
@@ -897,42 +882,13 @@ class IptablesFirewallTestCase(test.TestCase):
def test_static_filters(self):
instance_ref = self._create_instance_ref()
- ip = '10.11.12.13'
-
- network_ref = db.project_get_networks(self.context,
- 'fake',
- associate=True)[0]
- vif = {'address': '56:12:12:12:12:12',
- 'network_id': network_ref['id'],
- 'instance_id': instance_ref['id']}
- vif_ref = db.virtual_interface_create(self.context, vif)
-
- fixed_ip = {'address': ip,
- 'network_id': network_ref['id'],
- 'virtual_interface_id': vif_ref['id']}
-
src_instance_ref = self._create_instance_ref()
- src_instance_ip = '10.11.12.14'
- src_instance_vif = {'address': '56:12:12:12:12:13',
- 'network_id': network_ref['id'],
- 'instance_id': src_instance_ref['id']}
- src_instance_vif_ref = db.virtual_interface_create(self.context,
- src_instance_vif)
- src_instance_fixed_ip = {'address': src_instance_ip,
- 'network_id': network_ref['id'],
- 'virtual_interface_id':
- src_instance_vif_ref['id']}
+ src_ip = '10.11.12.14'
+ src_mac = '56:12:12:12:12:13'
+ _setup_networking(instance_ref['id'], self.test_ip, src_mac)
+ _setup_networking(src_instance_ref['id'], src_ip)
admin_ctxt = context.get_admin_context()
- db.fixed_ip_create(admin_ctxt, fixed_ip)
- db.fixed_ip_update(admin_ctxt, ip, {'allocated': True,
- 'instance_id': instance_ref['id']})
-
- db.fixed_ip_create(admin_ctxt, src_instance_fixed_ip)
- db.fixed_ip_update(admin_ctxt, src_instance_ip,
- {'allocated': True,
- 'instance_id': src_instance_ref['id']})
-
secgroup = db.security_group_create(admin_ctxt,
{'user_id': 'fake',
'project_id': 'fake',
@@ -1041,7 +997,7 @@ class IptablesFirewallTestCase(test.TestCase):
"ICMP Echo Request acceptance rule wasn't added")
regex = re.compile('-A .* -j ACCEPT -p tcp -m multiport '
- '--dports 80:81 -s %s' % (src_instance_ip,))
+ '--dports 80:81 -s %s' % (src_ip,))
self.assertTrue(len(filter(regex.match, self.out_rules)) > 0,
"TCP port 80/81 acceptance rule wasn't added")
@@ -1085,7 +1041,6 @@ class IptablesFirewallTestCase(test.TestCase):
self.assertEquals(ipv6_network_rules,
ipv6_rules_per_network * networks_count)
- @test.skip_test("skipping libvirt tests")
def test_do_refresh_security_group_rules(self):
instance_ref = self._create_instance_ref()
self.mox.StubOutWithMock(self.fw,
@@ -1096,7 +1051,6 @@ class IptablesFirewallTestCase(test.TestCase):
self.mox.ReplayAll()
self.fw.do_refresh_security_group_rules("fake")
- @test.skip_test("skip libvirt test project_get_network no longer exists")
def test_unfilter_instance_undefines_nwfilter(self):
# Skip if non-libvirt environment
if not self.lazy_load_library_exists():
@@ -1110,38 +1064,24 @@ class IptablesFirewallTestCase(test.TestCase):
self.fw.nwfilter._conn.nwfilterLookupByName =\
fakefilter.nwfilterLookupByName
instance_ref = self._create_instance_ref()
- inst_id = instance_ref['id']
- instance = db.instance_get(self.context, inst_id)
- ip = '10.11.12.13'
- network_ref = db.project_get_network(self.context, 'fake')
- fixed_ip = {'address': ip, 'network_id': network_ref['id']}
- db.fixed_ip_create(admin_ctxt, fixed_ip)
- db.fixed_ip_update(admin_ctxt, ip, {'allocated': True,
- 'instance_id': inst_id})
- self.fw.setup_basic_filtering(instance)
- self.fw.prepare_instance_filter(instance)
- self.fw.apply_instance_filter(instance)
+ _setup_networking(instance_ref['id'], self.test_ip)
+ self.fw.setup_basic_filtering(instance_ref)
+ self.fw.prepare_instance_filter(instance_ref)
+ self.fw.apply_instance_filter(instance_ref)
original_filter_count = len(fakefilter.filters)
- self.fw.unfilter_instance(instance)
+ self.fw.unfilter_instance(instance_ref)
# should undefine just the instance filter
self.assertEqual(original_filter_count - len(fakefilter.filters), 1)
db.instance_destroy(admin_ctxt, instance_ref['id'])
- @test.skip_test("skip libvirt test project_get_network no longer exists")
def test_provider_firewall_rules(self):
# setup basic instance data
instance_ref = self._create_instance_ref()
nw_info = _create_network_info(1)
- ip = '10.11.12.13'
- network_ref = db.project_get_network(self.context, 'fake')
- admin_ctxt = context.get_admin_context()
- fixed_ip = {'address': ip, 'network_id': network_ref['id']}
- db.fixed_ip_create(admin_ctxt, fixed_ip)
- db.fixed_ip_update(admin_ctxt, ip, {'allocated': True,
- 'instance_id': instance_ref['id']})
+ _setup_networking(instance_ref['id'], self.test_ip)
# FRAGILE: peeks at how the firewall names chains
chain_name = 'inst-%s' % instance_ref['id']
@@ -1153,6 +1093,7 @@ class IptablesFirewallTestCase(test.TestCase):
if rule.chain == 'provider']
self.assertEqual(0, len(rules))
+ admin_ctxt = context.get_admin_context()
# add a rule and send the update message, check for 1 rule
provider_fw0 = db.provider_fw_rule_create(admin_ctxt,
{'protocol': 'tcp',
@@ -1211,6 +1152,7 @@ class NWFilterTestCase(test.TestCase):
self.fake_libvirt_connection = Mock()
+ self.test_ip = '10.11.12.13'
self.fw = firewall.NWFilterFirewall(
lambda: self.fake_libvirt_connection)
@@ -1297,7 +1239,6 @@ class NWFilterTestCase(test.TestCase):
inst.update(params)
return db.instance_type_create(context, inst)['id']
- @test.skip_test('Skipping this test')
def test_creates_base_rule_first(self):
# These come pre-defined by libvirt
self.defined_filters = ['no-mac-spoofing',
@@ -1329,21 +1270,11 @@ class NWFilterTestCase(test.TestCase):
instance_ref = self._create_instance()
inst_id = instance_ref['id']
- ip = '10.11.12.13'
-
- #network_ref = db.project_get_networks(self.context, 'fake')[0]
- #fixed_ip = {'address': ip, 'network_id': network_ref['id']}
-
- #admin_ctxt = context.get_admin_context()
- #db.fixed_ip_create(admin_ctxt, fixed_ip)
- #db.fixed_ip_update(admin_ctxt, ip, {'allocated': True,
- # 'instance_id': inst_id})
-
- self._setup_networking(instance_ref['id'], ip=ip)
+ _setup_networking(instance_ref['id'], self.test_ip)
def _ensure_all_called():
instance_filter = 'nova-instance-%s-%s' % (instance_ref['name'],
- '00A0C914C829')
+ '561212121212')
secgroup_filter = 'nova-secgroup-%s' % self.security_group['id']
for required in [secgroup_filter, 'allow-dhcp-server',
'no-arp-spoofing', 'no-ip-spoofing',
@@ -1364,7 +1295,7 @@ class NWFilterTestCase(test.TestCase):
self.fw.apply_instance_filter(instance)
_ensure_all_called()
self.teardown_security_group()
- db.instance_destroy(admin_ctxt, instance_ref['id'])
+ db.instance_destroy(context.get_admin_context(), instance_ref['id'])
def test_create_network_filters(self):
instance_ref = self._create_instance()
@@ -1374,7 +1305,6 @@ class NWFilterTestCase(test.TestCase):
"fake")
self.assertEquals(len(result), 3)
- @test.skip_test("skip libvirt test project_get_network no longer exists")
def test_unfilter_instance_undefines_nwfilters(self):
admin_ctxt = context.get_admin_context()
@@ -1392,12 +1322,7 @@ class NWFilterTestCase(test.TestCase):
instance = db.instance_get(self.context, inst_id)
- ip = '10.11.12.13'
- network_ref = db.project_get_network(self.context, 'fake')
- fixed_ip = {'address': ip, 'network_id': network_ref['id']}
- db.fixed_ip_create(admin_ctxt, fixed_ip)
- db.fixed_ip_update(admin_ctxt, ip, {'allocated': True,
- 'instance_id': inst_id})
+ _setup_networking(instance_ref['id'], self.test_ip)
self.fw.setup_basic_filtering(instance)
self.fw.prepare_instance_filter(instance)
self.fw.apply_instance_filter(instance)
diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py
index 69d2deafe..a35caadf8 100644
--- a/nova/tests/test_quota.py
+++ b/nova/tests/test_quota.py
@@ -269,11 +269,10 @@ class QuotaTestCase(test.TestCase):
for volume_id in volume_ids:
db.volume_destroy(self.context, volume_id)
- @test.skip_test
def test_too_many_addresses(self):
address = '192.168.0.100'
db.floating_ip_create(context.get_admin_context(),
- {'address': address, 'host': FLAGS.host,
+ {'address': address,
'project_id': self.project.id})
self.assertRaises(quota.QuotaError,
self.network.allocate_floating_ip,
diff --git a/nova/tests/test_vmwareapi.py b/nova/tests/test_vmwareapi.py
index cbf7801cf..7313508a6 100644
--- a/nova/tests/test_vmwareapi.py
+++ b/nova/tests/test_vmwareapi.py
@@ -19,9 +19,6 @@
Test suite for VMWareAPI.
"""
-import stubout
-
-from nova import context
from nova import db
from nova import flags
from nova import test
@@ -41,51 +38,66 @@ FLAGS = flags.FLAGS
class VMWareAPIVMTestCase(test.TestCase):
"""Unit tests for Vmware API connection calls."""
- # NOTE(jkoelker): This is leaking stubs into the db module.
- # Commenting out until updated for multi-nic.
- #def setUp(self):
- # super(VMWareAPIVMTestCase, self).setUp()
- # self.flags(vmwareapi_host_ip='test_url',
- # vmwareapi_host_username='test_username',
- # vmwareapi_host_password='test_pass')
- # self.manager = manager.AuthManager()
- # self.user = self.manager.create_user('fake', 'fake', 'fake',
- # admin=True)
- # self.project = self.manager.create_project('fake', 'fake', 'fake')
- # self.network = utils.import_object(FLAGS.network_manager)
- # self.stubs = stubout.StubOutForTesting()
- # vmwareapi_fake.reset()
- # db_fakes.stub_out_db_instance_api(self.stubs)
- # stubs.set_stubs(self.stubs)
- # glance_stubs.stubout_glance_client(self.stubs,
- # glance_stubs.FakeGlance)
- # self.conn = vmwareapi_conn.get_connection(False)
-
- #def tearDown(self):
- # super(VMWareAPIVMTestCase, self).tearDown()
- # vmwareapi_fake.cleanup()
- # self.manager.delete_project(self.project)
- # self.manager.delete_user(self.user)
- # self.stubs.UnsetAll()
+ def setUp(self):
+ super(VMWareAPIVMTestCase, self).setUp()
+ self.flags(vmwareapi_host_ip='test_url',
+ vmwareapi_host_username='test_username',
+ vmwareapi_host_password='test_pass')
+ self.manager = manager.AuthManager()
+ self.user = self.manager.create_user('fake', 'fake', 'fake',
+ admin=True)
+ self.project = self.manager.create_project('fake', 'fake', 'fake')
+ self.network = utils.import_object(FLAGS.network_manager)
+ vmwareapi_fake.reset()
+ db_fakes.stub_out_db_instance_api(self.stubs)
+ stubs.set_stubs(self.stubs)
+ glance_stubs.stubout_glance_client(self.stubs)
+ self.conn = vmwareapi_conn.get_connection(False)
+ # NOTE(vish): none of the network plugging code is actually
+ # being tested
+ self.network_info = [({'bridge': 'fa0',
+ 'id': 0,
+ 'vlan': None,
+ 'bridge_interface': None,
+ 'injected': True},
+ {'broadcast': '192.168.0.255',
+ 'dns': ['192.168.0.1'],
+ 'gateway': '192.168.0.1',
+ 'gateway6': 'dead:beef::1',
+ 'ip6s': [{'enabled': '1',
+ 'ip': 'dead:beef::dcad:beff:feef:0',
+ 'netmask': '64'}],
+ 'ips': [{'enabled': '1',
+ 'ip': '192.168.0.100',
+ 'netmask': '255.255.255.0'}],
+ 'label': 'fake',
+ 'mac': 'DE:AD:BE:EF:00:00',
+ 'rxtx_cap': 3})]
+
+ def tearDown(self):
+ super(VMWareAPIVMTestCase, self).tearDown()
+ vmwareapi_fake.cleanup()
+ self.manager.delete_project(self.project)
+ self.manager.delete_user(self.user)
def _create_instance_in_the_db(self):
values = {'name': 1,
'id': 1,
'project_id': self.project.id,
'user_id': self.user.id,
- 'image_id': "1",
+ 'image_ref': "1",
'kernel_id': "1",
'ramdisk_id': "1",
+ 'mac_address': "de:ad:be:ef:be:ef",
'instance_type': 'm1.large',
- 'mac_address': 'aa:bb:cc:dd:ee:ff',
}
- self.instance = db.instance_create(values)
+ self.instance = db.instance_create(None, values)
def _create_vm(self):
"""Create and spawn the VM."""
self._create_instance_in_the_db()
self.type_data = db.instance_type_get_by_name(None, 'm1.large')
- self.conn.spawn(self.instance)
+ self.conn.spawn(self.instance, self.network_info)
self._check_vm_record()
def _check_vm_record(self):
@@ -129,24 +141,20 @@ class VMWareAPIVMTestCase(test.TestCase):
self.assertEquals(info["mem"], mem_kib)
self.assertEquals(info["num_cpu"], self.type_data['vcpus'])
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_list_instances(self):
instances = self.conn.list_instances()
self.assertEquals(len(instances), 0)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_list_instances_1(self):
self._create_vm()
instances = self.conn.list_instances()
self.assertEquals(len(instances), 1)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_spawn(self):
self._create_vm()
info = self.conn.get_info(1)
self._check_vm_info(info, power_state.RUNNING)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_snapshot(self):
self._create_vm()
info = self.conn.get_info(1)
@@ -155,27 +163,23 @@ class VMWareAPIVMTestCase(test.TestCase):
info = self.conn.get_info(1)
self._check_vm_info(info, power_state.RUNNING)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_snapshot_non_existent(self):
self._create_instance_in_the_db()
self.assertRaises(Exception, self.conn.snapshot, self.instance,
"Test-Snapshot")
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_reboot(self):
self._create_vm()
info = self.conn.get_info(1)
self._check_vm_info(info, power_state.RUNNING)
- self.conn.reboot(self.instance)
+ self.conn.reboot(self.instance, self.network_info)
info = self.conn.get_info(1)
self._check_vm_info(info, power_state.RUNNING)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_reboot_non_existent(self):
self._create_instance_in_the_db()
self.assertRaises(Exception, self.conn.reboot, self.instance)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_reboot_not_poweredon(self):
self._create_vm()
info = self.conn.get_info(1)
@@ -185,7 +189,6 @@ class VMWareAPIVMTestCase(test.TestCase):
self._check_vm_info(info, power_state.PAUSED)
self.assertRaises(Exception, self.conn.reboot, self.instance)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_suspend(self):
self._create_vm()
info = self.conn.get_info(1)
@@ -194,13 +197,11 @@ class VMWareAPIVMTestCase(test.TestCase):
info = self.conn.get_info(1)
self._check_vm_info(info, power_state.PAUSED)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_suspend_non_existent(self):
self._create_instance_in_the_db()
self.assertRaises(Exception, self.conn.suspend, self.instance,
self.dummy_callback_handler)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_resume(self):
self._create_vm()
info = self.conn.get_info(1)
@@ -212,13 +213,11 @@ class VMWareAPIVMTestCase(test.TestCase):
info = self.conn.get_info(1)
self._check_vm_info(info, power_state.RUNNING)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_resume_non_existent(self):
self._create_instance_in_the_db()
self.assertRaises(Exception, self.conn.resume, self.instance,
self.dummy_callback_handler)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_resume_not_suspended(self):
self._create_vm()
info = self.conn.get_info(1)
@@ -226,49 +225,41 @@ class VMWareAPIVMTestCase(test.TestCase):
self.assertRaises(Exception, self.conn.resume, self.instance,
self.dummy_callback_handler)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_get_info(self):
self._create_vm()
info = self.conn.get_info(1)
self._check_vm_info(info, power_state.RUNNING)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_destroy(self):
self._create_vm()
info = self.conn.get_info(1)
self._check_vm_info(info, power_state.RUNNING)
instances = self.conn.list_instances()
self.assertEquals(len(instances), 1)
- self.conn.destroy(self.instance)
+ self.conn.destroy(self.instance, self.network_info)
instances = self.conn.list_instances()
self.assertEquals(len(instances), 0)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_destroy_non_existent(self):
self._create_instance_in_the_db()
- self.assertEquals(self.conn.destroy(self.instance), None)
+ self.assertEquals(self.conn.destroy(self.instance, self.network_info),
+ None)
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_pause(self):
pass
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_unpause(self):
pass
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_diagnostics(self):
pass
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_get_console_output(self):
pass
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def test_get_ajax_console(self):
pass
- @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
def dummy_callback_handler(self, ret):
"""
Dummy callback function to be passed to suspend, resume, etc., calls.
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index 199a8bc52..8b3b5fa28 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -396,18 +396,22 @@ class XenAPIVMTestCase(test.TestCase):
def _test_spawn(self, image_ref, kernel_id, ramdisk_id,
instance_type_id="3", os_type="linux",
architecture="x86-64", instance_id=1,
- check_injection=False):
+ check_injection=False,
+ create_record=True):
stubs.stubout_loopingcall_start(self.stubs)
- values = {'id': instance_id,
- 'project_id': self.project.id,
- 'user_id': self.user.id,
- 'image_ref': image_ref,
- 'kernel_id': kernel_id,
- 'ramdisk_id': ramdisk_id,
- 'instance_type_id': instance_type_id,
- 'os_type': os_type,
- 'architecture': architecture}
- instance = db.instance_create(self.context, values)
+ if create_record:
+ values = {'id': instance_id,
+ 'project_id': self.project.id,
+ 'user_id': self.user.id,
+ 'image_ref': image_ref,
+ 'kernel_id': kernel_id,
+ 'ramdisk_id': ramdisk_id,
+ 'instance_type_id': instance_type_id,
+ 'os_type': os_type,
+ 'architecture': architecture}
+ instance = db.instance_create(self.context, values)
+ else:
+ instance = db.instance_get(self.context, instance_id)
network_info = [({'bridge': 'fa0', 'id': 0, 'injected': True},
{'broadcast': '192.168.0.255',
'dns': ['192.168.0.1'],
@@ -599,41 +603,38 @@ class XenAPIVMTestCase(test.TestCase):
# guest agent is detected
self.assertFalse(self._tee_executed)
- @test.skip_test("Never gets an address, not sure why")
def test_spawn_vlanmanager(self):
self.flags(xenapi_image_service='glance',
network_manager='nova.network.manager.VlanManager',
- network_driver='nova.network.xenapi_net',
vlan_interface='fake0')
def dummy(*args, **kwargs):
pass
- self.stubs.Set(VMOps, 'create_vifs', dummy)
+ self.stubs.Set(vmops.VMOps, 'create_vifs', dummy)
# Reset network table
xenapi_fake.reset_table('network')
# Instance id = 2 will use vlan network (see db/fakes.py)
ctxt = self.context.elevated()
- instance_ref = self._create_instance(2)
- network_bk = self.network
- # Ensure we use xenapi_net driver
- self.network = utils.import_object(FLAGS.network_manager)
+ instance = self._create_instance(2, False)
networks = self.network.db.network_get_all(ctxt)
for network in networks:
- self.network.set_network_host(ctxt, network['id'])
-
- self.network.allocate_for_instance(ctxt, instance_id=instance_ref.id,
- instance_type_id=1, project_id=self.project.id)
- self.network.setup_compute_network(ctxt, instance_ref.id)
+ self.network.set_network_host(ctxt, network)
+
+ self.network.allocate_for_instance(ctxt,
+ instance_id=2,
+ host=FLAGS.host,
+ vpn=None,
+ instance_type_id=1,
+ project_id=self.project.id)
self._test_spawn(glance_stubs.FakeGlance.IMAGE_MACHINE,
glance_stubs.FakeGlance.IMAGE_KERNEL,
glance_stubs.FakeGlance.IMAGE_RAMDISK,
- instance_id=instance_ref.id,
+ instance_id=2,
create_record=False)
# TODO(salvatore-orlando): a complete test here would require
# a check for making sure the bridge for the VM's VIF is
# consistent with bridge specified in nova db
- self.network = network_bk
def test_spawn_with_network_qos(self):
self._create_instance()
@@ -644,7 +645,7 @@ class XenAPIVMTestCase(test.TestCase):
str(3 * 1024))
def test_rescue(self):
- self.flags(xenapi_inject_image=False)
+ self.flags(flat_injected=False)
instance = self._create_instance()
conn = xenapi_conn.get_connection(False)
conn.rescue(instance, None, [])
@@ -663,7 +664,7 @@ class XenAPIVMTestCase(test.TestCase):
self.vm = None
self.stubs.UnsetAll()
- def _create_instance(self, instance_id=1):
+ def _create_instance(self, instance_id=1, spawn=True):
"""Creates and spawns a test instance."""
stubs.stubout_loopingcall_start(self.stubs)
values = {
@@ -691,7 +692,8 @@ class XenAPIVMTestCase(test.TestCase):
'label': 'fake',
'mac': 'DE:AD:BE:EF:00:00',
'rxtx_cap': 3})]
- self.conn.spawn(instance, network_info)
+ if spawn:
+ self.conn.spawn(instance, network_info)
return instance
diff --git a/nova/tests/vmwareapi/db_fakes.py b/nova/tests/vmwareapi/db_fakes.py
index d4eb87daf..afd672c7a 100644
--- a/nova/tests/vmwareapi/db_fakes.py
+++ b/nova/tests/vmwareapi/db_fakes.py
@@ -70,8 +70,8 @@ def stub_out_db_instance_api(stubs):
'launch_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),
'instance_type': values['instance_type'],
'memory_mb': type_data['memory_mb'],
- 'mac_address': values['mac_address'],
'vcpus': type_data['vcpus'],
+ 'mac_addresses': [{'address': values['mac_address']}],
'local_gb': type_data['local_gb'],
}
return FakeModel(base_options)
@@ -83,6 +83,8 @@ def stub_out_db_instance_api(stubs):
'bridge': 'vmnet0',
'netmask': '255.255.255.0',
'gateway': '10.10.10.1',
+ 'broadcast': '10.10.10.255',
+ 'dns1': 'fake',
'vlan': 100}
return FakeModel(fields)
@@ -90,7 +92,7 @@ def stub_out_db_instance_api(stubs):
"""Stubs out the db.instance_action_create method."""
pass
- def fake_instance_get_fixed_address(context, instance_id):
+ def fake_instance_get_fixed_addresses(context, instance_id):
"""Stubs out the db.instance_get_fixed_address method."""
return '10.10.10.10'
@@ -103,7 +105,7 @@ def stub_out_db_instance_api(stubs):
stubs.Set(db, 'instance_create', fake_instance_create)
stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance)
stubs.Set(db, 'instance_action_create', fake_instance_action_create)
- stubs.Set(db, 'instance_get_fixed_address',
- fake_instance_get_fixed_address)
+ stubs.Set(db, 'instance_get_fixed_addresses',
+ fake_instance_get_fixed_addresses)
stubs.Set(db, 'instance_type_get_all', fake_instance_type_get_all)
stubs.Set(db, 'instance_type_get_by_name', fake_instance_type_get_by_name)
diff --git a/nova/tests/vmwareapi/stubs.py b/nova/tests/vmwareapi/stubs.py
index a648efb16..0ed5e9b68 100644
--- a/nova/tests/vmwareapi/stubs.py
+++ b/nova/tests/vmwareapi/stubs.py
@@ -22,6 +22,8 @@ Stubouts for the test suite
from nova.virt import vmwareapi_conn
from nova.virt.vmwareapi import fake
from nova.virt.vmwareapi import vmware_images
+from nova.virt.vmwareapi import vmops
+from nova.virt.vmwareapi import network_utils
def fake_get_vim_object(arg):
@@ -36,11 +38,16 @@ def fake_is_vim_object(arg, module):
def set_stubs(stubs):
"""Set the stubs."""
+ stubs.Set(vmops.VMWareVMOps, 'plug_vifs', fake.fake_plug_vifs)
+ stubs.Set(network_utils, 'get_network_with_the_name',
+ fake.fake_get_network)
stubs.Set(vmware_images, 'fetch_image', fake.fake_fetch_image)
stubs.Set(vmware_images, 'get_vmdk_size_and_properties',
fake.fake_get_vmdk_size_and_properties)
stubs.Set(vmware_images, 'upload_image', fake.fake_upload_image)
stubs.Set(vmwareapi_conn.VMWareAPISession, "_get_vim_object",
fake_get_vim_object)
+ stubs.Set(vmwareapi_conn.VMWareAPISession, "_get_vim_object",
+ fake_get_vim_object)
stubs.Set(vmwareapi_conn.VMWareAPISession, "_is_vim_object",
fake_is_vim_object)
diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
index 96f9c41f9..c27e92feb 100644
--- a/nova/virt/libvirt/connection.py
+++ b/nova/virt/libvirt/connection.py
@@ -351,7 +351,7 @@ class LibvirtConnection(driver.ComputeDriver):
virt_dom = self._lookup_by_name(instance_name)
mount_device = mountpoint.rpartition("/")[2]
(type, protocol, name) = \
- self._get_volume_device_info(vol['device_path'])
+ self._get_volume_device_info(device_path)
if type == 'block':
xml = """<disk type='block'>
<driver name='qemu' type='raw'/>
@@ -364,9 +364,6 @@ class LibvirtConnection(driver.ComputeDriver):
<source protocol='%s' name='%s'/>
<target dev='%s' bus='virtio'/>
</disk>""" % (protocol, name, mount_device)
- else:
- raise exception.InvalidDevicePath(path=device_path)
-
virt_dom.attachDevice(xml)
def _get_disk_xml(self, xml, device):
@@ -955,7 +952,6 @@ class LibvirtConnection(driver.ComputeDriver):
return True
return False
- @exception.wrap_exception
def _get_volume_device_info(self, device_path):
if device_path.startswith('/dev/'):
return ('block', None, None)
diff --git a/nova/virt/libvirt/netutils.py b/nova/virt/libvirt/netutils.py
index 041eacb2d..a8e88fc07 100644
--- a/nova/virt/libvirt/netutils.py
+++ b/nova/virt/libvirt/netutils.py
@@ -25,6 +25,7 @@ import netaddr
from nova import context
from nova import db
+from nova import exception
from nova import flags
from nova import ipv6
from nova import utils
@@ -55,10 +56,12 @@ def get_network_info(instance):
# we should cache network_info
admin_context = context.get_admin_context()
- fixed_ips = db.fixed_ip_get_by_instance(admin_context, instance['id'])
+ try:
+ fixed_ips = db.fixed_ip_get_by_instance(admin_context, instance['id'])
+ except exception.FixedIpNotFoundForInstance:
+ fixed_ips = []
+
vifs = db.virtual_interface_get_by_instance(admin_context, instance['id'])
- networks = db.network_get_all_by_instance(admin_context,
- instance['id'])
flavor = db.instance_type_get(admin_context,
instance['instance_type_id'])
network_info = []
@@ -89,6 +92,7 @@ def get_network_info(instance):
'label': network['label'],
'gateway': network['gateway'],
'broadcast': network['broadcast'],
+ 'dhcp_server': network['gateway'],
'mac': vif['address'],
'rxtx_cap': flavor['rxtx_cap'],
'dns': [],
diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py
index 24d45d1a7..eef582fac 100644
--- a/nova/virt/libvirt/vif.py
+++ b/nova/virt/libvirt/vif.py
@@ -126,7 +126,7 @@ class LibvirtOpenVswitchDriver(VIFDriver):
dev = "tap-%s" % vif_id
try:
utils.execute('sudo', 'ovs-vsctl', 'del-port',
- FLAGS.flat_network_bridge, dev)
+ network['bridge'], dev)
utils.execute('sudo', 'ip', 'link', 'delete', dev)
except:
LOG.warning(_("Failed while unplugging vif of instance '%s'"),
diff --git a/nova/virt/vmwareapi/fake.py b/nova/virt/vmwareapi/fake.py
index 7370684bd..4c62d18bb 100644
--- a/nova/virt/vmwareapi/fake.py
+++ b/nova/virt/vmwareapi/fake.py
@@ -402,6 +402,16 @@ def _remove_file(file_path):
lst_files.remove(file)
+def fake_plug_vifs(*args, **kwargs):
+ """Fakes plugging vifs."""
+ pass
+
+
+def fake_get_network(*args, **kwargs):
+ """Fake get network."""
+ return [{'type': 'fake'}]
+
+
def fake_fetch_image(image, instance, **kwargs):
"""Fakes fetch image call. Just adds a reference to the db for the file."""
ds_name = kwargs.get("datastore_name")
diff --git a/nova/virt/vmwareapi/network_utils.py b/nova/virt/vmwareapi/network_utils.py
index 08e3bf0b1..ec3b93fe7 100644
--- a/nova/virt/vmwareapi/network_utils.py
+++ b/nova/virt/vmwareapi/network_utils.py
@@ -46,6 +46,7 @@ def get_network_with_the_name(session, network_name="vmnet0"):
"get_properties_for_a_collection_of_objects",
"Network", vm_networks, ["summary.name"])
network_obj = {}
+ LOG.warn(vm_networks)
for network in vm_networks:
# Get network properties
if network._type == 'DistributedVirtualPortgroup':
diff --git a/nova/virt/vmwareapi/vm_util.py b/nova/virt/vmwareapi/vm_util.py
index 55578dd3c..82b5f7214 100644
--- a/nova/virt/vmwareapi/vm_util.py
+++ b/nova/virt/vmwareapi/vm_util.py
@@ -110,7 +110,8 @@ def create_network_spec(client_factory, network_name, mac_address,
# ephemeral. Invalid configuration if set to static and the NIC does
# not come up on boot if set to dynamic.
backing = None
- if (network_ref['type'] == "DistributedVirtualPortgroup"):
+ if (network_ref and
+ network_ref['type'] == "DistributedVirtualPortgroup"):
backing_name = \
'ns0:VirtualEthernetCardDistributedVirtualPortBackingInfo'
backing = \
diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py
index 7e7d2dac3..1ee8fa1c0 100644
--- a/nova/virt/vmwareapi/vmops.py
+++ b/nova/virt/vmwareapi/vmops.py
@@ -734,13 +734,14 @@ class VMWareVMOps(object):
net_mask = network["netmask"]
gateway = network["gateway"]
broadcast = network["broadcast"]
- dns = network["dns"]
+ # TODO(vish): add support for dns2
+ dns = network["dns1"]
addresses = db.instance_get_fixed_addresses(admin_context,
instance['id'])
ip_addr = addresses[0] if addresses else None
- machine_id_chanfge_spec = \
+ machine_id_change_spec = \
vm_util.get_machine_id_change_spec(client_factory, mac_address,
ip_addr, net_mask, gateway,
broadcast, dns)
@@ -750,7 +751,7 @@ class VMWareVMOps(object):
'ip_addr': ip_addr}))
reconfig_task = self._session._call_method(self._session._get_vim(),
"ReconfigVM_Task", vm_ref,
- spec=machine_id_chanfge_spec)
+ spec=machine_id_change_spec)
self._session._wait_for_task(instance.id, reconfig_task)
LOG.debug(_("Reconfigured VM instance %(name)s to set the machine id "
"with ip - %(ip_addr)s") %
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 0473abb97..77efe1bf0 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -255,7 +255,7 @@ class VMOps(object):
userdevice += 1
# Alter the image before VM start for, e.g. network injection
- if FLAGS.xenapi_inject_image:
+ if FLAGS.flat_injected:
VMHelper.preconfigure_instance(self._session, instance,
first_vdi_ref, network_info)
@@ -471,7 +471,7 @@ class VMOps(object):
self._session, instance, template_vdi_uuids, image_id)
finally:
if template_vm_ref:
- self._destroy(instance, template_vm_ref, None,
+ self._destroy(instance, template_vm_ref,
shutdown=False, destroy_kernel_ramdisk=False)
logging.debug(_("Finished snapshot and upload for VM %s"), instance)
@@ -853,7 +853,7 @@ class VMOps(object):
vm_ref = VMHelper.lookup(self._session, instance.name)
return self._destroy(instance, vm_ref, network_info, shutdown=True)
- def _destroy(self, instance, vm_ref, network_info, shutdown=True,
+ def _destroy(self, instance, vm_ref, network_info=None, shutdown=True,
destroy_kernel_ramdisk=True):
"""Destroys VM instance by performing:
@@ -1092,7 +1092,7 @@ class VMOps(object):
LOG.debug(_('Created VIF %(vif_ref)s for VM %(vm_ref)s,'
' network %(network_ref)s.') % locals())
- def plug_vifs(instance, network_info):
+ def plug_vifs(self, instance, network_info):
"""Set up VIF networking on the host."""
for (network, mapping) in network_info:
self.vif_driver.plug(self._session, instance, network, mapping)
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index 7c355a55b..cddb8203b 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -112,22 +112,15 @@ flags.DEFINE_integer('xenapi_vhd_coalesce_max_attempts',
5,
'Max number of times to poll for VHD to coalesce.'
' Used only if connection_type=xenapi.')
-flags.DEFINE_bool('xenapi_inject_image',
- True,
- 'Specifies whether an attempt to inject network/key'
- ' data into the disk image should be made.'
- ' Used only if connection_type=xenapi.')
flags.DEFINE_string('xenapi_agent_path',
'usr/sbin/xe-update-networking',
'Specifies the path in which the xenapi guest agent'
' should be located. If the agent is present,'
' network configuration is not injected into the image'
' Used only if connection_type=xenapi.'
- ' and xenapi_inject_image=True')
-
+ ' and flat_injected=True')
flags.DEFINE_string('xenapi_sr_base_path', '/var/run/sr-mount',
'Base path to the storage repository')
-
flags.DEFINE_string('target_host',
None,
'iSCSI Target Host')