Skip to content

Instantly share code, notes, and snippets.

@ogrisel
Created April 8, 2013 21:43
Show Gist options
  • Select an option

  • Save ogrisel/5340771 to your computer and use it in GitHub Desktop.

Select an option

Save ogrisel/5340771 to your computer and use it in GitHub Desktop.
Tentative python script to provision a linux vm on Azure
#!/usr/bin/env python
import os
import sys
import logging
from azure import WindowsAzureConflictError
from azure import WindowsAzureError
from azure.servicemanagement import ServiceManagementService
from azure.servicemanagement import OSVirtualHardDisk
from azure.servicemanagement import LinuxConfigurationSet
from azure.storage import BlobService
FORMAT = '%(levelname)-8s %(asctime)-15s %(message)s'
logging.basicConfig(level=logging.INFO, format=FORMAT)
log = logging.getLogger()
subscription_id = os.environ['AZURE_SUBSCRIPTION_ID']
location = os.environ.get('AZURE_DEFAULT_LOCATION', 'West US')
role_size = os.environ.get('AZURE_DEFAULT_ROLE_SIZE', 'Small')
# Choose the latest ubuntu from sms.list_os_images()
image_name = ('b39f27a8b8c64d52b05eac6a62ebad85'
'__Ubuntu-12_10-amd64-server-20130227-en-us-30GB')
certificate_path = os.path.expanduser('~/mycert.pem')
# Connect to the Azure platform and check that the location is valid
log.info("Checking availability of location: '%s'", location)
sms = ServiceManagementService(subscription_id, certificate_path)
assert location in [l.name for l in sms.list_locations()]
# Provision an hosted service
service_name = sys.argv[1]
affinity_group = service_name
target_blob_name = service_name + ".vhd"
service_label = service_name
description = 'Provisioning test from the Windows Azure Python SDK'
# Create an affinity group for all the services related to this project
log.info("Checking availability of affinity group: '%s'", affinity_group)
if affinity_group not in [ag.name for ag in sms.list_affinity_groups()]:
try:
log.info("Creating new affinity_group: '%s'", affinity_group)
sms.create_affinity_group(affinity_group, service_label, location,
description)
except WindowsAzureConflictError:
log.error("Affinity Group '%s' has already been provisioned")
sys.exit(1)
# Provision de hosted service itself if not already existing
log.info("Checking availability of hosted service: '%s'", service_name)
if service_name not in [s.service_name for s in sms.list_hosted_services()]:
try:
log.info("Creating new hosted service: '%s'", service_name)
sms.create_hosted_service(service_name, service_label, description,
affinity_group=affinity_group)
except WindowsAzureConflictError:
log.error("Hosted service '%s' has already been provisioned"
" by another user.", service_name)
sys.exit(1)
cloud_service = sms.get_hosted_service_properties(service_name)
log.info("Using hosted service '%s' at: %s", service_name, cloud_service.url)
# Create the OS image
# Create a storage account if none is found for the given service
log.info("Checking availability of storage account: '%s'", service_name)
storage_accounts = [sa.service_name for sa in sms.list_storage_accounts()]
if service_name not in storage_accounts:
try:
log.info("Creating new storage account: '%s'", service_name)
sms.create_storage_account(service_name,
"Blob store for " + service_name, service_label,
affinity_group=affinity_group)
except WindowsAzureConflictError:
log.error("Storage Account '%s' has already been provisioned"
" by another user.", service_name)
sys.exit(1)
log.info("Fetching keys for storage account: '%s'", service_name)
keys = sms.get_storage_account_keys(service_name)
blob_service = BlobService(account_name=service_name,
account_key=keys.storage_service_keys.primary)
blob_service.create_container('osimage')
os_image_url = "http://{}.blob.core.windows/osimage/{}".format(
service_name, target_blob_name)
# XXX: change the password: read it from os.environ or generate a random one
# to be printed on stdout
linux_config = LinuxConfigurationSet('hostname', 'username', 'secretA1,!', True)
# linux_config.ssh = None
log.info("Using OS image at: %s", os_image_url)
os_hd = OSVirtualHardDisk(image_name, os_image_url, disk_label=target_blob_name)
log.info("Provisioning virtual machine deployment %s", service_name)
sms.create_virtual_machine_deployment(
service_name=service_name,
deployment_name=service_name,
deployment_slot='production',
label=service_label,
role_name=service_name,
system_config=linux_config,
os_virtual_hard_disk=os_hd,
role_size=role_size)
@ogrisel
Copy link
Author

