CloudStack: Creating advanced networking zone using API

28-03-2014 / Pierre-Luc Dion

In the process of automating CloudStack installation, we’ve been through a challenging part: Creating an Entire Advanced networking Zone from the API. Production and test system that we deploy don’t have building tools such as mavin in order to create zones, pod,networks,… So the usual process is to use the Web UI and follow the “Add Zone” wizard. Well, not anymore!

To create an entire zone using API we are using Ruby with Chip’s cloudstack_ruby_client. Other API clients can be used such as cloudmonkey, the idea is to demonstrate required API calls and their order.

Overview

In this scenario we are using XenServer as hypervisor that have a Bond interface named: “bond1”, Storage networking is not used and we also enable local Storage instead of using Shared SAN for the Primary Storage. Virtual Router and VPC’s are enabled Network Service Providers.

So, to create and populate a zone we need to perform following tasks (the order matter, they might be variant but that version as been tested and does work well so far).

  1. Create zone  (createZone)
  2. Prepare networks
    1. Create physicalnetworks, and define guest VLAN-range (createPhysicalNetwork)
    2. Assign physical network to traffic type and assign labels. (addTrafficType)
    3. Update network_service_providers (updateNetworkServiceProvider)
    4. Define guest networks vlan range (updatePhysicalNetwork)
    5. Define public IP range (createVlanIpRange)
  3. Create pod (createPod)
  4. Create cluster (createCluster)
  5. Create secondary storage (addSecondaryStorage)
  6. Create primary storage or enable localstorage into the zone (updateZone)
  7. add host (addHost)
  8. enable the zone (updateZone)

Following steps presume that you have API_KEY and SECRET_KEY of admin and have set `system.vm.use.local.storage` to true.

let’s roll

This quick how to consider that you have Ruby installed, more info on installing ruby: rvm.io

  1. Prepare your ruby:
    $ gem install cloudstack_ruby_client
    $ irb
    
  2. Connection to CloudStack:
    require 'cloudstack_ruby_client'# cloudstack connection
    URL = 'http://IP:8080/client/api/'
    APIKEY = "admin apikey"
    SECKEY = "admin secretkey"
    client = CloudstackRubyClient::Client.new(URL, APIKEY, SECKEY, false)
    
  3. Create zone: 
    zone_conf = {
        :dns1 => "8.8.8.8",
        :internaldns1 => "8.8.8.8",
        :name => "testZone2",
        :guestcidraddress => "10.2.1.0/24",
        :networktype => "Advanced"
    }
    zone = client.create_zone(zone_conf)
    
  4. Configure network:
    1. physical interface mapping
    2. define guest VLANs
    3. define public IP’s range
    4. Enable network service providers
    phy_net_conf = {
        :name =>"data2", 
        :isolationmethods => "VLAN",
        :zoneid => zone["zone"]["id"]
    }
    p_net = client.create_physical_network(phy_net_conf)
    

    phy_net = client.list_physical_networks(:name => phy_net_conf[:name])

    client.add_traffic_type({ :physicalnetworkid => phy_net["physicalnetwork"].first["id"], :traffictype => "Management", :xennetworklabel => "bond1" }) client.add_traffic_type({ :physicalnetworkid => phy_net["physicalnetwork"].first["id"], :traffictype => "Public", :xennetworklabel => "bond1" }) client.add_traffic_type({ :physicalnetworkid => phy_net["physicalnetwork"].first["id"], :traffictype => "Guest", :xennetworklabel => "bond1" })

    # cannot enable phy_network at creation. guest_vlan_range = client.update_physical_network({ :id => phy_net["physicalnetwork"].first["id"], :state => "Enabled", :vlan => "3101-3110", :isolationmethods => "VLAN", :zoneid => zone["zone"]["id"] })

    public_range = client.create_vlan_ip_range({ :physicalnetworkid => phy_net["physicalnetwork"].first["id"], :startip => "172.12.1.80", :endip => "172.12.1.89", :netmask => "255.255.255.0", :gateway => "172.12.1.1", :vlan => "1161", :zoneid => zone["zone"]["id"] })

    ## # Service Providers # # enable vr-element => need loop vre = client.list_virtual_router_elements(:enabled => "false")["virtualrouterelement"] vre.each do |vre| client.configure_virtual_router_element({ :id => vre["id"], :enabled => "true" }) end vr_prov = client.list_network_service_providers( :physicalnetworkid => phy_net["physicalnetwork"].first["id"], :name => "VirtualRouter" ) vpc_prov = client.list_network_service_providers( :physicalnetworkid => phy_net["physicalnetwork"].first["id"], :name => "VpcVirtualRouter" )

    # enable network service providers client.update_network_service_provider({ :id => vr_prov["networkserviceprovider"].first["id"], :state => "Enabled" }) client.update_network_service_provider({ :id => vpc_prov["networkserviceprovider"].first["id"], :state => "Enabled" }) # ##

  5. Create everything else for the zone:
    # create POD
    pod_conf = {
    :name => "pod1",
    :gateway => "172.30.20.1",
    :netmask => "255.255.255.0",
    :startip => "172.16.20.80",
    :endip => "172.30.20.89",
    :zoneid => zone["zone"]["id"]
    }
    pod = client.create_pod(pod_conf)# create CLUSTER
    cluster_conf = {
    :clustername => "cluster1",
    :clustertype => "CloudManaged",
    :hypervisor => "XenServer",
    :podid => pod["pod"]["id"],
    :zoneid => zone["zone"]["id"]
    }
    cluster = client.add_cluster (cluster_conf)# create secondary storage
    sec = client.add_secondary_storage ({
    :url => "nfs://172.30.21.173/data/secondary",
    :zoneid => zone["zone"]["id"]
    })# enable local storage
    client.update_zone({:id => zone["zone"]["id"], :localstorageenabled => "true"})# add host that is ready to go
    host_conf = {
    :hypervisor => "XenServer",
    :url => "http://172.30.20.34",
    :username => "root",
    :password => "ROOT_PASSORD",
    :clusterid => cluster["cluster"].first["id"],
    :zoneid => zone["zone"]["id"],
    :podid => pod["pod"]["id"]
    }
    host = client.add_host(host_conf)
    
  6. Finaly, enable the zone:
    # enable zone
    client.update_zone({:id => zone["zone"]["id"], :allocationstate => "Enabled"})