from django.utils import timezone
 
 import json
-import re
 from datetime import timedelta
 
-from dashboard.exceptions import InvalidHostnameException
 from booking.models import Booking
 from account.models import UserProfile, Lab, LabStatus, VlanManager, PublicNetwork
 from resource_inventory.models import (
-    Host,
-    HostProfile,
+    ResourceTemplate,
+    ResourceProfile,
+    ResourceConfiguration,
     InterfaceProfile,
+    InterfaceConfiguration,
+    Server,
     DiskProfile,
     CpuProfile,
     Opsys,
     OPNFVRole,
     RamProfile,
     Network,
-    GenericResourceBundle,
-    GenericResource,
-    GenericHost,
-    ConfigBundle,
-    GenericInterface,
-    HostConfiguration,
-    OPNFVConfig,
-    NetworkConnection,
-    HostOPNFVConfig
 )
 from resource_inventory.resource_manager import ResourceManager
 
                  project="my_project", collaborators=[],
                  topology={}, installer=None, scenario=None):
 
-    grb, host_set = make_grb(topology, owner, lab)
-    config_bundle, opnfv_bundle = make_config_bundle(grb, owner, topology, host_set, installer, scenario)
-    resource = ResourceManager.getInstance().convertResourceBundle(grb, config=config_bundle)
+    resource_template = make_resource_template()
+    resource = ResourceManager.getInstance().convertResourceBundle(resource_template)
     if not resource:
         raise Exception("Resource not created")
 
     return Booking.objects.create(
         resource=resource,
-        config_bundle=config_bundle,
         start=start,
         end=end,
         owner=owner,
         purpose=purpose,
         project=project,
         lab=lab,
-        opnfv_config=opnfv_bundle
     )
 
 
-def make_config_bundle(grb, owner, topology={}, host_set={},
-                       installer=None, scenario=None):
-    cb = ConfigBundle.objects.create(
-        owner=owner,
-        name="config bundle " + str(ConfigBundle.objects.count()),
-        description="cb generated by make_config_bundle() method",
-        bundle=grb
-    )
-
-    scen = scenario or Scenario.objects.first() or make_scenario()
-    inst = installer or Installer.objects.first() or make_installer([scen])
-
-    opnfv_config = OPNFVConfig.objects.create(
-        installer=inst,
-        scenario=scen,
-        bundle=cb
-    )
-
-    # generate host configurations based on topology and host set
-    for hostname, host_info in topology.items():
-        host_config = HostConfiguration.objects.create(
-            host=host_set[hostname],
-            image=host_info["image"],
-            bundle=cb,
-            is_head_node=host_info['role'].name.lower() == "jumphost"
-        )
-        HostOPNFVConfig.objects.create(
-            role=host_info["role"],
-            host_config=host_config,
-            opnfv_config=opnfv_config
-        )
-    return cb, opnfv_config
-
-
 def make_network(name, lab, grb, public):
     network = Network(name=name, bundle=grb, is_public=public)
     if public:
     return network
 
 
-def make_grb(topology, owner, lab):
-
-    grb = GenericResourceBundle.objects.create(
-        owner=owner,
-        lab=lab,
-        name="Generic ResourceBundle " + str(GenericResourceBundle.objects.count()),
-        description="grb generated by make_grb() method"
-    )
-
-    networks = {}
-    host_set = {}
-
-    for hostname, info in topology.items():
-        host_profile = info["type"]
+def make_resource_template(owner=None, lab=None, name="Test Template"):
+    if owner is None:
+        owner = make_user(username="template_owner")
+    if lab is None:
+        lab = make_lab(name="template_lab")
+    rt = ResourceTemplate.objects.create(name=name, owner=owner, lab=lab, public=True)
+    config = make_resource_config(rt)
+    make_interface_config(config)
+    return rt
 
-        # need to construct host from hostname and type
-        generic_host = make_generic_host(grb, host_profile, hostname)
-        host_set[hostname] = generic_host
 
-        # set up networks
-        nets = info["nets"]
-        for interface_index, interface_profile in enumerate(host_profile.interfaceprofile.all()):
-            generic_interface = GenericInterface.objects.create(host=generic_host, profile=interface_profile)
-            netconfig = nets[interface_index]
-            for network_info in netconfig:
-                network_name = network_info["name"]
-                if network_name not in networks:
-                    networks[network_name] = make_network(network_name, lab, grb, network_info['public'])
+def make_resource_config(template, profile=None, image=None):
+    if profile is None:
+        profile = make_resource_profile(lab=template.lab)
 