ogrisel commented Apr 8, 2013

When running this I get:

$ python provision.py ogriseltest3
INFO     2013-04-08 23:53:53,890 Checking availability of location: 'West Europe'
INFO     2013-04-08 23:53:56,060 Checking availability of affinity group: 'ogriseltest3'
INFO     2013-04-08 23:53:58,418 Checking availability of hosted service: 'ogriseltest3'
INFO     2013-04-08 23:54:01,588 Using hosted service 'ogriseltest3' at: https://management.core.windows.net/15261ec6-ba42-4adc-acb1-3c2d046c67e7/services/hostedservices/ogriseltest3
INFO     2013-04-08 23:54:01,588 Checking availability of storage account: 'ogriseltest3'
INFO     2013-04-08 23:54:04,157 Fetching keys for storage account: 'ogriseltest3'
INFO     2013-04-08 23:54:06,522 Using OS image at: http://ogriseltest3.blob.core.windows/osimage/ogriseltest3.vhd
INFO     2013-04-08 23:54:06,522 Provisioning virtual machine deployment ogriseltest3
Traceback (most recent call last):
  File "provision.py", line 111, in <module>
    role_size=role_size)
  File "/usr/local/lib/python2.7/site-packages/azure/servicemanagement/servicemanagementservice.py", line 905, in create_virtual_machine_deployment
    async=True)
  File "/usr/local/lib/python2.7/site-packages/azure/servicemanagement/servicemanagementservice.py", line 1413, in _perform_post
    response = self._perform_request(request)
  File "/usr/local/lib/python2.7/site-packages/azure/servicemanagement/servicemanagementservice.py", line 1375, in _perform_request
    return _management_error_handler(e)
  File "/usr/local/lib/python2.7/site-packages/azure/servicemanagement/__init__.py", line 670, in _management_error_handler
    return _general_error_handler(http_error)
  File "/usr/local/lib/python2.7/site-packages/azure/__init__.py", line 645, in _general_error_handler
    raise WindowsAzureError(_ERROR_UNKNOWN % http_error.message + '\n' + http_error.respbody)
azure.WindowsAzureError: Unknown error (Bad Request)
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Code>BadRequest</Code><Message>The request URI is invalid.</Message></Error>

@chenghsiang
Copy link

The code in line 91 is incorrect...
os_image_url = "http://{}.blob.core.windows/osimage/{}".format(
service_name, target_blob_name)

You need ".net" after "windows".
e.g.
os_image_url = "http://{}.blob.core.windows.net/osimage/{}".format(
service_name, target_blob_name)

@chenghsiang
Copy link

Do you have an example to pass SSH key in linux_config = LinuxConfigurationSet('hostname', 'username', 'secretA1,!', True)?
I did the following, but when I tried to ssh into the vm, I was asked for passPhrase.

In Linux machine, I did:
mkdir .ssh
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout myPrivateKey.key -out mycert.pem
openssl pkcs12 -in mycert.pem -inkey myPrivateKey.key -export -out mycert.pfx
chmod 600 myPrivateKey.key
openssl x509 -in mycert.pem -fingerprint -noout|cut -d"=" -f2|sed 's/://g'> thumbprint
ssh-keygen -f myPrivateKey.key -y >> ~/.ssh/authorized_keys

In the Python code, in addition to the code provided by ogrisel, I add the following:
thumbprint_path = '/home/test/thumbprint'
authorized_keys = '/home/test/.ssh/authorized_keys'
thumbprint=open(thumbprint_path, 'r').readline().split('\n')[0]
print thumbprint
publickey = PublicKey(thumbprint, authorized_keys)
linux_config.ssh.public_keys.public_keys.append(publickey)
print vars(publickey)
print vars(linux_config.ssh.public_keys.public_keys.list_type)

add a certificate to a cloud/hosted service (.pfx only supported)

import base64
cert_data_path = "/home/test/mycert.pfx"
with open(cert_data_path, "rb") as bfile:
cert_data = base64.b64encode(bfile.read())
cert_format = 'pfx'
cert_password = 'password'
cert_res = sms.add_service_certificate(service_name=name, data=cert_data, certificate_format=cert_format, password=cert_password)

Is there a way to get ride of the passPhrase?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment