Merge "Add tenant network creation to account creation script"
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index 472e86e..892e051 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -83,6 +83,7 @@
 [OPTIONS] <accounts_file.yaml> -h``.
 """
 import argparse
+import netaddr
 import os
 
 from oslo_log import log as logging
@@ -91,6 +92,7 @@
 from tempest import config
 from tempest import exceptions
 from tempest.services.identity.v2.json import identity_client
+from tempest.services.network.json import network_client
 import tempest_lib.auth
 from tempest_lib.common.utils import data_utils
 import tempest_lib.exceptions
@@ -105,7 +107,7 @@
     LOG = logging.getLogger(__name__)
 
 
-def keystone_admin(opts):
+def get_admin_clients(opts):
     _creds = tempest_lib.auth.KeystoneV2Credentials(
         username=opts.os_username,
         password=opts.os_password,
@@ -126,18 +128,28 @@
         'build_interval': CONF.compute.build_interval,
         'build_timeout': CONF.compute.build_timeout
     }
-    return identity_client.IdentityClientJSON(
+    identity_admin = identity_client.IdentityClientJSON(
         _auth,
         CONF.identity.catalog_type,
         CONF.identity.region,
         endpoint_type='adminURL',
         **params
     )
+    network_admin = None
+    if (CONF.service_available.neutron and
+        CONF.auth.create_isolated_networks):
+        network_admin = network_client.NetworkClientJSON(
+            _auth,
+            CONF.network.catalog_type,
+            CONF.network.region or CONF.identity.region,
+            endpoint_type='adminURL',
+            **params)
+    return identity_admin, network_admin
 
 
 def create_resources(opts, resources):
-    admin = keystone_admin(opts)
-    roles = admin.list_roles()
+    identity_admin, network_admin = get_admin_clients(opts)
+    roles = identity_admin.list_roles()
     for u in resources['users']:
         u['role_ids'] = []
         for r in u.get('roles', ()):
@@ -148,24 +160,24 @@
                 raise exceptions.TempestException(
                     "Role: %s - doesn't exist" % r
                 )
-    existing = [x['name'] for x in admin.list_tenants()]
+    existing = [x['name'] for x in identity_admin.list_tenants()]
     for tenant in resources['tenants']:
         if tenant not in existing:
-            admin.create_tenant(tenant)
+            identity_admin.create_tenant(tenant)
         else:
             LOG.warn("Tenant '%s' already exists in this environment" % tenant)
     LOG.info('Tenants created')
     for u in resources['users']:
         try:
-            tenant = admin.get_tenant_by_name(u['tenant'])
+            tenant = identity_admin.get_tenant_by_name(u['tenant'])
         except tempest_lib.exceptions.NotFound:
             LOG.error("Tenant: %s - not found" % u['tenant'])
             continue
         while True:
             try:
-                admin.get_user_by_username(tenant['id'], u['name'])
+                identity_admin.get_user_by_username(tenant['id'], u['name'])
             except tempest_lib.exceptions.NotFound:
-                admin.create_user(
+                identity_admin.create_user(
                     u['name'], u['pass'], tenant['id'],
                     "%s@%s" % (u['name'], tenant['id']),
                     enabled=True)
@@ -176,21 +188,29 @@
                 u['name'] = random_user_name(opts.tag, u['prefix'])
 
     LOG.info('Users created')
+    if network_admin:
+        for u in resources['users']:
+            tenant = identity_admin.get_tenant_by_name(u['tenant'])
+            network_name = create_network_resources(network_admin,
+                                                    tenant['id'],
+                                                    u['name'])
+            u['network'] = network_name
+        LOG.info('Networks created')
     for u in resources['users']:
         try:
-            tenant = admin.get_tenant_by_name(u['tenant'])
+            tenant = identity_admin.get_tenant_by_name(u['tenant'])
         except tempest_lib.exceptions.NotFound:
             LOG.error("Tenant: %s - not found" % u['tenant'])
             continue
         try:
-            user = admin.get_user_by_username(tenant['id'],
-                                              u['name'])
+            user = identity_admin.get_user_by_username(tenant['id'],
+                                                       u['name'])
         except tempest_lib.exceptions.NotFound:
             LOG.error("User: %s - not found" % u['user'])
             continue
         for r in u['role_ids']:
             try:
-                admin.assign_user_role(tenant['id'], user['id'], r)
+                identity_admin.assign_user_role(tenant['id'], user['id'], r)
             except tempest_lib.exceptions.Conflict:
                 # don't care if it's already assigned
                 pass
@@ -198,6 +218,57 @@
     LOG.info('Resources deployed successfully!')
 
 
+def create_network_resources(network_admin_client, tenant_id, name):
+
+    def _create_network(name):
+        resp_body = network_admin_client.create_network(
+            name=name, tenant_id=tenant_id)
+        return resp_body['network']
+
+    def _create_subnet(subnet_name, network_id):
+        base_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
+        mask_bits = CONF.network.tenant_network_mask_bits
+        for subnet_cidr in base_cidr.subnet(mask_bits):
+            try:
+                resp_body = network_admin_client.\
+                    create_subnet(
+                        network_id=network_id, cidr=str(subnet_cidr),
+                        name=subnet_name,
+                        tenant_id=tenant_id,
+                        enable_dhcp=True,
+                        ip_version=4)
+                break
+            except tempest_lib.exceptions.BadRequest as e:
+                if 'overlaps with another subnet' not in str(e):
+                    raise
+        else:
+            message = 'Available CIDR for subnet creation could not be found'
+            raise Exception(message)
+        return resp_body['subnet']
+
+    def _create_router(router_name):
+        external_net_id = dict(
+            network_id=CONF.network.public_network_id)
+        resp_body = network_admin_client.create_router(
+            router_name,
+            external_gateway_info=external_net_id,
+            tenant_id=tenant_id)
+        return resp_body['router']
+
+    def _add_router_interface(router_id, subnet_id):
+        network_admin_client.add_router_interface_with_subnet_id(
+            router_id, subnet_id)
+
+    network_name = name + "-network"
+    network = _create_network(network_name)
+    subnet_name = name + "-subnet"
+    subnet = _create_subnet(subnet_name, network['id'])
+    router_name = name + "-router"
+    router = _create_router(router_name)
+    _add_router_interface(router['id'], subnet['id'])
+    return network_name
+
+
 def random_user_name(tag, prefix):
     if tag:
         return data_utils.rand_name('-'.join((tag, prefix)))
@@ -253,12 +324,15 @@
 def dump_accounts(opts, resources):
     accounts = []
     for user in resources['users']:
-        accounts.append({
+        account = {
             'username': user['name'],
             'tenant_name': user['tenant'],
             'password': user['pass'],
             'roles': user['roles']
-        })
+        }
+        if 'network' in user:
+            account['resources'] = {'network': user['network']}
+        accounts.append(account)
     if os.path.exists(opts.accounts):
         os.rename(opts.accounts, '.'.join((opts.accounts, 'bak')))
     with open(opts.accounts, 'w') as f: