{ "metadata": { "name": "Tutorial - Deploying Windows and Linux VMs" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": "# Deploying Windows and Linux VMs\n\nThis tutorial shows how to create a number of VMs with mixed OS." }, { "cell_type": "markdown", "metadata": {}, "source": "## Specify the number of VMs\n\nWe expect to have 5 mixed VMs including 2 Windows Server VMs and 3 Ubuntu VMs. \nNUM_W indicates the number of Windows VMs, \nNUM_L indicates the number of Linux VMs below. \n\n*If you made changes, plese make sure you run the selected IPython Notebook cell by 'ctrl + Enter'*" }, { "cell_type": "code", "collapsed": false, "input": "NUM_W = 2\nNUM_L = 3\n\nNUM = NUM_W + NUM_L", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "markdown", "metadata": {}, "source": "## Initialize azure SDK\n\nIt is about setting credentials and obtaining access, etc.\nFor the rest of the parts, there is not much thing that you have to change but it might be important to understand how it works." }, { "cell_type": "code", "collapsed": false, "input": "from azure import *", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 58 }, { "cell_type": "code", "collapsed": false, "input": "import os\nimport json\n\nclass Credentials(object):\n '''\n Azure credentials needed to run Azure.\n '''\n def __init__(self):\n configFilename = os.environ[\"HOME\"] + \"/.azure/config.json\"\n tmpName = os.path.join(os.getcwd(), configFilename)\n \n if not os.path.exists(tmpName):\n errMsg = \"Cannot run Azure when the expected config file containing Azure credentials, '%s', does not exist!\" % (tmpName)\n raise EnvironmentError(errMsg)\n\n with open(tmpName, \"r\") as f:\n self.ns = json.load(f)\n self.config_path = os.path.dirname(tmpName)\n\n def getManagementCertFile(self):\n try:\n return self.ns[u'managementcertfile'] \n except:\n return self.config_path + \"/managementCertificate.pem\"\n def getSubscriptionId(self):\n return self.ns[u'subscriptionid'] \n\n def getSubscription(self):\n return self.ns[u'subscription'] \n \n def getServiceBusKey(self):\n return self.ns[u'servicebuskey'] \n\n def getServiceBusNamespace(self):\n return self.ns[u'servicebusns']\n\n def getStorageServicesKey(self):\n return self.ns[u'storageserviceskey']\n\n def getStorageServicesName(self):\n return self.ns[u'storageservicesname']\n\n def getLinuxOSVHD(self):\n return self.ns[u'linuxosvhd']\n\n def getProxyHost(self):\n return self.ns[u'proxyhost']\n\n def getProxyPort(self):\n return self.ns[u'proxyport']", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 59 }, { "cell_type": "code", "collapsed": false, "input": "cert = Credentials()\n\nsubscription_id = cert.getSubscription()\ncertificate_path = cert.getManagementCertFile()", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 60 }, { "cell_type": "code", "collapsed": false, "input": "from azure.servicemanagement import *\n\nsms = ServiceManagementService(subscription_id, certificate_path)", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 61 }, { "cell_type": "code", "collapsed": false, "input": "name = 'myvm-cluster-'\n# In my case, I need to use 'Central US' location instead of 'West US' due to the location constraint of my subscription.\nlocation = \"Central US\"", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 62 }, { "cell_type": "markdown", "metadata": {}, "source": "## Get image names for Windows and Linux OS\nlinux_image_name will be set for an image name of latest Ubuntu 12.04 \nwindow_image_name will be set for an image name of Windows Server 2008 R2 SP1." }, { "cell_type": "code", "collapsed": false, "input": "result = sms.list_os_images()\nfor image in result:\n if image.os == \"Linux\":\n if image.category == \"Canonical\":\n try:\n if image.label.index(\"12.04\"):\n linux_image_name = image.name\n except:\n pass\n elif image.os == \"Windows\":\n if image.category == \"Microsoft Windows Server Group\":\n try:\n if image.label.index(\"2008 R2 SP1\"):\n window_image_name = image.name\n except:\n pass", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 63 }, { "cell_type": "code", "collapsed": false, "input": "result = sms.list_storage_accounts()\nfor account in result:\n storage_account = account.service_name", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 64 }, { "cell_type": "code", "collapsed": false, "input": "container = \"cluster\"\nblob_l = \"ubuntu-12-04.vhd\"\nblob_w = \"Win2K8R2SP1.vhd\"", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 65 }, { "cell_type": "code", "collapsed": false, "input": "windows_blob_url = \"blob.core.windows.net\"\n#media_link = \"http://\" + storage_account + \".\" + windows_blob_url + \"/\" + container + \"/\" + blob", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 66 }, { "cell_type": "code", "collapsed": false, "input": "#os_hd = OSVirtualHardDisk(image_name, media_link)", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 67 }, { "cell_type": "code", "collapsed": false, "input": "linux_user_id = 'azureuser'\nlinux_user_passwd = 'mypassword1234@'\nlinux_config = LinuxConfigurationSet(name, linux_user_id, linux_user_passwd, False)", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 68 }, { "cell_type": "code", "collapsed": false, "input": "window_user_passwd = linux_user_passwd\ntzone = 'Pacific Standard Time'\nwindow_config = WindowsConfigurationSet(computer_name=name, \n admin_password=window_user_passwd, \n reset_password_on_first_logon=False, \n enable_automatic_updates=False, \n time_zone=tzone)", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 69 }, { "cell_type": "code", "collapsed": false, "input": "azure_config = os.environ[\"HOME\"] + '/.azure'\nthumbprint_path = azure_config + '/.ssh/thumbprint'\nauthorized_keys = \"/home/\" + linux_user_id + \"/.ssh/authorized_keys\"", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 70 }, { "cell_type": "code", "collapsed": false, "input": "try:\n thumbprint=open(thumbprint_path, 'r').readline().split('\\n')[0]\nexcept:\n thumbprint=None", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 71 }, { "cell_type": "code", "collapsed": false, "input": "publickey = PublicKey(thumbprint, authorized_keys)\n#keypair = KeyPair(thumbprint, key_pair_path)\n\nlinux_config.ssh.public_keys.public_keys.append(publickey)\n#linux_config.ssh.key_pairs.key_pairs.append(keypair)", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 72 }, { "cell_type": "markdown", "metadata": {}, "source": "## Configure certificate for Windows" }, { "cell_type": "code", "collapsed": false, "input": "window_config.domain_join = None\nwindow_config.stored_certificate_settings.stored_certificate_settings.append(CertificateSetting(thumbprint=thumbprint, store_name='My', store_location='LocalMachine'))", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 73 }, { "cell_type": "code", "collapsed": false, "input": "network = ConfigurationSet()\nnetwork.configuration_set_type = 'NetworkConfiguration'\nnetwork.input_endpoints.input_endpoints.append(ConfigurationSetInputEndpoint('ssh', 'tcp', '22', '22'))", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 74 }, { "cell_type": "code", "collapsed": false, "input": "import base64\ncert_data_path = azure_config + \"/.ssh/myCert.pfx\"\nwith open(cert_data_path, \"rb\") as bfile:\n cert_data = base64.b64encode(bfile.read())", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 75 }, { "cell_type": "code", "collapsed": false, "input": "cert_format = 'pfx'\ncert_password = ''", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 76 }, { "cell_type": "code", "collapsed": false, "input": "from time import sleep", "language": "python", "metadata": {}, "outputs": [], "prompt_number": 77 }, { "cell_type": "code", "collapsed": false, "input": "%time\nresults = []\nresults_cert = []\nlinux_cnt = 0\nfor num in range(NUM):\n new_name = name + str(num)\n if linux_cnt < NUM_L:\n image_name = linux_image_name\n blob = blob_l\n sys_config = linux_config\n linux_cnt += 1\n continue\n else:\n image_name = window_image_name\n blob = blob_w \n sys_config = window_config\n media_link = \"http://\" + storage_account + \".\" + windows_blob_url + \"/\" + container + \"/0-\" + new_name + \"-\" + blob\n res = sms.create_hosted_service(service_name=new_name, label=new_name, location=location)\n sleep(5)\n os_hd = OSVirtualHardDisk(image_name, media_link)\n result_cert = sms.add_service_certificate(service_name=new_name,\n data=cert_data,\n certificate_format=cert_format,\n password=cert_password)\n print new_name\n try:\n print vars(result_cert)\n except:\n print result_cert\n sleep(5)\n result = sms.create_virtual_machine_deployment(service_name=new_name,\n deployment_name=new_name,\n deployment_slot='production',\n label=new_name,\n role_name=new_name,\n system_config=sys_config,\n os_virtual_hard_disk=os_hd,\n network_config=network,\n role_size='Small')\n results.append(result)\n results_cert.append(result_cert)", "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": "CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s\nWall time: 0.00 s\nmyvm-cluster-3" }, { "output_type": "stream", "stream": "stdout", "text": "\n{'request_id': '5b46797d3fdf467eb25be36b309a7a7a'}\nmyvm-cluster-4" }, { "output_type": "stream", "stream": "stdout", "text": "\n{'request_id': '34917e9844bb42feb3e63492ca2dc474'}\n" } ], "prompt_number": 81 }, { "cell_type": "code", "collapsed": false, "input": "for result in results:\n request_id = result.request_id\n status = sms.get_operation_status(request_id)\n try:\n print vars(status.error)\n except:\n print vars(status)", "language": "python", "metadata": {}, "outputs": [] } ], "metadata": {} } ] }