Ask Your Question

Revision history [back]

How do you get a subnet from a nested template that creates a network?

I've been struggling with this for a couple of days. It looks like it should be straightforward, but ...

What I am trying to do is create a parent template with two nested templates. The first nested template creates the network, subnet, etc. The second nested template creates a tomcat instance, does the software deployment, creates the port, etc. From the parent I first create the network and I want to back outputs from the nested network template and then pass those outputs to the nested tomcat template.

So here is the relevant parent code:

  NestZone1:
    type: zone_network.template
    properties:
      zone_name: nzone1
      cidr: 192.168.20.0/24
      gateway_ip: 192.168.20.1
      allocation_pools:
        "start": "192.168.20.2"
        "end": "192.168.20.254"
      shared_network: 'False'
      enable_dhcp: 'True'
      ip_version:
        get_param:  ip_ver
      dns_servers:
        get_param: dns_servers
      router_id:
        get_resource: Router
      tenant_network_id:
        get_param: tenant_net_id


  #######################
  # Tomcat Server
  #######################
  wmwcvm1:
    type: sprint9_tomcat_server.template
    properties:
      subnet_id: { get_attr: [ NestZone1, subnet_id, 0 ] }
      network: { get_attr: [ NestZone1, network_uuid ] }
      name: { get_param: tomcat_server_name }
      key_name: widgetco
      image: { get_param: image_id }
      flavor: { get_param: instance_type }
      chef_params: DEBUG
      user_data:
        str_replace:
          template: { get_file:  "http://haasaet.web.att.com/depot/hot-skel.sh" }
          params:
            $HOTSKEL1: { get_file:  "http://haasaet.web.att.com/depot/deploy-chef-client-as3525.sh" }

Here is the relevant portion of the nested network template:

  zone_network:
    type: OS::Neutron::Net
    properties:
      name:
        get_param: zone_name
      shared:
        get_param: shared_network
      tenant_id:
        get_param: tenant_network_id
      value_specs: {}

      zone_subnet:
        type: OS::Neutron::Subnet
        properties:
          name:
            str_replace:
              template:
                $subnet-subnet
              params:
                $subnet: { get_param: zone_name }
          network_id:
            get_resource: zone_network
          allocation_pools:
            - { get_param: allocation_pools }
          cidr:
            get_param: cidr
          dns_nameservers:
            get_param: dns_servers
          enable_dhcp:
            get_param: enable_dhcp
          gateway_ip:
            get_param: gateway_ip
          #host_routes: []
          ip_version:
            get_param: ip_version
          tenant_id:
            get_param: tenant_network_id
          value_specs: {}


      zone_interface:
        type: OS::Neutron::RouterInterface
        properties:
          router_id:
            get_param: router_id
          subnet_id:
            get_resource: zone_subnet

    outputs:
      network_name:
        description: Name of the network
        value: { get_attr: [zone_network, name] }
      subnet_id:
        description: Subnet for network
        value: { get_attr: [zone_network, subnets ] }
      network_uuid:
        description: Network UUID
        value: { get_attr: [zone_subnet, network_id] }

So in the outputs I pass back the subnets attribute of the net I created. From what I have read in the docs it should pass back subnets plain xsd:dict which are the associated subnets.

So if I look at the web services api for show network I assume it should contain something that looks like this example:

{

    "network": {
        "status": "ACTIVE",
        "subnets": [
            "54d6f61d-db07-451c-9ab3-b9609b6b6f0b"
        ],
        "name": "private-network",
        "provider:physical_network": null,
        "admin_state_up": true,
        "tenant_id": "4fd44f30292945e481c7b8a0c8908869",
        "provider:network_type": "local",
        "router:external": true,
        "shared": true,
        "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
        "provider:segmentation_id": null
    }
}

Subnets does not really look like a dict to me. It looks more like a list. I know from a previous question you can't pass lists as parameters. Does that also apply to lists not being able to pass back as outputs?

So the key pieces of the tomcat nested template looks like:

parameters:
  # declaration of input parameters

  network:
    type: string
    description: Network to deploy on

  subnet_id:
    type: string
    description: Subnet to deploy on

