def AddNetworkPort(self, port_name, dockingnetwork_obj,
                       attachingsubnet_obj):
        '''Creates a network port, docks it on a network, attaches a subnet IP, then adds it to the 
        virtual infrastructure'''
        # Ensure the docking network and attaching subnet exist
        netkey = "Network_" + dockingnetwork_obj.name
        subnetkey = "Subnet_" + attachingsubnet_obj.name
        if netkey in self.resources.keys():
            pass
        else:
            raise NameError("No network named %s to attach to!" %
                            dockingnetwork_obj.name)
        if subnetkey in self.resources.keys():
            pass
        else:
            raise NameError("No subnet named %s to attach to!" %
                            attachingsubnet_obj.name)
        # Create port object and key, then add dock and attachment
        port_object = NetworkPort(port_name, dockingnetwork_obj,
                                  attachingsubnet_obj)
        portkey = port_object.type + "_" + port_object.name
        # Add to infrastructure
        if portkey in self.resources.keys():
            prompt = "An object of this type and name already exists in your environment, adding it\
again will erase the old object! Are you sure you want to overwrite the old object? (y/n): "

            usr_inpt = raw_input(prompt)
            response = sT.ResponseLoop(usr_inpt, "[yn]", prompt)
            if response == "y":
                self.resources[portkey] = port_object
            else:
                pass
        else:
            self.resources[portkey] = port_object
    def AddRouterInterface(self, interface_name, docking_router_object,
                           attaching_subnet_object):
        '''Creates a router interface, attaches a subnet to it, and adds it to the pool of 
        resources'''
        # Ensure the docking router and attaching subnet exist
        routerkey = "Router_" + docking_router_object.name
        subnetkey = "Subnet_" + attaching_subnet_object.name
        if routerkey in self.resources.keys():
            pass
        else:
            raise NameError("No router named %s to attach to!" %
                            docking_router_object.name)
        if subnetkey in self.resources.keys():
            pass
        else:
            raise NameError("No subnet named %s to attach to router!" %
                            attaching_subnet_object.name)
        # Create interface object and key
        interface_object = RouterInterface(interface_name,
                                           docking_router_object,
                                           attaching_subnet_object)
        interfacekey = interface_object.type + "_" + interface_object.name
        # Add to infrastructure
        if interfacekey in self.resources.keys():
            prompt = "An object of this type and name already exists in your environment, adding it\
again will erase the old object! Are you sure you want to overwrite the old object? (y/n): "

            usr_inpt = raw_input(prompt)
            response = sT.ResponseLoop(usr_inpt, "[yn]", prompt)
            if response == "y":
                self.resources[interfacekey] = interface_object
            else:
                pass
        else:
            self.resources[interfacekey] = interface_object
    def AddVolumeAttachment(self, attachment_name, docking_instance_name,
                            attaching_volume_name):
        '''Creates a volume attachment between and existing instance and volume, then adds the 
        attachment to the virtual infrastructure'''
        # Ensure the docking instance and attaching volume exist
        instancekey = "Instance_" + docking_instance_name
        volumekey = "Volume_" + attaching_volume_name
        if instancekey in self.resources.keys():
            pass
        else:
            raise NameError("No instance named %s to attach to!" %
                            docking_instance_name)
        if volumekey in self.resources.keys():
            pass
        else:
            raise NameError("No volume named %s to attach to instance!" %
                            attaching_volume_name)
        # Create attachment object and key, instantiated object creates appropriate dock and attachment
        attachment_object = VolumeAttachment(attachment_name,
                                             docking_instance_name,
                                             attaching_volume_name)
        attachmentkey = attachment_object.type + "_" + attachment_object.name
        # Add to infrastructure
        if attachmentkey in self.resources.keys():
            prompt = "An object of this type and name already exists in your environment, adding it\
again will erase the old object! Are you sure you want to overwrite the old object? (y/n): "

            usr_inpt = raw_input(prompt)
            response = sT.ResponseLoop(usr_inpt, "[yn]", prompt)
            if response == "y":
                self.resources[attachmentkey] = attachment_object
            else:
                pass
        else:
            self.resources[attachmentkey] = attachment_object
    def AddAttribute(self, key, value):
        if key in self.attributes.keys():
            prompt = "This property already exists for the object and adding it will overwrite the\
current value! Are you sure you want to overwrite this property? (y/n): "

            usr_inpt = raw_input(prompt)
            response = sT.ResponseLoop(usr_inpt, "[yn]", prompt)
            if response == "y":
                self.attributes[key] = value
            else:
                pass
        else:
            self.attributes[key] = value
    def AddVolume(self, volume_name, attributes, properties):
        '''Creates a volume object and adds it to the virtual infrastructure'''
        volume_object = Volume(volume_name, attributes, properties)
        key = volume_object.type + "_" + volume_object.name
        if key in self.resources.keys():
            prompt = "An object of this type and name already exists in your environment, adding it\
again will erase the old object! Are you sure you want to overwrite the old object? (y/n): "

            usr_inpt = raw_input(prompt)
            response = sT.ResponseLoop(usr_inpt, "[yn]", prompt)
            if response == "y":
                self.resources[key] = volume_object
            else:
                pass
        else:
            self.resources[key] = volume_object
    def AddFlavor(self, flavor_name, attributes, properties):
        '''Creates an image object and adds it to the list of virtual resources'''
        flavor_object = Flavor(flavor_name, attributes, properties)
        key = flavor_object.type + "_" + flavor_object.name
        if key in self.resources.keys():
            prompt = "An object of this type and name already exists in your environment, adding it\
again will erase the old object! Are you sure you want to overwrite the old object? (y/n): "

            usr_inpt = raw_input(prompt)
            response = sT.ResponseLoop(usr_inpt, "[yn]", prompt)
            if response == "y":
                self.resources[key] = flavor_object
            else:
                pass
        else:
            self.resources[key] = flavor_object
