Automating Contrail Cloud Solution

Executive summary:

Contrail Cloud solution is an open cloud network automation product that uses software-defined networking (SDN) technology to orchestrate the creation of virtual networks with high scalability. It exposes a set of REST APIs for northbound interaction with cloud orchestration tools, as well as other applications. Contrail Cloud solution has multiple components like Contrail controller, Openstack controller and vRouters.

This product creates Virtual Machines on the compute nodes, attach Virtual Machine to the virtual network and connect the Virtual Machine to the storage.

This Document gives details on REST APIs to automate the following,

  • Verifying hypervisor status
  • Create Virtual Machine or delete Virtual Machine
  • Create virtual Networks
  • Attach Virtual Machine to virtual network
  • Verifying Virtual Machine status
  • Get information about existing Virtual Machines

Description:

In contrail cloud solution Openstack server is responsible for creation of Virtual Machines.Openstack

server has inventory of all the Hypervisors.When a VM creation is requested through openstack Horizon GUI or through RESTAPI commands,NOVA component in openstack controller will connect to the Hypervisor (which has sufficient resources to create VM) and request for VM creation.

After VM is created, NEUTRON component in Openstack controller will connect to the Contrail controller and request for attaching the VM to the specefic Virtual Network.Contrail controller will then connect to the vrouter in the  Hypervisor (through XMPP protocol) and request for routing instance creation for the specefic virtual network.The same sequence operation repeated for each VM creation.

When the VMs are created on multiple hypervisors.They exchange routes between them.Then MPLS-OVER-GRE/MPLS-OVER-UDP Tunnels created between them.

RESTAPIs can be used for automating VM creation, VM deletion and other operations described.

This picture shows the implementation details of Contrail cloud solution.In this topology PE2 & PE3 will be acting as local Datacenter gateway.PE1 will be the remote Datacenter gateway.

