Merge "nsb_setup: parametrize docker image"
[yardstick.git] / yardstick / benchmark / contexts / model.py
index d3c03e1..a55c11f 100644 (file)
@@ -14,8 +14,12 @@ from __future__ import absolute_import
 
 import six
 import logging
+
+from collections import Mapping
 from six.moves import range
 
+from yardstick.common import constants as consts
+
 
 LOG = logging.getLogger(__name__)
 
@@ -130,11 +134,28 @@ class Network(Object):
             if self.gateway_ip is None:
                 self.gateway_ip = "null"
 
-        if "external_network" in attrs:
-            self.router = Router("router", self.name,
-                                 context, attrs["external_network"])
-
-        Network.list.append(self)
+        self.net_flags = attrs.get('net_flags', {})
+        if self.is_existing():
+            self.subnet = attrs.get('subnet')
+            if not self.subnet:
+                raise Warning('No subnet set in existing netwrok!')
+        else:
+            if "external_network" in attrs:
+                self.router = Router("router", self.name,
+                                     context, attrs["external_network"])
+            Network.list.append(self)
+
+    def is_existing(self):
+        net_is_existing = self.net_flags.get(consts.IS_EXISTING)
+        if net_is_existing and not isinstance(net_is_existing, bool):
+            raise SyntaxError('Network flags should be bool type!')
+        return net_is_existing
+
+    def is_public(self):
+        net_is_public = self.net_flags.get(consts.IS_PUBLIC)
+        if net_is_public and not isinstance(net_is_public, bool):
+            raise SyntaxError('Network flags should be bool type!')
+        return net_is_public
 
     def has_route_to(self, network_name):
         """determines if this network has a route to the named network"""
@@ -241,6 +262,26 @@ class Server(Object):     # pragma: no cover
 
         Server.list.append(self)
 
+    def override_ip(self, network_name, port):
+        def find_port_overrides():
+            for p in ports:
+                # p can be string or dict
+                # we can't just use p[port['port'] in case p is a string
+                # and port['port'] is an int?
+                if isinstance(p, Mapping):
+                    g = p.get(port['port'])
+                    # filter out empty dicts
+                    if g:
+                        yield g
+
+        ports = self.network_ports.get(network_name, [])
+        intf = self.interfaces[port['port']]
+        for override in find_port_overrides():
+            intf['local_ip'] = override.get('local_ip', intf['local_ip'])
+            intf['netmask'] = override.get('netmask', intf['netmask'])
+            # only use the first value
+            break
+
     @property
     def image(self):
         """returns a server's image name"""
@@ -270,16 +311,23 @@ class Server(Object):     # pragma: no cover
                     continue
                 else:
                     if isinstance(ports, six.string_types):
-                        if ports.startswith('-'):
-                            LOG.warning("possible YAML error, port name starts with - '%s", ports)
-                        ports = [ports]
+                        # because strings are iterable we have to check specifically
+                        raise SyntaxError("network_port must be a list '{}'".format(ports))
+                    # convert port subdicts into their just port name
+                    # port subdicts are used to override Heat IP address,
+                    # but we just need the port name
+                    # we allow duplicates here and let Heat raise the error
+                    ports = [next(iter(p)) if isinstance(p, dict) else p for p in ports]
             # otherwise add a port for every network with port name as network name
             else:
                 ports = [network.name]
+            net_flags = network.net_flags
             for port in ports:
                 port_name = "{0}-{1}-port".format(server_name, port)
-                self.ports.setdefault(network.name, []).append(
-                    {"stack_name": port_name, "port": port})
+                port_info = {"stack_name": port_name, "port": port}
+                if net_flags:
+                    port_info['net_flags'] = net_flags
+                self.ports.setdefault(network.name, []).append(port_info)
                 # we can't use secgroups if port_security_enabled is False
                 if network.port_security_enabled is False:
                     sec_group_id = None
@@ -288,11 +336,14 @@ class Server(Object):     # pragma: no cover
                     sec_group_id = self.secgroup_name
                 # don't refactor to pass in network object, that causes JSON
                 # circular ref encode errors
-                template.add_port(port_name, network.stack_name, network.subnet_stack_name,
-                                  network.vnic_type, sec_group_id=sec_group_id,
+                template.add_port(port_name, network,
+                                  sec_group_id=sec_group_id,
                                   provider=network.provider,
                                   allowed_address_pairs=network.allowed_address_pairs)
-                port_name_list.append(port_name)
+                if network.is_public():
+                    port_name_list.insert(0, port_name)
+                else:
+                    port_name_list.append(port_name)
 
                 if self.floating_ip:
                     external_network = self.floating_ip["external_network"]