Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add windows support to azure #349

Merged
merged 1 commit into from
Jun 30, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 54 additions & 14 deletions perfkitbenchmarker/azure/azure_virtual_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from perfkitbenchmarker import resource
from perfkitbenchmarker import virtual_machine
from perfkitbenchmarker import vm_util
from perfkitbenchmarker import windows_virtual_machine
from perfkitbenchmarker.azure import azure_disk
from perfkitbenchmarker.azure import azure_network

Expand All @@ -44,6 +45,8 @@
'14_04_1-LTS-amd64-server-20150123-en-us-30GB')
CENTOS_IMAGE = ('0b11de9248dd4d87b18621318e037d37__RightImage-'
'CentOS-7.0-x64-v14.2.1')
WINDOWS_IMAGE = ('a699494373c04fc0bc8f2bb1389d6106__Windows-Server'
'-2012-R2-201505.01-en.us-127GB.vhd')


class AzureService(resource.BaseResource):
Expand Down Expand Up @@ -108,7 +111,6 @@ def __init__(self, vm_spec):
disk_spec = disk.BaseDiskSpec(None, None, None)
self.os_disk = azure_disk.AzureDisk(disk_spec, self.name)
self.max_local_disks = 1
self.local_disk_counter = 0

@classmethod
def SetVmSpecDefaults(cls, vm_spec):
Expand All @@ -126,22 +128,26 @@ def _CreateDependencies(self):

def _DeleteDependencies(self):
"""Delete VM dependencies."""
self.os_disk.Delete()
if self.os_disk.name:
self.os_disk.Delete()
self.service.Delete()

def _Create(self):
create_cmd = [AZURE_PATH,
'vm',
'create',
'--ssh-cert=%s' % vm_util.GetCertPath(),
'--ssh=22',
'--no-ssh-password',
'--affinity-group=%s' % self.network.affinity_group.name,
'--virtual-network-name=%s' % self.network.vnet.name,
'--vm-size=%s' % self.machine_type,
self.name,
self.image,
self.user_name]
if self.password:
create_cmd.append(self.password)
else:
create_cmd.extend(['--ssh=%d' % self.ssh_port,
'--ssh-cert=%s' % vm_util.GetCertPath(),
'--no-ssh-password'])
vm_util.IssueCommand(create_cmd)

def _Delete(self):
Expand Down Expand Up @@ -187,18 +193,26 @@ def CreateScratchDisk(self, disk_spec):
Args:
disk_spec: virtual_machine.BaseDiskSpec object of the disk.
"""
if disk_spec.disk_type == disk.LOCAL:
self.local_disk_counter += disk_spec.num_striped_disks
if self.local_disk_counter > self.max_local_disks:
raise errors.Error('Not enough local disks.')

# Instantiate the disk(s) that we want to create.
disks = [azure_disk.AzureDisk(disk_spec, self.name)
for _ in range(disk_spec.num_striped_disks)]
disks = []

for _ in xrange(disk_spec.num_striped_disks):
data_disk = azure_disk.AzureDisk(disk_spec, self.name)
if disk_spec.disk_type == disk.LOCAL:
# Local disk numbers start at 1 (0 is the system disk).
data_disk.disk_number = self.local_disk_counter + 1
self.local_disk_counter += 1
if self.local_disk_counter > self.max_local_disks:
raise errors.Error('Not enough local disks.')
else:
# Remote disk numbers start at 1 + max_local disks (0 is the system disk
# and local disks occupy [1, max_local_disks]).
data_disk.disk_number = (self.remote_disk_counter +
1 + self.max_local_disks)
self.remote_disk_counter += 1
disks.append(data_disk)

self._CreateScratchDiskFromDisks(disk_spec, disks)


def GetLocalDisks(self):
"""Returns a list of local disks on the VM.
Expand All @@ -217,3 +231,29 @@ class DebianBasedAzureVirtualMachine(AzureVirtualMachine,
class RhelBasedAzureVirtualMachine(AzureVirtualMachine,
linux_virtual_machine.RhelMixin):
DEFAULT_IMAGE = CENTOS_IMAGE


class WindowsAzureVirtualMachine(AzureVirtualMachine,
windows_virtual_machine.WindowsMixin):

DEFAULT_IMAGE = WINDOWS_IMAGE

def __init__(self, vm_spec):
super(WindowsAzureVirtualMachine, self).__init__(vm_spec)
self.user_name = self.name
self.password = vm_util.GenerateRandomWindowsPassword()

def _PostCreate(self):
super(WindowsAzureVirtualMachine, self)._PostCreate()
config_dict = {'commandToExecute': windows_virtual_machine.STARTUP_SCRIPT}
config = json.dumps(config_dict)
set_extension_command = [AZURE_PATH,
'vm',
'extension',
'set',
self.name,
'CustomScriptExtension',
'Microsoft.Compute',
'1.4',
'--public-config=%s' % config]
vm_util.IssueRetryableCommand(set_extension_command)
3 changes: 2 additions & 1 deletion perfkitbenchmarker/benchmark_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@
AZURE: {
VIRTUAL_MACHINE: {
DEBIAN: azure_virtual_machine.DebianBasedAzureVirtualMachine,
RHEL: azure_virtual_machine.RhelBasedAzureVirtualMachine
RHEL: azure_virtual_machine.RhelBasedAzureVirtualMachine,
WINDOWS: azure_virtual_machine.WindowsAzureVirtualMachine
},
FIREWALL: azure_network.AzureFirewall
},
Expand Down
17 changes: 17 additions & 0 deletions perfkitbenchmarker/vm_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import random
import re
import socket
import string
import subprocess
import tempfile
import threading
Expand Down Expand Up @@ -60,6 +61,7 @@
MAX_RETRIES = -1

WINDOWS = 'nt'
PASSWORD_LENGTH = 15

flags.DEFINE_integer('default_timeout', TIMEOUT, 'The default timeout for '
'retryable commands in seconds.')
Expand Down Expand Up @@ -678,3 +680,18 @@ def _RegisterDStatCollector(sender, parsed_flags):
output_directory=output_directory)
events.before_phase.connect(collector.Start, events.RUN_PHASE, weak=False)
events.after_phase.connect(collector.Stop, events.RUN_PHASE, weak=False)


def GenerateRandomWindowsPassword(password_length=PASSWORD_LENGTH):
"""Generates a password that meets Windows complexity requirements."""
special_chars = '~!$%*_-+=\\[]:.?/'
password = [
random.choice(string.ascii_letters + string.digits + special_chars)
for _ in range(password_length - 4)]
# Ensure that the password contains at least one of each 4 required
# character types.
password.append(random.choice(string.ascii_lowercase))
password.append(random.choice(string.ascii_uppercase))
password.append(random.choice(string.digits))
password.append(random.choice(special_chars))
return ''.join(password)