All compute nodes, controllers are attached to IP fabric.The IP Fabric is not aware of the virtual Networks to which the virtual machines are attached.There is no need for the IP fabric to know virtual network details.Between PE2 (&PE3) and compute nodes and between the compute nodes TUNNEL overlays is implemented.So all traffic between compute nodes to PE2/PE3 or between compute nodes will be encapsulated with TUNNEL header.IP fabric is aware of the IP addresses present in the Tunnel header(as these IP addresses are part of underlay/IP fabric network.

Contrail controllers will be managing the compute nodes (vRouters) using XMPP.PE2 &PE3  will talk to Contrail controllers with BGP.The vRouters in contrail cloud will act similar to PE router in L3 VPN environment.

When a VM in a vRouter need to send traffic to VM in another vRouter in the same datacenter,

the source vRouter will encapsulate the packets with Tunnel header and then forward it to the IP fabric.After the destination vRouter receives the packet it will decapsulate the packets and forward it to the VM.

When vRouter need to send traffic to vRouters in another datacenter it will encapulate packets with Tunnel header and forward it to PE2 or PE3.PE2 or PE3 will decapsulate the MPLS-OVER-UDP header and then encapsulate it with MPLS headers and forward it to PE1.PE1 decapsulate MPLS header and forward the packets to the node in remote Datacenter.

Automating Contrail/Openstack Controller:

This section gives details on Contrail/Openstack controller Automation.A sample perl code with RESTAPI details given for each operations like virtual network creation,VM creation,VM deletion etc..Perl module LWP::UserAgent and use JSON qw( decode_json encode_json) should be sourced for this.

Virtual Machine creation:

OpenStack Token-id and Tenant id:

This section gives details on automating VM creation.Before starting VM creation we need to get the token-id and tenant id from the openstack controller.This token id is required to execute any operational commands in the openstack controller.Tenant id is required to find the right openstack project.The sample code given below gives details on this . The Openstack component keystone provides this token-id.

Keystone is the identity service used by OpenStack for authentication (authN) and high-level authorization (authZ). It currently supports token-based authN and user-service authorization.

In this sample code “$OS_tenant_name” is the project name.This name can be found on openstack Horizon GUI(identity->Projects).Project name is required to find the correct tenant id.The “$CMDpath” shows  the syntax of RESTAPI command to get token-id from openstack controller.The tenant id and token id collected here will be used in next steps.

my openstack_ip = ‘1.1.1.1’;
      	     	my  $KEYSTONEport     =  "5000";               
        		my $OS_tenant_name = "PROJECTNAME";
        		my $OS_user = "admin";
        		my $OS_password = ‘xxxxxx’;
                 	my $CMDpath= "/v2.0/tokens";
        	my $APIport=$KEYSTONEport;
        	my $url= "http://".$openstack_ip.":".$APIport.$CMDpath;
             my $body =
        	{
               	"auth"   =>
                      	   {
                         	       "tenantName"  => "$OS_tenant_name",
                               	 "passwordCredentials" =>
                                                {
                                              	  "username"  => "$OS_user",
                                              	  "password"  => "$OS_password"
                                                }
                          }                     
         };               
        	my $request  = HTTP::Request->new( POST => $url );
        	my $bjson = encode_json $body;
        	$request->content_type("application/json");
        	$request->authorization_basic( "$OS_user", "$OS_password" );
        	$request->content($bjson);
        	my $http = LWP::UserAgent->new->request($request);
        	my @y = $http->{_content};
        	my $mes         = JSON::decode_json($y[0]);
         
        	my $token_id = $mes->{'access'}{'token'}{'id'};
        	my $token_exp = $mes->{'access'}{'token'}{'expires'};
        	my $tenant_id = $mes->{'access'}{'token'}{'tenant'}{'id'};
        	print("\n\n *******  token_id is $token_id and token_exp is $token_exp and tenant_id is $tenant_id ******* \n\n");

Verifying Hypervisor status:

Before going to next step we need to verify the status of compute nodes(Hypervisors).Before creating the VM,the Hypervisors should be Up and running.The RESTAPI command “/v1.1/”.$tenant_id.”/os-services” provides the status of the hypervisors.This is equivalent to “nova service-list command(the output given below).

my $NOVAport         =  "8774";
       $CMDpath= "/v1.1/".$tenant_id."/os-services";
        $APIport=$NOVAport;
        $url= "http://".$cont_ip.":".$APIport.$CMDpath;
        $request  = HTTP::Request->new( GET => $url );
        $request->header('content-type' => 'application/json');
        $request->header('x-auth-token' => $token_id);
        $http = LWP::UserAgent->new->request($request);
        @y = $http->{_content};
        print Dumper($http);    
        $mes         = JSON::decode_json($y[0]);
        my $len = @{$mes->{"services"}};          
        my %server_to_netaddr_hash;
        my %test;
        my $servername;
        my $state;
        my $status; 
        my $hostcount=0;
        for (my $x = 0; $x< $len ; ++$x) { $servername = $mes->{"services"}[$x]{"host"};
                        if( ($servername =~/vmg\d+/) || ($servername =~/vm\d+/) ) {
	        $state = $mes->{"services"}[$x]{"state"};
                         my $status = $mes->{"services"}[$x]{"status"};
                         if ($state ne "up" || $status ne "enabled") {
        print("\n\n *******  status or state of host $servername is not correct.The state is $state and status is $status ******* \n\n");
         return JT::FALSE;
                        }
        print ("\n\n *******  status or state of the compute node $servername is correct The state is $state and status is $status ******* \n\n");
                    $hostcount++;

                   }
	}

root@server01:~# nova service-list
+----+------------------+--------------+----------+---------+-------+----------------------------+-----------------+
| Id | Binary           | Host         | Zone     | Status  | State | Updated_at                 | Disabled Reason |
+----+------------------+--------------+----------+---------+-------+----------------------------+-----------------+
| 1  | nova-scheduler   | server1 | internal | enabled | up    | 2016-12-09T21:32:39.000000 | -               |
| 2  | nova-console     |  server1 | internal | enabled | up    | 2016-12-09T21:32:42.000000 | -               |
| 3  | nova-consoleauth | server1 | internal | enabled | up    | 2016-12-09T21:32:42.000000 | -               |
| 4  | nova-conductor   | server1 | internal | enabled | up    | 2016-12-09T21:32:38.000000 | -               |
| 6  | nova-compute     | vm6          | nova     | enabled | up    | 2016-12-09T21:32:38.000000 | -               |
| 7  | nova-compute     | vm7          | nova     | enabled | up    | 2016-12-09T21:32:35.000000 | -               |
| 8  | nova-compute     | vm8          | nova     | enabled | up    | 2016-12-09T21:32:38.000000 | -               |
| 9  | nova-compute     | vm9          | nova     | enabled | up    | 2016-12-09T21:32:33.000000 | -               |
| 10 | nova-compute     | vm10         | nova     | enabled | up    | 2016-12-09T21:32:41.000000 | -               |
| 11 | nova-compute     | vm11         | nova     | enabled | up    | 2016-12-09T21:32:41.000000 | -               |
| 12 | nova-compute     | vm12         | nova     | enabled | up    | 2016-12-09T21:32:33.000000 | -               |
| 13 | nova-compute     | vm13         | nova     | enabled | up    | 2016-12-09T21:32:37.000000 | -               |
| 14 | nova-compute     | vm14         | nova     | enabled | up    | 2016-12-09T21:32:41.000000 | -               |
| 15 | nova-compute     | vm15         | nova     | enabled | up    | 2016-12-09T21:32:39.000000 | -               |
| 16 | nova-compute     | vm16         | nova     | enabled | up    | 2016-12-09T21:32:42.000000 | -               |
| 17 | nova-compute     | vm17         | nova     | enabled | up    | 2016-12-09T21:32:33.000000 | -               |
| 18 | nova-compute     | vm18         | nova     | enabled | up    | 2016-12-09T21:32:40.000000 | -               |
+----+------------------+--------------+----------+---------+-------+----------------------------+-----------------+
root@ server01:~# 

Creating Virtual Network:

The next step is to create virtual Network. Virtual network has to be created before creating VM.

To create virtual Network the following information is required.

  • Network segment address and netmask
  • Gateway address
  • Network name
  • Route-target attached to this network
  • Project name (collected from openstack horizon GUI)
  • Token-id (as explained in previous step)

To create virtual network ,the RESAPI command “/virtual-networks” is executed on the contrail controller.Port number 8082 is used for this.The correct project name should be added here where it says “PROJECTNAME”.”nova net-list” shows the network created as shown below.

$netname="net$i";
		$cont_ip=”1.1.1.1”;
		$target="target:64512:$value";
		$gateway="100.$n.$m.1";
		$pool = "100.$n.$m.0";
       		 $CMDpath = "/virtual-networks";
        		$APIport="8082";
       		 $url= "http://".$cont_ip.":".$APIport.$CMDpath;
          		$body =
              		{
               			"virtual-network"=>
                 			  {
                  				 "parent_type"=> "project",
                 				  "fq_name"=> [
                             			 "default-domain",
                              			 "PROJECTNAME",
                              			  	$netname ],

                    			"route_target_list"=>
                               		 {
                                			 "route_target"=> [
								$target
							      ]
				  },

				"network_ipam_refs"=> [{
                                         					  "attr"=> {
                                                 				   	  "ipam_subnets"=> [{
                                                                 				     "subnet"=> {
                                                                                	  	 "gateway_ip" => $gateway,
                                                                                 		 "ip_prefix"=> $pool,
                                                                                 		"ip_prefix_len"=> 24}}]},
                                          					  "to"=> [
                                                				     	"default-domain",
                                                    				     	"default-project",
                                                      				 "default-network-ipam"]}]}
            			   };

		$request  = HTTP::Request->new( POST => $url );
        		$bjson = encode_json $body;
       	 	$request->content_type("application/json");
       	 	$request->header('x-auth-token' => $token_id);
       	 	$request->content($bjson);
        		$http = LWP::UserAgent->new->request($request);

root@server1:~# nova net-list
+--------------------------------------+-------------------------+------+
| ID                                   | Label                   | CIDR |
+--------------------------------------+-------------------------+------+
| 363b4323-69d3-404a-b7b2-6587b4507479 | net6                    | None |
| 274b0b81-52be-48f9-8888-0c6be1d910c2 | net9                    | None |
| 72f26b86-f0bf-44c0-aadb-5f94c34b5eeb | net4                    | None |
| 72be70e4-c0d8-46ce-be8c-33d80f095c5a | default-virtual-network | None |
| aa0f528e-f276-4d5a-a02f-bb02f7289c9c | net10                   | None |
| ce1e9035-9c4d-49de-a867-2f4a27bd5691 | net13                   | None |
| b8599366-f1c0-4c2f-bab2-34533902466d | net12                   | None |
| b8543c48-872d-4e25-9de7-658f304c032a | net7                    | None |
| 34168c65-a4c8-439a-beda-3c7a1f380176 | net3                    | None |
| 7a244326-fc1e-416c-98fb-cc073f8762a0 | test                    | None |
| e7b4e0b9-6fc9-497f-9899-4e2aa344a97b | net11                   | None |
| d669a490-53f4-4fac-bed2-b79fe8538eae | __link_local__          | None |
| f5307953-9490-4da6-b365-7173035d69d3 | net5                    | None |
| a9eac604-a634-43df-8b9f-ea7258941313 | net8                    | None |
| a8363373-548d-4f78-8366-bd0277be8b80 | net1                    | None |
| c4d757cb-d2ab-4334-8e80-029cb0c31610 | ip-fabric               | None |
| fac53b08-59e7-45c6-9ef6-6007160979bb | net2                    | None |
+--------------------------------------+-------------------------+------+
root@ server1:~# 

VM Flavor id/VM Image id/virtual Network id Details:

Before creating the VM we need the following information.There are separate RESTAPI commands available to collect each of this information.

  • VM name
  • VM flavor id
  • VM image id
  • Virtual network id
  • VM security group
  • Tenant name( or project name)

VM Flavor id:

To get the VM flavor id the following code is used.The RESTAPI command “/v1.1/”.$tenant_id.”/flavors” returns the VM flavor id.This RESTAPI command is handled by NOVA component of OpenStack controller.

My $NOVAport         =  "8774";
           My $openstack_ip        =”1.1.1.1”;
	my $headers = "{ 'Content-Type' : 'application/json', 'Accept'  :  'application/json' , 'ser-Agent'  : 'python-novaclient', 'X-Auth-Token'   :    $token_id}";
        $CMDpath= "/v1.1/".$tenant_id."/flavors";
        $APIport=$NOVAport;
        $url= "http://". $openstack_ip.":".$APIport.$CMDpath;
        $request  = HTTP::Request->new( GET => $url );
        $request->header('content-type' => 'application/json');
        $request->header('x-auth-token' => $token_id);
        $http = LWP::UserAgent->new->request($request);
        @y = $http->{_content};
        $mes         = JSON::decode_json($y[0]);
        my $len = @{$mes->{'flavors'}};
        my $flavor_id;
        for (my $x = 0; $x< $len ; ++$x) { if ($mes->{'flavors'}[$x]{'name'} eq $add_vm_flavor) {
                        $flavor_id = $mes->{'flavors'}[$x]{'id'};
                        last;
                }
        }
        print ( "\n\n *******  image id for $add_vm_flavor is $flavor_id ******* \n\n");

VM image id:

To get the image id this code is used.The RESTAPI command “/v1.1/”.$tenant_id.”/images”returns the image id.This RESTAPI command is handled by NOVA component of openstack controller.

my $headers = "{ 'Content-Type' : 'application/json', 'Accept'  :  'application/json' , 'ser-Agent'  : 'python-novaclient', 'X-Auth-Token'   :    $token_id}";
        $CMDpath= "/v1.1/".$tenant_id."/images";
        $APIport=$NOVAport;
        $url= "http://".$cont_ip.":".$APIport.$CMDpath;
        $request  = HTTP::Request->new( GET => $url );
        $request->header('content-type' => 'application/json');
        $request->header('x-auth-token' => $token_id);
        $http = LWP::UserAgent->new->request($request);
        @y = $http->{_content};
        $mes         = JSON::decode_json($y[0]);
        my $len = @{$mes->{'images'}};
        my $image_id;
        for (my $x = 0; $x< $len ; ++$x) { if ($mes->{'images'}[$x]{'name'} eq $add_vm_image ) {
                        $image_id = $mes->{'images'}[$x]{'id'};
                        last;
                }
        }
        print ("\n\n *******  image id for $add_vm_image is $image_id ******* \n\n");

Virtual Network ID:

The RESTAPI command “/v1.1/”.$tenant_id.”/os-tenant-networks” returns the virtual network id.This RESTAPI command is handled by NOVA component of openstack controller.The network id of the networkname “$add_vm_net” can be identified by this code.

my $headers = "{ 'Content-Type' : 'application/json', 'Accept'  :  'application/json' , 'ser-Agent'  : 'python-novaclient', 'X-Auth-Token'   :    $token_id}";
        $CMDpath= "/v1.1/".$tenant_id."/os-tenant-networks";
        $APIport=$NOVAport;
        $url= "http://".$cont_ip.":".$APIport.$CMDpath;
        $request  = HTTP::Request->new( GET => $url );
        $request->header('content-type' => 'application/json');
        $request->header('x-auth-token' => $token_id);
        $http = LWP::UserAgent->new->request($request);
        @y = $http->{_content};
        $mes         = JSON::decode_json($y[0]);
        my $len = @{$mes->{'networks'}};
        my $network_id;
        for (my $x = 0; $x< $len ; ++$x) { if ($mes->{'networks'}[$x]{'label'} eq $add_vm_net ) {
                        $network_id = $mes->{'networks'}[$x]{'id'};
                        last;
                }
        }
        print ("\n\n *******  networks id for $add_vm_net is $network_id ******* \n\n");

VM creation:

Now we reached the final step to create VM.The RESTAPI “/v1.1/”.$tenant_id.”/servers” creates the VM.

The VM name,image id ,flavor id and security group name are required to run this RESTAPI command.

$headers = "{ 'Content-Type' : 'application/json', 'Accept' : 'application/json', 'ser-Agent' : 'python-novaclient', 'X-OpenStack-Nova-API-Version': '2.11', 'X-Auth-Token' : $token_id}";
        $CMDpath = "/v1.1/".$tenant_id."/servers";
        $APIport=$NOVAport;
        $url= "http://".$cont_ip.":".$APIport.$CMDpath;
        $body =
        {       "server" =>
                         {
                                "name" => "$add_vm_name",
                                "imageRef" => "$image_id",
                                "flavorRef" => "$flavor_id",
                                "max_count" => 1,
                                "min_count" => 1,
                                "networks" => [{
                                                "uuid" => "$network_id"
                                }],
                                "security_groups" => [{
                                                "name" => "$add_vm_secgroup"
                                }]
                        }
        };
        $request  = HTTP::Request->new( POST => $url );
        $bjson = encode_json $body;
        $request->content_type("application/json");
        $request->header('x-auth-token' => $token_id);
        $request->content($bjson);
        $http = LWP::UserAgent->new->request($request);

VM status verification:

After creating VM the status of the VM can be verified by the RESTAPI command “/v1.1/”.$tenant_id.”/servers/detail”.This sample code gives details on how to verify status of a VM.It checks for vm_state to be active and power_state to be 1.This RESTAPI command is equivalent to nova list command shown below.

$CMDpath= "/v1.1/".$tenant_id."/servers/detail";
        $APIport=$NOVAport;
        $url= "http://".$cont_ip.":".$APIport.$CMDpath;
        $request  = HTTP::Request->new( GET => $url );
        $request->header('content-type' => 'application/json');
        $request->header('x-auth-token' => $token_id);
        $http = LWP::UserAgent->new->request($request);
        @y = $http->{_content};
        print Dumper($http);
        $mes         = JSON::decode_json($y[0]);
        my $len = @{$mes->{"servers"}};
        my %server_to_netaddr_hash;
        my %test;
        my $servername;
        my $state;
        my $status;
        my $test;
        my $vmcount=0;

	$status = $mes->{"servers"}[$x]{"OS-EXT-STS:vm_state"};
          $state = $mes->{"servers"}[$x]{"OS-EXT-STS:power_state"};
          if ( $status ne "active" || $state != 1) {
        print ("\n\n *******  status/state  of the vm $test is not correct.The current  status is $status and state is $state ******* \n\n");
         return JT::FALSE;
                        }
        print ("\n\n *******  status and state  of the vm $test is correct The current status is $status and state is $state******* \n\n");

                     }