-                generic_interface.connections.add(NetworkConnection.objects.create(
-                    network=networks[network_name],
-                    vlan_is_tagged=network_info["tagged"]
-                ))
+    if image is None:
+        image = make_image(profile)
 
-    return grb, host_set
+    return ResourceConfiguration.objects.create(profile=profile, image=image, template=template)
 
 
-def make_generic_host(grb, host_profile, hostname):
-    if not re.match(r"(?=^.{1,253}$)(^([A-Za-z0-9-_]{1,62}\.)*[A-Za-z0-9-_]{1,63})$", hostname):
-        raise InvalidHostnameException("Hostname must comply to RFC 952 and all extensions")
-    gresource = GenericResource.objects.create(bundle=grb, name=hostname)
+def make_interface_config(resource_config):
+    # lets just grab one of the iface profiles from the related host
+    iface_profile = resource_config.profile.interfaceprofile.all()[0]
 
-    return GenericHost.objects.create(resource=gresource, profile=host_profile)
+    # not adding any connections here
+    return InterfaceConfiguration.objects.create(profile=iface_profile, resource_config=resource_config)
 
 
 def make_user(is_superuser=False, username="testuser",
 """
 
 
-def make_complete_host_profile(lab, name="test_hostprofile"):
-    host_profile = make_host_profile(lab, name=name)
-    make_disk_profile(host_profile, 500, name=name)
-    make_cpu_profile(host_profile)
-    make_interface_profile(host_profile, name=name)
-    make_ram_profile(host_profile)
-
-    return host_profile
-
-
-def make_host_profile(lab, host_type=0, name="test hostprofile"):
-    host_profile = HostProfile.objects.create(
-        host_type=host_type,
+def make_resource_profile(lab, name="test_hostprofile"):
+    resource_profile = ResourceProfile.objects.create(
         name=name,
-        description='test hostprofile instance'
+        description='test resourceprofile instance'
     )
-    host_profile.labs.add(lab)
-
-    return host_profile
-
-
-def make_ram_profile(host, channels=4, amount=256):
-    return RamProfile.objects.create(
-        host=host,
-        amount=amount,
-        channels=channels
+    resource_profile.labs.add(lab)
+
+    RamProfile.objects.create(host=resource_profile, amount=8, channels=2)
+    CpuProfile.objects.create(cores=4, architecture="x86_64", cpus=1, host=resource_profile)
+    DiskProfile.objects.create(
+        name="test disk profile",
+        size=256,
+        media_type="SSD",
+        host=resource_profile
     )
 
-
-def make_disk_profile(hostprofile, size=0, media_type="SSD",
-                      name="test diskprofile", rotation=0,
-                      interface="sata"):
-    return DiskProfile.objects.create(
-        name=name,
-        size=size,
-        media_type=media_type,
-        host=hostprofile,
-        rotation=rotation,
-        interface=interface
+    InterfaceProfile.objects.create(
+        host=resource_profile,
+        name="test interface profile",
+        speed=1000,
+        nic_type="pcie"
     )
 
+    return resource_profile
 
-def make_cpu_profile(hostprofile,
-                     cores=4,
-                     architecture="x86_64",
-                     cpus=4,):
-    return CpuProfile.objects.create(
-        cores=cores,
-        architecture=architecture,
-        cpus=cpus,
-        host=hostprofile,
-        cflags=''
-    )
 
+def make_image(resource_profile, lab=None, lab_id="4", owner=None, os=None,
+               public=True, name="default image", description="default image"):
+    if lab is None:
+        lab = make_lab()
 
-def make_interface_profile(hostprofile,
-                           speed=1000,
-                           name="test interface profile",
-                           nic_type="pcie"):
-    return InterfaceProfile.objects.create(
-        host=hostprofile,
-        name=name,
-        speed=speed,
-        nic_type=nic_type
-    )
+    if owner is None:
+        owner = make_user()
 
+    if os is None:
+        os = make_os()
 
-def make_image(lab, lab_id, owner, os, host_profile,
-               public=True, name="default image", description="default image"):
     return Image.objects.create(
         from_lab=lab,
         lab_id=lab_id,
         os=os,
-        host_type=host_profile,
+        host_type=resource_profile,
         public=public,
         name=name,
         description=description
     return os
 
 
-def make_host(host_profile, lab, labid="test_host", name="test_host",
-              booked=False, working=True, config=None, template=None,
-              bundle=None, model="Model 1", vendor="ACME"):
-    return Host.objects.create(
+def make_server(host_profile, lab, labid="test_host", name="test_host",
+                booked=False, working=True, config=None, template=None,
+                bundle=None, model="Model 1", vendor="ACME"):
+    return Server.objects.create(
         lab=lab,
         profile=host_profile,
         name=name,