resources:

  #############################################################
  # Define the application server (Tomcat)
  #############################################################
  tomcat_server:
    type: OS::Nova::Server
    properties:
      key_name: { get_param:  key_name }
      image: { get_param: image }
      flavor: { get_param: flavor }
      networks:
        - port: { get_resource: server_port }
      user_data_format: RAW
      user_data: { get_param: user_data }

  tomcat_sw_config:
    type: OS::Heat::SoftwareConfig
    properties:
      inputs:
      - name: chefParam
        default: { get_param: chef_params }
      config: |
        { get_file: http://haasaet.web.att.com/depot/install_tomcat.sh }

  tocmat_deployment:
    type: OS::Heat::SoftwareDeployment
    properties:
      name: tomcat-deployment
      actions: [CREATE, UPDATE]
      config:
        get_resource: tomcat_sw_config
      server:
        get_resource: tomcat_server


  #######################
  server_port:
    type: OS::Neutron::Port
    properties:
      network_id: { get_param: network }
      fixed_ips:
        - subnet_id: { get_param: subnet_id }
      security_groups: [{ get_resource: server_security_group }]


  server_security_group:
    type: OS::Neutron::SecurityGroup
    properties:
      name: security-group
      rules:
        - remote_ip_prefix: 0.0.0.0/0
          protocol: tcp
          port_range_min: 22
          port_range_max: 22
        - remote_ip_prefix: 0.0.0.0/0

I cut out some of the parameters for brevity. I'm passing in the subnet_id as a string because of the prohibition on passing in lists and I try to extract the specific UUID into a string from the parent template.

So how do I accomplish this? I've tried numerous methods. Is there a way to print the value of an attribute in a template so you can actually see what's there? Is there a definitive reference on what the attributes being passed back should look like?

The error I get during the build is:

Error: Resource CREATE failed: NeutronClientException: Invalid input for fixed_ips. Reason: '[' is not a valid UUID.

That makes me think that I am indexing only the first character of the string instead of the first item in the dictionary. That also makes me think that a dictionary/map in an output parameter does not implicitly keep it's type and gets converted to a string. If that is the case that is probably my issue. If so, how do I work around it?

Thanks!

How do you get a subnet from a nested template that creates a network?

I've been struggling with this for a couple of days. It looks like it should be straightforward, but ...

What I am trying to do is create a parent template with two nested templates. The first nested template creates the network, subnet, etc. The second nested template creates a tomcat instance, does the software deployment, creates the port, etc. From the parent I first create the network and I want to back outputs from the nested network template and then pass those outputs to the nested tomcat template.

So here is the relevant parent code:

  NestZone1:
    type: zone_network.template
    properties:
      zone_name: nzone1
      cidr: 192.168.20.0/24
      gateway_ip: 192.168.20.1
      allocation_pools:
        "start": "192.168.20.2"
        "end": "192.168.20.254"
      shared_network: 'False'
      enable_dhcp: 'True'
      ip_version:
        get_param:  ip_ver
      dns_servers:
        get_param: dns_servers
      router_id:
        get_resource: Router
      tenant_network_id:
        get_param: tenant_net_id


  #######################
  # Tomcat Server
  #######################
  wmwcvm1:
    type: sprint9_tomcat_server.template
    properties:
      subnet_id: { get_attr: [ NestZone1, subnet_id, 0 ] }
      network: { get_attr: [ NestZone1, network_uuid ] }
      name: { get_param: tomcat_server_name }
      key_name: widgetco
      image: { get_param: image_id }
      flavor: { get_param: instance_type }
      chef_params: DEBUG
      user_data:
        str_replace:
          template: { get_file:  "http://haasaet.web.att.com/depot/hot-skel.sh" }
          params:
            $HOTSKEL1: { get_file:  "http://haasaet.web.att.com/depot/deploy-chef-client-as3525.sh" }

Here is the relevant portion of the nested network template:

  zone_network:
    type: OS::Neutron::Net
    properties:
      name:
        get_param: zone_name
      shared:
        get_param: shared_network
      tenant_id:
        get_param: tenant_network_id
      value_specs: {}

      zone_subnet:
        type: OS::Neutron::Subnet
        properties:
          name:
            str_replace:
              template:
                $subnet-subnet
              params:
                $subnet: { get_param: zone_name }
          network_id:
            get_resource: zone_network
          allocation_pools:
            - { get_param: allocation_pools }
          cidr:
            get_param: cidr
          dns_nameservers:
            get_param: dns_servers
          enable_dhcp:
            get_param: enable_dhcp
          gateway_ip:
            get_param: gateway_ip
          #host_routes: []
          ip_version:
            get_param: ip_version
          tenant_id:
            get_param: tenant_network_id
          value_specs: {}


      zone_interface:
        type: OS::Neutron::RouterInterface
        properties:
          router_id:
            get_param: router_id
          subnet_id:
            get_resource: zone_subnet

    outputs:
      network_name:
        description: Name of the network
        value: { get_attr: [zone_network, name] }
      subnet_id:
        description: Subnet for network
        value: { get_attr: [zone_network, subnets ] }
      network_uuid:
        description: Network UUID
        value: { get_attr: [zone_subnet, network_id] }

So in the outputs I pass back the subnets attribute of the net I created. From what I have read in the docs it should pass back subnets plain xsd:dict which are the associated subnets.

So if I look at the web services api for show network I assume it should contain something that looks like this example:

{

    "network": {
        "status": "ACTIVE",
        "subnets": [
            "54d6f61d-db07-451c-9ab3-b9609b6b6f0b"
        ],
        "name": "private-network",
        "provider:physical_network": null,
        "admin_state_up": true,
        "tenant_id": "4fd44f30292945e481c7b8a0c8908869",
        "provider:network_type": "local",
        "router:external": true,
        "shared": true,
        "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
        "provider:segmentation_id": null
    }
}

Subnets does not really look like a dict to me. It looks more like a list. I know from a previous question you can't pass lists as parameters. Does that also apply to lists not being able to pass back as outputs?

So the key pieces of the tomcat nested template looks like:

parameters:
  # declaration of input parameters

  network:
    type: string
    description: Network to deploy on

  subnet_id:
    type: string
    description: Subnet to deploy on

resources:

  #############################################################
  # Define the application server (Tomcat)
  #############################################################
  tomcat_server:
    type: OS::Nova::Server
    properties:
      key_name: { get_param:  key_name }
      image: { get_param: image }
      flavor: { get_param: flavor }
      networks:
        - port: { get_resource: server_port }
      user_data_format: RAW
      user_data: { get_param: user_data }

  tomcat_sw_config:
    type: OS::Heat::SoftwareConfig
    properties:
      inputs:
      - name: chefParam
        default: { get_param: chef_params }
      config: |
        { get_file: http://haasaet.web.att.com/depot/install_tomcat.sh }

  tocmat_deployment:
    type: OS::Heat::SoftwareDeployment
    properties:
      name: tomcat-deployment
      actions: [CREATE, UPDATE]
      config:
        get_resource: tomcat_sw_config
      server:
        get_resource: tomcat_server


  #######################
  server_port:
    type: OS::Neutron::Port
    properties:
      network_id: { get_param: network }
      fixed_ips:
        - subnet_id: { get_param: subnet_id }
      security_groups: [{ get_resource: server_security_group }]


  server_security_group:
    type: OS::Neutron::SecurityGroup
    properties:
      name: security-group
      rules:
        - remote_ip_prefix: 0.0.0.0/0
          protocol: tcp
          port_range_min: 22
          port_range_max: 22
        - remote_ip_prefix: 0.0.0.0/0

I cut out some of the parameters for brevity. I'm passing in the subnet_id as a string because of the prohibition on passing in lists and I try to extract the specific UUID into a string from the parent template.

So how do I accomplish this? I've tried numerous methods. Is there a way to print the value of an attribute in a template so you can actually see what's there? Is there a definitive reference on what the attributes being passed back should look like?

The error I get during the build is:

Error: Resource CREATE failed: NeutronClientException: Invalid input for fixed_ips. Reason: '[' is not a valid UUID.

That makes me think that I am indexing only the first character of the string instead of the first item in the dictionary. That also makes me think that a dictionary/map in an output parameter does not implicitly keep it's type and gets converted to a string. If that is the case that is probably my issue. If so, how do I work around it?

If I change the parameter subnet_id I pass into the tomcat template to json I get:

StackValidationFailed: Property error : wmwcvm1: subnet_id "[u'028b13f1-1756-4ea2-a910-061c58114e3a']" is not a map

The good news there is that is the correct UUID for the subnet so at least what I'm passing back contains the right data if not the right type.

Thanks!