def CheckOldResources(new_name, existing_resources, object_type):
    object_key = object_type + "_" + new_name
    n = 0
    while object_key in existing_resources.resources.keys():
        new_name = str(
            raw_input(
                "That name is already in use by an existing resource! Please pick another one: "
            ))
        new_name = str(
            sT.ResponseLoop(
                new_name, "^\S+$",
                "Your name did not match the expected pattern. Please ensure there are no spaces and try again: "
            ))
        n += 1
        if n >= 5:
            print "Exceed limit of 5 attempts. Review your existing resources and try again."
            quit()
    return new_name
def CheckOldResources(new_name, existing_resources, command):
    old_names = existing_resources[command]
    chain = itertools.chain.from_iterable(old_names)
    n = 0
    while new_name in chain:
        new_name = str(
            raw_input(
                "That name is already in use by an existing resource! Please pick another one: "
            ))
        new_name = str(
            sT.ResponseLoop(
                new_name, "^\S+$",
                "Your name did not match the expected pattern. Please ensure there are no spaces and try again: "
            ))
        n += 1
        if n >= 5:
            print "Exceed limit of 5 attempts. Review your existing resources and try again."
            quit()
    return new_name
def BuildNewInfrastructure(existing_resources, template_version):
    # Instantiate new virtual infrastructure object
    NewInfrastructure = cL.OpenStack_Virtual_Infrastructure(template_version)
    # Add all the networks
    prompt = "How many networks would you like in your environment?: "
    num_nets = raw_input(prompt)
    num_nets = int(sT.ResponseLoop(num_nets, "^[0-9]+$", prompt))
    prompt = "Please enter the name you wish to give this network. There must be no spaces: "
    for i in range(1, num_nets + 1):
        print "Building network %i" % i
        net_name = raw_input(prompt)
        net_name = sT.ResponseLoop(net_name, '^\S+$', prompt)
        net_name = str(
            CheckOldResources(net_name, existing_resources,
                              "neutron net-list"))
        NewInfrastructure.AddNetwork(net_name, {}, {})
    # Add all the subnets to each network
    networks = NewInfrastructure.GetObjectType("Network")
    for network_name, network_object in networks.iteritems():
        prompt = "How many subnets would you like to add to the network named \"%s\"?: " % network_object.name
        num_subnets = raw_input(prompt)
        num_subnets = int(sT.ResponseLoop(num_subnets, "^[0-9]+$", prompt))
        for i in range(1, num_subnets + 1):
            print "Building subnet %i" % i
            prompt = "Please enter the name you wish to give this subnet. There must be no spaces: "
            subnet_name = raw_input(prompt)
            subnet_name = sT.ResponseLoop(subnet_name, '^\S+$', prompt)
            subnet_name = str(
                CheckOldResources(subnet_name, existing_resources,
                                  "neutron subnet-list"))
            prompt = "Please enter the CIDR for this subnet: "
            cidr = raw_input(prompt)
            cidr = sT.ResponseLoop(cidr,
                                   '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$',
                                   prompt)
            NewInfrastructure.AddSubnet(
                subnet_name, {}, {
                    "cidr": cidr,
                    "network_id": "{ get_resource: %s }" % network_object.name
                })
            network_object.UpdateSubnets(subnet_name)
    # Create all the routers and router interfaces needed to interconnect subnets
    prompt = "How many routers would you like in your environment?: "
    num_routers = raw_input(prompt)
    num_routers = int(sT.ResponseLoop(num_routers, "^[0-9]+$", prompt))
    for i in range(1, num_routers + 1):
        print "Building router %i" % i
        prompt = "Please enter the name you wish to give this router. There must be no spaces: "
        router_name = raw_input(prompt)
        router_name = str(sT.ResponseLoop(router_name, '^\S+$', prompt))
        router_name = str(
            CheckOldResources(router_name, existing_resources,
                              "neutron router-list"))
        NewInfrastructure.AddRouter(
            router_name, {},
            {"external_gateway_info": "{ network: net04_ext }"
             })  # REMOVE THIS HARD CODING!!!!
        prompt = "Which subnets would you like to connect this router to? Please enter the subnet names as a comma separated list with no spaces: "
        subnet_names_str = raw_input(prompt)
        subnet_names_str = sT.ResponseLoop(subnet_names_str, '([\S+][,\S+]*)',
                                           prompt)
        subnet_names_list = subnet_names_str.split(",")
        for subnet_name in subnet_names_list:
            interface_name = router_name + "_to_" + subnet_name + "_interface"
            NewInfrastructure.AddRouterInterface(
                interface_name,
                NewInfrastructure.resources["Router_" + router_name],
                NewInfrastructure.resources["Subnet_" + subnet_name])
    # Create all instances
    #prompt = "How many virtual machines would you like in your environment?: "
    #num_instances = raw_input(prompt)
    #num_instances = int(sT.ResponseLoop(num_routers,"^[0-9]+$",prompt))
    #for i in range(num_instances):
    #    print "Building instance %i"%i
    #    prompt = "Please enter the name you wish to give this instance. There must be no spaces: "
    #    inst_name = raw_input(prompt)
    #    inst_name = str(sT.ResponseLoop(inst_name,'^\S+$',prompt))
    #    inst_name = str(CheckOldResources(inst_name,existing_resources,"nova list"))
    #    prompt = "What flavor would you like to use to specify the virtual resources of this instance? Please choose from %s:"%str()

    with open("deployment_test.yaml", 'w+') as template_file:
        template_file.write(NewInfrastructure.__repr__())