root@ server1:~# nova list
+--------------------------------------+--------+--------+------------+-------------+--------------------+
| ID                                   | Name   | Status | Task State | Power State | Networks           |
+--------------------------------------+--------+--------+------------+-------------+--------------------+
| 935bb371-9fb6-4d1e-92b6-239db2d28a2a | nvmg1  | ACTIVE | -          | Running     | net1=100.0.4.252   |
| 69b9dca5-a4e0-4168-8363-b87caa65e741 | nvmg10 | ACTIVE | -          | Running     | net10=100.0.13.252 |
| 176f9b62-1561-41e9-9c2f-de86f76afffd | nvmg11 | ACTIVE | -          | Running     | net11=100.0.14.252 |
| 15eff465-7251-4de8-b371-cc85790ca9a6 | nvmg12 | ACTIVE | -          | Running     | net12=100.0.15.252 |
| c1be1e20-4969-4911-8fdf-81e09c0023e9 | nvmg13 | ACTIVE | -          | Running     | net13=100.0.16.252 |
| 449becae-69b7-4f57-947a-74d78875ef39 | nvmg2  | ACTIVE | -          | Running     | net2=100.0.5.252   |
| db8c1d5b-5990-458f-bfcb-13a7d2bdbbda | nvmg3  | ACTIVE | -          | Running     | net3=100.0.6.252   |
| a7ceee7e-539a-4398-a768-209db065a71c | nvmg4  | ACTIVE | -          | Running     | net4=100.0.7.252   |
| 43713c5b-c262-4e56-9a77-ffde968f448e | nvmg5  | ACTIVE | -          | Running     | net5=100.0.8.252   |
| 8010f8a0-56d8-4904-a747-8e5dfa1f8ac8 | nvmg6  | ACTIVE | -          | Running     | net6=100.0.9.252   |
| 0c57cb78-922b-4f76-98d5-f962f08a85a6 | nvmg7  | ACTIVE | -          | Running     | net7=100.0.10.252  |
| 47ca6427-c898-4d71-9c2d-61ffa533e31e | nvmg8  | ACTIVE | -          | Running     | net8=100.0.11.252  |
| a08bbaac-3ed9-4cf6-ad6c-def7484a35e4 | nvmg9  | ACTIVE | -          | Running     | net9=100.0.12.252  |
+--------------------------------------+--------+--------+------------+-------------+--------------------+

