Create Cloud Machine programmatically

When your business requires cloud services for your applications or infrastructure, then you have to find good cloud provider. Amazon EC2, Tata Insta compute are a good example. Most of the cloud provider uses Apache CloudStack.

If we need 2-3 cloud machines then we can use their interface. But based on business if you need more machines then its painful to create them using their interface. Most of the cloud providers provides API in such cases. So client can create machines automatically.

There are few things which they need for all machines:
– All the machines must be remotely accessible.
– Required application must be installed.
– Some port shall be opened for global access.

All these points if we add in API then we can remote machines with in few minutes.

Amazon EC2 provides a AWS console and AWSSDK to achieve this. But if we go Tata Insta Compute or any other provider then I think it will create complex compared to AWS console.

To automate this manual process for Tata I have written a API which will do all things one by one… Just we have to create a single machine first with all required application. Then create a snapshot of this machines. Note down all the id related to OS, Snapshot, ZONE, Network.

Below script (Apache CloudStack) will handle all the creativity which require API keys of Sandbox or Production account.

public enum MachineState { START = 1, STOP = 2, RESTART = 3 };
    public enum JobType { DEPLOYMACHINE = 1, ACQUIREIP = 2 };

    class Program
    {

        const int ZONEID = 1111;
        const int SERVICEOFFERINGID = 2222;
        const int TEMPLATEID = 3333;
        const int NETWORKIDS = 4444;
        static string[] PORTLIST = { "3389-3389" };

        static void Main(string[] args)
        {
            // Fully qualified URL with http(s)://host:port
            String apiHost = "http://xxxxxxxxxxxxxx.com/client/api";

            // ApiKey and secretKey as given by your InstaCompute vendor
            String apiKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
            String secretKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

            for (int icounter = 1; icounter <= 1; icounter++)
            {
                String jobId = DeployVirtualMachine(apiHost, apiKey, secretKey, "Feb-04-" + icounter);
                Console.WriteLine("DeployVirtualMachine Job ID:" + jobId);
                if (!string.IsNullOrEmpty(jobId))
                {
                    string currentJobIDStatus = "0";
                    int machineID = 0;
                    int ipID = 0;
                    while (currentJobIDStatus == "0")
                    {
                        currentJobIDStatus = CheckJob(apiHost, apiKey, secretKey, Convert.ToInt32(jobId), JobType.DEPLOYMACHINE, out machineID);
                        Console.WriteLine("DeployVirtualMachine Job ID Status:" + currentJobIDStatus);
                        System.Threading.Thread.Sleep(5000);
                    }
                    if (currentJobIDStatus == "1")
                    {
                        jobId = AcuirePublicIP(apiHost, apiKey, secretKey);
                        Console.WriteLine("AcuirePublicIP Job ID:" + jobId);

                        if (!string.IsNullOrEmpty(jobId))
                        {
                            currentJobIDStatus = "0";
                            while (currentJobIDStatus == "0")
                            {
                                currentJobIDStatus = CheckJob(apiHost, apiKey, secretKey, Convert.ToInt32(jobId), JobType.ACQUIREIP, out ipID);
                                Console.WriteLine("AcuirePublicIP Job ID Status:" + currentJobIDStatus);
                                System.Threading.Thread.Sleep(5000);
                            }
                            Console.WriteLine("MachineID :" + machineID);
                            Console.WriteLine("IPID :" + ipID);

                            if (machineID > 0 && ipID > 0 && currentJobIDStatus == "1")
                            {
                                Console.WriteLine("MapPublicIPWithMachine.");
                                MapPublicIPWithMachine(apiHost, apiKey, secretKey, ipID, machineID);
                            }
                        }
                    }
                }
            }

       }

        protected static string parseUrl(string url)
        {
            System.Net.WebClient webdata = new System.Net.WebClient();

            //the below statement assigns byte[]
            byte[] bytes = webdata.DownloadData(url);

            //the below code converts byte[] type string type
            return System.Text.Encoding.GetEncoding("utf-8").GetString(bytes);
        }

        protected static string GetEncodedValue(string data)
        {
            return HttpUtility.UrlEncode(data, System.Text.Encoding.UTF8);
        }

        /**
        * 1. Signs a string with a secret key using SHA-1
        * 2. Base64 encode the result
        * 3. URL encode the final result
        *
        * @param request
        * @param key
        * @return
        */
        protected static String signRequest(String data, String key)
        {
            string canonicalString = data;
            // now encode the canonical string
            Encoding ae = new UTF8Encoding();
            // create a hashing object
            HMACSHA1 signature = new HMACSHA1();
            // secretId is the hash key
            signature.Key = ae.GetBytes(key);
            byte[] bytes = ae.GetBytes(canonicalString);
            byte[] moreBytes = signature.ComputeHash(bytes);
            // convert the hash byte array into a base64 encoding
            return Convert.ToBase64String(moreBytes);
        }

        protected static void List(string apiHost, string apiKey, string secretKey, string apiCommand)
        {
            // Step 1: Make sure your APIKey is toLowerCased and URL encoded
            String encodedApiKey = GetEncodedValue(apiKey.ToLower());

            // Step 2: toLowerCase all the parameters, URL encode each parameter value,
            // and the sort the parameters in alphabetical order
            // Please note that if any parameters with a '&' as a value will cause
            // this test client to fail since we are using '&' to delimit
            // the string
            ArrayList sortedParams = new ArrayList();
            sortedParams.Add("apikey=" + encodedApiKey);
            sortedParams.Add("command=" + GetEncodedValue(apiCommand.ToLower()));

            sortedParams.Sort();

            // Step 3: Construct the sorted URL and sign and URL encode
            // the sorted URL with your secret key
            String sortedUrl = null;
            bool first = true;
            foreach (String param in sortedParams)
            {
                if (first)
                {
                    sortedUrl = param;
                    first = false;
                }
                else
                {
                    sortedUrl = sortedUrl + "&" + param;
                }
            }

            String encodedSignature = GetEncodedValue(signRequest(sortedUrl, secretKey));

            // Step 4: Construct the final URL we want to send to the
            // InstaCompute Management Server
            // Final result should look like:
            // http(s)://://client/api?&apiKey=&signature=
            String finalUrl = apiHost + "?command=" + apiCommand + "&apiKey=" + apiKey + "&signature="
              + encodedSignature;

            string response = parseUrl(finalUrl);
        }


        protected static void ListTemplates(string apiHost, string apiKey, string secretKey)
        {
            string apiCommand = "listTemplates";
            // Step 1: Make sure your APIKey is toLowerCased and URL encoded
            String encodedApiKey = GetEncodedValue(apiKey.ToLower());

            // Step 2: toLowerCase all the parameters, URL encode each parameter value,
            // and the sort the parameters in alphabetical order
            // Please note that if any parameters with a '&' as a value will cause
            // this test client to fail since we are using '&' to delimit
            // the string
            ArrayList sortedParams = new ArrayList();
            sortedParams.Add("apikey=" + encodedApiKey);
            sortedParams.Add("command=" + GetEncodedValue(apiCommand.ToLower()));
            sortedParams.Add("templatefilter=" + GetEncodedValue("selfexecutable".ToLower()));

            sortedParams.Sort();

            // Step 3: Construct the sorted URL and sign and URL encode
            // the sorted URL with your secret key
            String sortedUrl = null;
            bool first = true;
            foreach (String param in sortedParams)
            {
                if (first)
                {
                    sortedUrl = param;
                    first = false;
                }
                else
                {
                    sortedUrl = sortedUrl + "&" + param;
                }
            }

            String encodedSignature = GetEncodedValue(signRequest(sortedUrl, secretKey));

            // Step 4: Construct the final URL we want to send to the
            // InstaCompute Management Server
            // Final result should look like:
            // http(s)://://client/api?&apiKey=&signature=
            String finalUrl = apiHost + "?command=" + apiCommand + "&templateFilter=selfexecutable&apiKey=" + apiKey + "&signature="
              + encodedSignature;

            string response = parseUrl(finalUrl);
        }



        protected static void ListVirtualMachines(string apiHost, string apiKey, string secretKey)
        {
            string apiCommand = "listVirtualMachines";
            // Step 1: Make sure your APIKey is toLowerCased and URL encoded
            String encodedApiKey = GetEncodedValue(apiKey.ToLower());

            // Step 2: toLowerCase all the parameters, URL encode each parameter value,
            // and the sort the parameters in alphabetical order
            // Please note that if any parameters with a '&' as a value will cause
            // this test client to fail since we are using '&' to delimit
            // the string
            ArrayList sortedParams = new ArrayList();
            sortedParams.Add("apikey=" + encodedApiKey);
            sortedParams.Add("command=" + GetEncodedValue(apiCommand.ToLower()));

            sortedParams.Sort();

            // Step 3: Construct the sorted URL and sign and URL encode
            // the sorted URL with your secret key
            String sortedUrl = null;
            bool first = true;
            foreach (String param in sortedParams)
            {
                if (first)
                {
                    sortedUrl = param;
                    first = false;
                }
                else
                {
                    sortedUrl = sortedUrl + "&" + param;
                }
            }

            String encodedSignature = GetEncodedValue(signRequest(sortedUrl, secretKey));

            // Step 4: Construct the final URL we want to send to the
            // InstaCompute Management Server
            // Final result should look like:
            // http(s)://://client/api?&apiKey=&signature=
            String finalUrl = apiHost + "?command=" + apiCommand + "&apiKey=" + apiKey + "&signature="
              + encodedSignature;

            string response = parseUrl(finalUrl);

          }

        protected static string AcuirePublicIP(string apiHost, string apiKey, string secretKey)
        {
            string apiCommand = "associateIpAddress";

            // Step 1: Make sure your APIKey is toLowerCased and URL encoded
            String encodedApiKey = GetEncodedValue(apiKey.ToLower());

            // Step 2: toLowerCase all the parameters, URL encode each parameter value,
            // and the sort the parameters in alphabetical order
            // Please note that if any parameters with a '&' as a value will cause
            // this test client to fail since we are using '&' to delimit
            // the string
            ArrayList sortedParams = new ArrayList();
            sortedParams.Add("apikey=" + encodedApiKey);
            sortedParams.Add("command=" + GetEncodedValue(apiCommand.ToLower()));
            sortedParams.Add("zoneid=" + ZONEID);

            sortedParams.Sort();

            // Step 3: Construct the sorted URL and sign and URL encode
            // the sorted URL with your secret key
            String sortedUrl = null;
            bool first = true;
            foreach (String param in sortedParams)
            {
                if (first)
                {
                    sortedUrl = param;
                    first = false;
                }
                else
                {
                    sortedUrl = sortedUrl + "&" + param;
                }
            }

            String encodedSignature = GetEncodedValue(signRequest(sortedUrl, secretKey));

            // Step 4: Construct the final URL we want to send to the
            // InstaCompute Management Server
            // Final result should look like:
            // http(s)://://client/api?&apiKey=&signature=
            String finalUrl = apiHost + "?command=" + apiCommand + "&zoneId=" + ZONEID + "&apiKey=" + apiKey + "&signature=" + encodedSignature; ;

            string response = parseUrl(finalUrl);

            XDocument xdoc = XDocument.Parse(response, LoadOptions.PreserveWhitespace);

            return (from xmlData in xdoc.Descendants("jobid")
                    select xmlData.Value).FirstOrDefault();
        }

        protected static void MapPublicIPWithMachine(string apiHost, string apiKey, string secretKey, int publicIP, int machineID)
        {
            string apiCommand = "createPortForwardingRule";
            int ipaddressid = publicIP;
            
            string protocol = "tcp";
            int virtualmachineid = machineID;
            int networkid = NETWORKIDS;

            foreach (string port in PORTLIST)
            {
                string[] portRange = port.Split('-');
                // Step 1: Make sure your APIKey is toLowerCased and URL encoded
                String encodedApiKey = GetEncodedValue(apiKey.ToLower());

                // Step 2: toLowerCase all the parameters, URL encode each parameter value,
                // and the sort the parameters in alphabetical order
                // Please note that if any parameters with a '&' as a value will cause
                // this test client to fail since we are using '&' to delimit
                // the string
                ArrayList sortedParams = new ArrayList();
                sortedParams.Add("apikey=" + encodedApiKey);
                sortedParams.Add("command=" + GetEncodedValue(apiCommand.ToLower()));
                sortedParams.Add("ipaddressid=" + ipaddressid);
                sortedParams.Add("networkid=" + networkid);
                sortedParams.Add("privateport=" + portRange[0]);
                sortedParams.Add("protocol=" + protocol);
                sortedParams.Add("publicport=" + portRange[0]);
                sortedParams.Add("privateendport=" + portRange[1]);
                sortedParams.Add("publicendport=" + portRange[1]);
                sortedParams.Add("virtualmachineid=" + virtualmachineid);

                sortedParams.Sort();

                // Step 3: Construct the sorted URL and sign and URL encode
                // the sorted URL with your secret key
                String sortedUrl = null;
                bool first = true;
                foreach (String param in sortedParams)
                {
                    if (first)
                    {
                        sortedUrl = param;
                        first = false;
                    }
                    else
                    {
                        sortedUrl = sortedUrl + "&" + param;
                    }
                }

                String encodedSignature = GetEncodedValue(signRequest(sortedUrl, secretKey));

                // Step 4: Construct the final URL we want to send to the
                // InstaCompute Management Server
                // Final result should look like:
                // http(s)://://client/api?&apiKey=&signature=
                String finalUrl = apiHost + "?command=" + apiCommand + "&ipaddressid=" + ipaddressid + "&networkid=" + networkid + "&privateport=" + portRange[0] + "&protocol=" + protocol + "&publicport=" + portRange[0] + "&privateendport=" + portRange[1] + "&publicendport=" + portRange[1] + "&virtualmachineid=" + virtualmachineid + "&apiKey=" + apiKey + "&signature=" + encodedSignature;

                string response = parseUrl(finalUrl);

                XDocument xdoc = XDocument.Parse(response, LoadOptions.PreserveWhitespace);
            }
        }

        protected static string DeployVirtualMachine(string apiHost, string apiKey, string secretKey, string displayName)
        {
            string apiCommand = "deployVirtualMachine";
            displayName = GetEncodedValue(displayName);
            // Step 1: Make sure your APIKey is toLowerCased and URL encoded
            String encodedApiKey = GetEncodedValue(apiKey.ToLower());

            // Step 2: toLowerCase all the parameters, URL encode each parameter value,
            // and the sort the parameters in alphabetical order
            // Please note that if any parameters with a '&' as a value will cause
            // this test client to fail since we are using '&' to delimit
            // the string
            ArrayList sortedParams = new ArrayList();
            sortedParams.Add("apikey=" + encodedApiKey);
            sortedParams.Add("command=" + GetEncodedValue(apiCommand.ToLower()));
            sortedParams.Add("displayname=" + GetEncodedValue(displayName.ToLower()));
            sortedParams.Add("networkids=" + NETWORKIDS);
            sortedParams.Add("serviceofferingid=" + SERVICEOFFERINGID);
            sortedParams.Add("templateid=" + TEMPLATEID);
            sortedParams.Add("zoneid=" + ZONEID);

            sortedParams.Sort();

            // Step 3: Construct the sorted URL and sign and URL encode
            // the sorted URL with your secret key
            String sortedUrl = null;
            bool first = true;
            foreach (String param in sortedParams)
            {
                if (first)
                {
                    sortedUrl = param;
                    first = false;
                }
                else
                {
                    sortedUrl = sortedUrl + "&" + param;
                }
            }

            String encodedSignature = GetEncodedValue(signRequest(sortedUrl, secretKey));

            // Step 4: Construct the final URL we want to send to the
            // InstaCompute Management Server
            // Final result should look like:
            // http(s)://://client/api?&apiKey=&signature=
            String finalUrl = apiHost + "?command=" + apiCommand + "&zoneId=" + ZONEID + "&serviceOfferingId=" + SERVICEOFFERINGID + "&templateId=" + TEMPLATEID + "&networkIds=" + NETWORKIDS + "&displayName=" + displayName + "&apiKey=" + apiKey + "&signature=" + encodedSignature; ;

            string response = parseUrl(finalUrl);

            XDocument xdoc = XDocument.Parse(response, LoadOptions.PreserveWhitespace);

            return (from xmlData in xdoc.Descendants("jobid")
                    select xmlData.Value).FirstOrDefault();
        }

        protected static string ChangeVirtualMachineState(string apiHost, string apiKey, string secretKey, int hostID, MachineState toState)
        {
            string apiCommand = string.Empty;
            switch (toState)
            {
                case MachineState.START:
                    apiCommand = "startVirtualMachine";
                    break;
                case MachineState.STOP:
                    apiCommand = "stopVirtualMachine";
                    break;
                case MachineState.RESTART:
                    apiCommand = "rebootVirtualMachine";
                    break;

            }
            // Step 1: Make sure your APIKey is toLowerCased and URL encoded
            String encodedApiKey = GetEncodedValue(apiKey.ToLower());

            // Step 2: toLowerCase all the parameters, URL encode each parameter value,
            // and the sort the parameters in alphabetical order
            // Please note that if any parameters with a '&' as a value will cause
            // this test client to fail since we are using '&' to delimit
            // the string
            ArrayList sortedParams = new ArrayList();
            sortedParams.Add("apikey=" + encodedApiKey);
            sortedParams.Add("command=" + GetEncodedValue(apiCommand.ToLower()));
            sortedParams.Add("id=" + hostID);

            sortedParams.Sort();

            // Step 3: Construct the sorted URL and sign and URL encode
            // the sorted URL with your secret key
            String sortedUrl = null;
            bool first = true;
            foreach (String param in sortedParams)
            {
                if (first)
                {
                    sortedUrl = param;
                    first = false;
                }
                else
                {
                    sortedUrl = sortedUrl + "&" + param;
                }
            }

            String encodedSignature = GetEncodedValue(signRequest(sortedUrl, secretKey));

            // Step 4: Construct the final URL we want to send to the
            // InstaCompute Management Server
            // Final result should look like:
            // http(s)://://client/api?&apiKey=&signature=
            String finalUrl = apiHost + "?command=" + apiCommand + "&id=" + hostID + "&apiKey=" + apiKey + "&signature="
              + encodedSignature;

            string response = parseUrl(finalUrl);

            XDocument xdoc = XDocument.Parse(response, LoadOptions.PreserveWhitespace);

            return (from xmlData in xdoc.Descendants("jobid")
                    select xmlData.Value).FirstOrDefault();
        }


        protected static string CheckJob(string apiHost, string apiKey, string secretKey, int jobID, JobType jobType, out int ID)
        {
            ID = 0;
            string apiCommand = "queryAsyncJobResult";
            // Step 1: Make sure your APIKey is toLowerCased and URL encoded
            String encodedApiKey = GetEncodedValue(apiKey.ToLower());

            // Step 2: toLowerCase all the parameters, URL encode each parameter value,
            // and the sort the parameters in alphabetical order
            // Please note that if any parameters with a '&' as a value will cause
            // this test client to fail since we are using '&' to delimit
            // the string
            ArrayList sortedParams = new ArrayList();
            sortedParams.Add("apikey=" + encodedApiKey);
            sortedParams.Add("command=" + GetEncodedValue(apiCommand.ToLower()));
            sortedParams.Add("jobid=" + jobID);

            sortedParams.Sort();

            // Step 3: Construct the sorted URL and sign and URL encode
            // the sorted URL with your secret key
            String sortedUrl = null;
            bool first = true;
            foreach (String param in sortedParams)
            {
                if (first)
                {
                    sortedUrl = param;
                    first = false;
                }
                else
                {
                    sortedUrl = sortedUrl + "&" + param;
                }
            }

            String encodedSignature = GetEncodedValue(signRequest(sortedUrl, secretKey));

            // Step 4: Construct the final URL we want to send to the
            // InstaCompute Management Server
            // Final result should look like:
            // http(s)://://client/api?&apiKey=&signature=
            String finalUrl = apiHost + "?command=" + apiCommand + "&jobId=" + jobID + "&apiKey=" + apiKey + "&signature="
              + encodedSignature;

            string response = parseUrl(finalUrl);

            XDocument xdoc = XDocument.Parse(response, LoadOptions.PreserveWhitespace);

            var jobStatus = (from xmlData in xdoc.Descendants("jobstatus")
                             select xmlData.Value).FirstOrDefault();

            if (jobStatus == "0")
            {
                return jobStatus;
            }
            if (jobStatus == "1")
            {
                string query = string.Empty;
                switch (jobType)
                {
                    case JobType.DEPLOYMACHINE:
                        var newMachine = (from xmlData in xdoc.Descendants("virtualmachine")
                                          select new CloudVirtualMachine
                                          {
                                              Account = xmlData.Element("account").Value,
                                              ID = Convert.ToInt32(xmlData.Element("id").Value),
                                              Name = xmlData.Element("name").Value,
                                              DisplayName = xmlData.Element("displayname").Value,
                                          }).ToList();
                        foreach (CloudVirtualMachine cvm in newMachine)
                        {
                            ID = cvm.ID;
                        }
                        break;
                    case JobType.ACQUIREIP:
                        var newIP = (from xmlData in xdoc.Descendants("jobresult").Elements("ipaddress")

                                     select new CloudIP
                                     {
                                         Account = xmlData.Element("account").Value,
                                         ID = Convert.ToInt32(xmlData.Element("id").Value),
                                         IPAddress = xmlData.Element("ipaddress").Value,
                                     }).ToList();
                        foreach (CloudIP cip in newIP)
                        {
                            ID = cip.ID;
                        }
                        break;
                }
            }
            return jobStatus;
        }    

       
    }

    public class CloudVirtualMachine
    {
        public String Account { get; set; }
        public int ID { get; set; }
        public String Name { get; set; }
        public String DisplayName { get; set; }
        public int DomainID { get; set; }
        public String Domain { get; set; }
        public DateTime Created { get; set; }
        public string State { get; set; }
        public int Groupid { get; set; }
        public String Group { get; set; }
        public int ZoneID { get; set; }
        public String ZoneName { get; set; }
        public int TemplateID { get; set; }
        public String TemplateName { get; set; }
        public String TemplateDisplayText { get; set; }
        public bool PasswordEnabled { get; set; }
        public int ServiceOfferingID { get; set; }
        public String ServiceOfferingName { get; set; }
        public int CpuNumber { get; set; }
        public int CpuSpeed { get; set; }
        public int Memory { get; set; }
        public int GuestOSID { get; set; }
        public string Hypervisor { get; set; }
    }

    public class CloudIP
    {
        public String Account { get; set; }
        public int ID { get; set; }
        public int DomainID { get; set; }
        public String Domain { get; set; }
        public String IPAddress { get; set; }
        public String VirtualMachineID { get; set; }
        public String VirtualMachineName { get; set; }
        public String VirtualMachineDisplayName { get; set; }
    }