def BuildNewInfrastructure(existing_infrastructure, template_version):
    # Instantiate new virtual infrastructure object
    NewInfrastructure = cL.OpenStack_Virtual_Infrastructure(template_version)
    # Instantiate hydrid infrastructure object by initializing from old infrastructure
    HybridInfrastructure = copy.deepcopy(existing_infrastructure)
    # Add all the networks
    prompt = "How many networks would you like in your environment?: "
    num_nets = raw_input(prompt)
    num_nets = int(sT.ResponseLoop(num_nets, "^[0-9]+$", prompt))
    prompt = "Please enter the name you wish to give this network. There must be no spaces: "
    for i in range(1, num_nets + 1):
        print "Building network %i" % i
        net_name = raw_input(prompt)
        net_name = sT.ResponseLoop(net_name, '^\S+$', prompt)
        net_name = str(
            CheckOldResources(net_name, HybridInfrastructure, "Network"))
        NewInfrastructure.AddNetwork(net_name, {}, {})
        HybridInfrastructure.AddNetwork(net_name, {}, {})
    # Add all the subnets to each network
    networks = NewInfrastructure.GetObjectType("Network")
    for network_name, network_object in networks.iteritems():
        prompt = "How many subnets would you like to add to the network named \"%s\"?: " % network_object.name
        num_subnets = raw_input(prompt)
        num_subnets = int(sT.ResponseLoop(num_subnets, "^[0-9]+$", prompt))
        for i in range(1, num_subnets + 1):
            print "Building subnet %i" % i
            prompt = "Please enter the name you wish to give this subnet. There must be no spaces: "
            subnet_name = raw_input(prompt)
            subnet_name = sT.ResponseLoop(subnet_name, '^\S+$', prompt)
            subnet_name = str(
                CheckOldResources(subnet_name, HybridInfrastructure, "Subnet"))
            prompt = "Please enter the CIDR for this subnet: "
            cidr = raw_input(prompt)
            cidr = sT.ResponseLoop(cidr,
                                   '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$',
                                   prompt)
            NewInfrastructure.AddSubnet(
                subnet_name, {'network_id': network_name}, {
                    "cidr": cidr,
                    "network_id": "{ get_resource: %s }" % network_object.name
                })
            HybridInfrastructure.AddSubnet(
                subnet_name, {'network_id': network_name}, {
                    "cidr": cidr,
                    "network_id": "{ get_resource: %s }" % network_object.name
                })
            network_object.UpdateSubnets(subnet_name)
    # Create all the routers and router interfaces needed to interconnect subnets
    prompt = "How many routers would you like in your environment?: "
    num_routers = raw_input(prompt)
    num_routers = int(sT.ResponseLoop(num_routers, "^[0-9]+$", prompt))
    for i in range(1, num_routers + 1):
        print "Building router %i" % i
        prompt = "Please enter the name you wish to give this router. There must be no spaces: "
        router_name = raw_input(prompt)
        router_name = str(sT.ResponseLoop(router_name, '^\S+$', prompt))
        router_name = str(
            CheckOldResources(router_name, HybridInfrastructure, "Router"))
        ext_nets = []
        # Ask the user which external network they would like to use for the external gateway of the router
        for network_name, network_obj in HybridInfrastructure.GetObjectType(
                "Network").iteritems():
            if ('router:external' in network_obj.attributes) and (
                    network_obj.attributes['router:external'] == 'True'):
                ext_nets.append(network_name)
        prompt = "What external network would you like to use to give this router internet access? Please choose from %s: " % str(
            ext_nets)
        ext_gateway = raw_input(prompt)
        ext_gateway = str(sT.ResponseLoop(ext_gateway, '^\S+$', prompt))
        while ext_gateway not in ext_nets:
            ext_gateway = str(sT.ResponseLoop(ext_gateway, '^\S+$', prompt))
        NewInfrastructure.AddRouter(
            router_name, {},
            {"external_gateway_info": "{ network: %s }" % ext_gateway
             })  #!!! REMOVE THIS HARD CODING!!!!
        HybridInfrastructure.AddRouter(
            router_name, {},
            {"external_gateway_info": "{ network: %s }" % ext_gateway
             })  #!!! REMOVE THIS HARD CODING!!!!
        prompt = "Which subnets would you like to connect this router to? Please enter the subnet names as a comma separated list with no spaces: "
        subnet_names_str = raw_input(prompt)
        subnet_names_str = sT.ResponseLoop(subnet_names_str, '([\S+][,\S+]*)',
                                           prompt)
        subnet_names_list = subnet_names_str.split(",")
        for subnet_name in subnet_names_list:
            interface_name = router_name + "_to_" + subnet_name + "_interface"
            NewInfrastructure.AddRouterInterface(
                interface_name,
                NewInfrastructure.resources["Router_" + router_name],
                NewInfrastructure.resources["Subnet_" + subnet_name])
            HybridInfrastructure.AddRouterInterface(
                interface_name,
                HybridInfrastructure.resources["Router_" + router_name],
                HybridInfrastructure.resources["Subnet_" + subnet_name])
    # Create all instances
    prompt = "How many virtual machines would you like in your environment?: "
    num_instances = raw_input(prompt)
    num_instances = int(sT.ResponseLoop(num_instances, "^[0-9]+$", prompt))
    for i in range(num_instances):
        print "Building instance %i" % i
        prompt = "Please enter the name you wish to give this instance. There must be no spaces: "
        inst_name = raw_input(prompt)
        inst_name = str(sT.ResponseLoop(inst_name, '^\S+$', prompt))
        inst_name = str(
            CheckOldResources(inst_name, HybridInfrastructure, "Instance"))
        prompt = "What flavor would you like to use to specify the virtual resources of this instance? Please choose from %s: " % str(
            existing_infrastructure.GetObjectType("Flavor").keys())
        flavor = raw_input(prompt)
        flavor = str(sT.ResponseLoop(flavor, '^\S+$', prompt))
        while flavor not in existing_infrastructure.GetObjectType(
                "Flavor").keys():
            flavor = str(sT.ResponseLoop(flavor, '^\S+$', prompt))
        prompt = "What image would you like to use to boot this instance? Please choose from %s: " % str(
            existing_infrastructure.GetObjectType("Image").keys())
        image = raw_input(prompt)
        image = str(sT.ResponseLoop(image, '^\S+$', prompt))
        while image not in existing_infrastructure.GetObjectType(
                "Image").keys():
            image = str(sT.ResponseLoop(image, '^\S+$', prompt))
        # Create all the network ports and attach them to subnets. Create list of port attachments for instance
        prompt = "Which subnets would you like to connect this instance to? Please enter the subnet names as a comma separated list with no spaces: "
        subnet_names_str = raw_input(prompt)
        subnet_names_str = sT.ResponseLoop(subnet_names_str, '([\S+][,\S+]*)',
                                           prompt)
        subnet_names_list = subnet_names_str.split(",")
        ports = []
        for subnet in subnet_names_list:
            subnet_obj = NewInfrastructure.GetObject("Subnet", subnet)
            network_obj = NewInfrastructure.GetObject(
                'Network', subnet_obj.attributes['network_id'])
            name = inst_name + '_to_' + subnet + '_port'
            ports.append(('port', '{ get_resource: %s }' % name))
            NewInfrastructure.AddNetworkPort(name, network_obj, subnet_obj)
            HybridInfrastructure.AddNetworkPort(name, network_obj, subnet_obj)
        # Add instances to virtual infrastructure
        NewInfrastructure.AddInstance(inst_name, {}, {
            'name': inst_name,
            'image': image,
            'flavor': flavor,
            'networks': ports
        })
        HybridInfrastructure.AddInstance(inst_name, {}, {
            'name': inst_name,
            'image': image,
            'flavor': flavor,
            'networks': ports
        })
    # Build template files
    with open("new_infrastructure.yaml", 'w+') as template_file:
        template_file.write(NewInfrastructure.__repr__())
    with open("old_infrastructure.yaml", 'w+') as template_file:
        template_file.write(existing_infrastructure.__repr__())
    with open("hybrid_infrastructure.yaml", 'w+') as template_file:
        template_file.write(HybridInfrastructure.__repr__())