The status of the VMs can also be checked in OPENSTACK horizon GUI as shown below.

VM Deletion:

Before start deleting the VMs we need to get the token-id from the Openstack server using the procedure given earlier.In addition to this we need to know the VM id.To get the VM id we can use the RESTAPI “/v2/”.$tenant_id.”/servers?name=”.$del_vm_name as shown below.

my $headers = "{ 'Content-Type' : 'application/json', 'Accept'  :  'application/json' , 'ser-Agent'  : 'python-novaclient', 'X-Auth-Token'   :    $token_id}";
        $CMDpath= "/v2/".$tenant_id."/servers?name=".$del_vm_name;
        $APIport=$NOVAport;
        $url= "http://".$cont_ip.":".$APIport.$CMDpath;
        $request  = HTTP::Request->new( GET => $url );
        $request->header('content-type' => 'application/json');
        $request->header('x-auth-token' => $token_id);
        $http = LWP::UserAgent->new->request($request);
        @y = $http->{_content};
        $mes         = JSON::decode_json($y[0]);
        #print "\n\n\n\n\n\---------------\n\n\n\n";
        #print Dumper($mes);
        my $del_vm_id = $mes->{'servers'}[0]{'id'};
        print ( "\n\n *******  delte vm instance id is $del_vm_id ******* \n\n");