How to export schema of MYSQL Database?

If you need schema of your MYSQL database for backup or any copy database to another server, then you must need schema with or without data.

GUI tools like SQLYog, WebYog or PHPmyAdmin will best example for that. But if you need any command or utility then MYSQLDUMP has most important role.

For using mysqldump you can export schema as well as data with it.


mysqldump -u root -p –no-data [mydatabase] > myschema.sql

How To Split Pdf Documents Using ITextSharp in C#

In Today?s life cycle PDF has a important role because it doesn?t require any special package to be installed to view it on system, mobile devices, IPOD or IPAD.

Sometimes pdf documents have scanned images, large text data. We need to extract some of the pages for sharing with someone else i.e. friends or any team members. ItextSharp can help us to achieve this.

Following is the sample code which can split the pdf pages to individual file.

using (PdfReader reader = new PdfReader(pdfFileName))
{
for (int pagenumber = 1; pagenumber <= reader.NumberOfPages; pagenumber++)
{
string filename = pagenumber.ToString() + ".pdf";

Document document = new Document();
PdfCopy pdfCopy = new PdfCopy(document, new FileStream(@"c:\temp\" + filename, FileMode.Create));

document.Open();

pdfCopy.AddPage(copy.GetImportedPage(reader, pagenumber));

document.Close();
}
}