After getting the VM ID we can use the RESTAPI “/v1.1/”.$tenant_id.”/servers/”.$del_vm_id.”/action” to delete the VM.This is equivlant to “nova delete <vm name/vm id>” command.

$headers = "{ 'Content-Type' : 'application/json', 'Accept'  :  'application/json' , 'ser-Agent'  : 'python-novaclient', 'X-Auth-Token'   :    $token_id}";
        $CMDpath = "/v1.1/".$tenant_id."/servers/".$del_vm_id."/action";
        $APIport=$NOVAport;
        $url= "http://".$cont_ip.":".$APIport.$CMDpath;
        $body =
        {
               "forceDelete"   =>  "null"
        };
        $request  = HTTP::Request->new( POST => $url );
        $bjson = encode_json $body;
        $request->content_type("application/json");
        $request->header('x-auth-token' => $token_id);
        $request->content($bjson);
        $http = LWP::UserAgent->new->request($request);

Conclusion

This document gives details on CONTRAIL cloud solution implementation. It also explains the RESTAPI details for  VM creation,VM deletion etc..

APPENDIX

The section give details on other RESTAPI commands.

Deleting virtual network:

This command is executed on the contrail controller. To run this command we need virtual network id.

$CMDpath = "/virtual-network/";
        $APIport="8082";
        $url= "http://".$cont_ip.":".$APIport.$CMDpath.$netid;
        $request  = HTTP::Request->new( DELETE => $url );
       $request->header('content-type' => 'application/json');
        $request->header('x-auth-token' => $token_id);
        $http = LWP::UserAgent->new->request($request);

To get the virtual network id this RESTAPI is used.The “uuid” returns the network id.

$CMDpath = "/virtual-networks";
        $APIport="8082";
        $url= "http://".$cont_ip.":".$APIport.$CMDpath;
        $request  = HTTP::Request->new( GET => $url );
        $request->content_type("application/json");
        $request->header('x-auth-token' => $token_id);
        $http = LWP::UserAgent->new->request($request);
         print Dumper $http;
          @y = $http->{_content};
        $mes         = JSON::decode_json($y[0]);
          $len = @{$mes->{"virtual-networks"}};
        my @network_list;
        my $i=1;
        for (my $x = 0; $x< $len ; ++$x) { if ($mes->{"virtual-networks"}[$x]{"fq_name"}[2]  =~ /net\d+/) {
                push (@network_list, $mes->{"virtual-networks"}[$x]{"uuid"});
                $i++;
            }
          }

To delete the ports which map virtual network with the VM we need to use the RESTAPI given below.

We need portid to run this command.

My $NEUTRONport      =  "9696";
         $CMDpath = "/v2.0/ports/";
        $APIport=$NEUTRONport;
        $url= "http://".$cont_ip.":".$APIport.$CMDpath.$portid.".json";
        $request  = HTTP::Request->new( DELETE => $url );
       $request->header('content-type' => 'application/json');
        $request->header('x-auth-token' => $token_id);
        $http = LWP::UserAgent->new->request($request);

The port id can be found from,

$CMDpath= "/v2.0/ports.json";
        $APIport=$NEUTRONport;
        $url= "http://".$cont_ip.":".$APIport.$CMDpath;
        $request  = HTTP::Request->new( GET => $url );
        $request->header('content-type' => 'application/json');
        $request->header('x-auth-token' => $token_id);
        $http = LWP::UserAgent->new->request($request);
        @y = $http->{_content};
        $mes         = JSON::decode_json($y[0]);
        my $len = @{$mes->{"ports"}};
        my @port_list;
        for (my $x = 0; $x< $len ; ++$x) { push (@port_list, $mes->{"ports"}[$x]{"id"});
        }