Adding support for affinity groups and virtual networking

This commit is contained in:
bwhipple 2013-07-09 10:29:14 -05:00 коммит произвёл adamedx
Родитель e4afa33ac6
Коммит 1098cffa22
15 изменённых файлов: 188 добавлений и 17 удалений

6
.gitignore поставляемый
Просмотреть файл

@ -13,3 +13,9 @@ Gemfile.lock
pkg/
tmp/
# Ignore gem files
*.gem
# Ignore IDEA project files
.idea/

Просмотреть файл

@ -133,6 +133,9 @@ class Azure
xml.DeploymentSlot 'Production'
xml.Label Base64.encode64(params['deploy_name']).strip
xml.RoleList { xml.Role('i:type'=>'PersistentVMRole') }
if params[:azure_network_name]
xml.VirtualNetworkName params[:azure_network_name]
end
}
end
builder.doc.at_css('Role') << roleXML.at_css('PersistentVMRole').children.to_s

Просмотреть файл

@ -120,7 +120,12 @@ class Azure
xml.ServiceName params[:azure_dns_name]
xml.Label Base64.encode64(params[:azure_dns_name])
xml.Description 'Explicitly created hosted service'
xml.Location params[:azure_service_location] || 'West US'
unless params[:azure_service_location].nil?
xml.Location params[:azure_service_location]
end
unless params[:azure_affinity_group].nil?
xml.AffinityGroup params[:azure_affinity_group]
end
}
end
@connection.query_azure("hostedservices", "post", builder.to_xml)

Просмотреть файл

@ -57,7 +57,7 @@ class Azure
@label = image.at_css('Label').content
@name = image.at_css('Name').content
@os = image.at_css('OS').content
@location = image.at_css('Location').content.gsub(";", ", ")
@location = image.at_css('Location').content.gsub(";", ", ") if image.at_css('Location')
@eula = image.at_css('Eula').content if image.at_css('Eula')
@description = image.at_css('Description').content if image.at_css('Description')
end

Просмотреть файл

@ -287,6 +287,11 @@ class Azure
end
end
}
if params[:azure_subnet_name]
xml.SubnetNames {
xml.SubnetName params[:azure_subnet_name]
}
end
}
}
if params[:azure_availability_set]

Просмотреть файл

@ -106,7 +106,11 @@ class Azure
xml.Label Base64.encode64(params[:azure_storage_account])
xml.Description params[:azure_storage_account_description] || 'Explicitly created storage service'
# Location defaults to 'West US'
xml.Location params[:azure_service_location] || 'West US'
if params[:azure_affinity_group]
xml.AffinityGroup params[:azure_affinity_group]
else
xml.Location params[:azure_service_location] || 'West US'
end
}
end
@connection.query_azure("storageservices", "post", builder.to_xml)

Просмотреть файл

@ -124,9 +124,14 @@ class Chef
option :azure_service_location,
:short => "-m LOCATION",
:long => "--azure-service-location LOCATION",
:description => "Required. Specifies the geographic location - the name of the data center location that is valid for your subscription.
:description => "Required if not using an Affinity Group. Specifies the geographic location - the name of the data center location that is valid for your subscription.
Eg: West US, East US, East Asia, Southeast Asia, North Europe, West Europe"
option :azure_affinity_group,
:short => "-a GROUP",
:long => "--azure-affinity-group GROUP",
:description => "Required if not using a Service Location. Specifies Affinity Group the VM should belong to."
option :azure_dns_name,
:short => "-d DNS_NAME",
:long => "--azure-dns-name DNS_NAME",
@ -174,6 +179,15 @@ class Chef
:default => false,
:description => "Set this flag to add the new VM to an existing deployment/service. Must give the name of the existing
DNS correctly in the --dns-name option"
option :azure_network_name,
:long => "--azure-network-name NETWORK_NAME",
:description => "Optional. Specifies the network of virtual machine"
option :azure_subnet_name,
:long => "--azure-subnet-name SUBNET_NAME",
:description => "Optional. Specifies the subnet of virtual machine"
option :identity_file,
:long => "--identity-file FILENAME",
:description => "SSH identity file for authentication, optional. It is the RSA private key path. Specify either ssh-password or identity-file"
@ -426,7 +440,6 @@ class Chef
:azure_mgmt_cert,
:azure_api_host_name,
:azure_dns_name,
:azure_service_location,
:azure_source_image,
:azure_vm_size,
])
@ -434,6 +447,13 @@ class Chef
ui.error("Specify the VM name using --azure-vm-name option, since you are connecting to existing dns")
exit 1
end
if locate_config_value(:azure_service_location) && locate_config_value(:azure_affinity_group)
ui.error("Cannot specify both --azure_service_location and --azure_affinity_group, use one or the other.")
exit 1
elsif locate_config_value(:azure_service_location).nil? && locate_config_value(:azure_affinity_group).nil?
ui.error("Must specify either --azure_service_location or --azure_affinity_group.")
exit 1
end
end
def create_server_def
@ -450,7 +470,10 @@ class Chef
:bootstrap_proto => locate_config_value(:bootstrap_protocol),
:azure_connect_to_existing_dns => locate_config_value(:azure_connect_to_existing_dns),
:winrm_user => locate_config_value(:winrm_user),
:azure_availability_set => locate_config_value(:azure_availability_set)
:azure_availability_set => locate_config_value(:azure_availability_set),
:azure_affinity_group => locate_config_value(:azure_affinity_group),
:azure_network_name => locate_config_value(:azure_network_name),
:azure_subnet_name => locate_config_value(:azure_subnet_name)
}
# If user is connecting a new VM to an existing dns, then
# the VM needs to have a unique public port. Logic below takes care of this.

Просмотреть файл

@ -0,0 +1,44 @@
<?xml version="1.0"?>
<Deployment xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Name>unknown_yet</Name>
<DeploymentSlot>Production</DeploymentSlot>
<Label>dW5rbm93bl95ZXQ=</Label>
<RoleList>
<Role i:type="PersistentVMRole">
<RoleName>vm01</RoleName>
<OsVersion i:nil="true"/>
<RoleType>PersistentVMRole</RoleType>
<ConfigurationSets>
<ConfigurationSet i:type="LinuxProvisioningConfigurationSet">
<ConfigurationSetType>LinuxProvisioningConfiguration</ConfigurationSetType>
<HostName>vm01</HostName>
<UserName>jetstream</UserName>
<UserPassword>jetstream1!</UserPassword>
<DisableSshPasswordAuthentication>false</DisableSshPasswordAuthentication>
</ConfigurationSet>
<ConfigurationSet i:type="NetworkConfigurationSet">
<ConfigurationSetType>NetworkConfiguration</ConfigurationSetType>
<InputEndpoints>
<InputEndpoint>
<LocalPort>22</LocalPort>
<Name>SSH</Name>
<Port>22</Port>
<Protocol>TCP</Protocol>
</InputEndpoint>
</InputEndpoints>
<SubnetNames>
<SubnetName>test-subnet</SubnetName>
</SubnetNames>
</ConfigurationSet>
</ConfigurationSets>
<Label>dm0wMQ==</Label>
<OSVirtualHardDisk>
<DiskName>disk004Test</DiskName>
<MediaLink>http://storageaccount001.blob.core.windows.net/vhds/disk004Test.vhd</MediaLink>
<SourceImageName>SUSE__OpenSUSE64121-03192012-en-us-15GB</SourceImageName>
</OSVirtualHardDisk>
<RoleSize>ExtraSmall</RoleSize>
</Role>
</RoleList>
<VirtualNetworkName>test-network</VirtualNetworkName>
</Deployment>

Просмотреть файл

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<CreateHostedService xmlns="http://schemas.microsoft.com/windowsazure">
<ServiceName>service003</ServiceName>
<Label>c2VydmljZTAwMw==</Label>
<Description>Explicitly created hosted service</Description>
<AffinityGroup>test-affinity</AffinityGroup>
</CreateHostedService>

Просмотреть файл

Просмотреть файл

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<CreateStorageServiceInput xmlns="http://schemas.microsoft.com/windowsazure">
<ServiceName>ka001testeurope</ServiceName>
<Label>a2EwMDF0ZXN0ZXVyb3Bl</Label>
<Description>Explicitly created storage service</Description>
<AffinityGroup>test-affinity-group</AffinityGroup>
</CreateStorageServiceInput>

Просмотреть файл

@ -26,7 +26,8 @@ before do
:azure_dns_name => 'service001',
:azure_vm_name => 'vm002',
:azure_storage_account => 'ka001testeurope',
:azure_vm_size => 'Small'
:azure_vm_size => 'Small',
:ssh_user => 'test-user'
}.each do |key, value|
Chef::Config[:knife][key] = value
end
@ -69,11 +70,6 @@ describe "parameter test:" do
@server_instance.ui.should_receive(:error)
expect {@server_instance.run}.to raise_error
end
it "azure_service_location" do
Chef::Config[:knife].delete(:azure_service_location)
@server_instance.ui.should_receive(:error)
expect {@server_instance.run}.to raise_error
end
it "azure_source_image" do
Chef::Config[:knife].delete(:azure_source_image)
@server_instance.ui.should_receive(:error)
@ -89,6 +85,16 @@ describe "parameter test:" do
@server_instance.ui.should_receive(:error)
expect {@server_instance.run}.to raise_error
end
it "azure_service_location and azure_affinity_group not allowed" do
Chef::Config[:knife][:azure_affinity_group] = 'test-affinity'
@server_instance.ui.should_receive(:error)
expect {@server_instance.run}.to raise_error
end
it "azure_service_location or azure_affinity_group must be provided" do
Chef::Config[:knife].delete(:azure_service_location)
@server_instance.ui.should_receive(:error)
expect {@server_instance.run}.to raise_error
end
end
context "server create options" do
@ -168,6 +174,15 @@ describe "parameter test:" do
testxml = Nokogiri::XML(@receivedXML)
xml_content(testxml, 'AvailabilitySetName').should == 'test-availability-set'
end
it "server create with virtual network and subnet" do
Chef::Config[:knife][:azure_dns_name] = 'vmname'
Chef::Config[:knife][:azure_network_name] = 'test-network'
Chef::Config[:knife][:azure_subnet_name] = 'test-subnet'
@server_instance.run
testxml = Nokogiri::XML(@receivedXML)
xml_content(testxml, 'SubnetName').should == 'test-subnet'
end
end
context "#cleanup_and_exit" do

Просмотреть файл

@ -27,20 +27,29 @@ describe "hosts" do
specify {@connection.hosts.exists?("service001").should == true}
end
context 'create a new host' do
context 'create a new host with service location' do
it 'using explicit parameters it should pass in expected body' do
params = {:azure_dns_name=>'service003', 'hosted_azure_service_location'=>'Windows Azure Preview'}
params = {:azure_dns_name=>'service003', :azure_service_location=>'West US', 'hosted_azure_service_location'=>'Windows Azure Preview'}
host = @connection.hosts.create(params)
@postname.should == 'hostedservices'
@postverb.should == 'post'
Nokogiri::XML(@postbody).should be_equivalent_to(Nokogiri::XML readFile('create_host.xml'))
Nokogiri::XML(@postbody).should be_equivalent_to(Nokogiri::XML readFile('create_host_location.xml'))
end
it 'using default parameters it should pass in expected body' do
params = {:azure_dns_name=>'service003'}
params = {:azure_dns_name=>'service003', :azure_service_location=>'West US'}
host = @connection.hosts.create(params)
@postname.should == 'hostedservices'
@postverb.should == 'post'
Nokogiri::XML(@postbody).should be_equivalent_to(Nokogiri::XML readFile('create_host.xml'))
Nokogiri::XML(@postbody).should be_equivalent_to(Nokogiri::XML readFile('create_host_location.xml'))
end
end
context 'create a new host with affinity group' do
it 'using explicit parameters it should pass in expected body' do
params = {:azure_dns_name=>'service003', :azure_affinity_group=>'test-affinity' }
host = @connection.hosts.create(params)
@postname.should == 'hostedservices'
@postverb.should == 'post'
Nokogiri::XML(@postbody).should be_equivalent_to(Nokogiri::XML readFile('create_host_affinity.xml'))
end
end
context 'delete a host' do

Просмотреть файл

@ -83,5 +83,32 @@ describe "roles" do
sbmt = Nokogiri::XML File.open(tmpFile('newDeploySbmt.xml'))
rcvd.should be_equivalent_to(sbmt).respecting_element_order
end
it 'create request with virtual network' do
submittedXML=Nokogiri::XML readFile('create_deployment_virtual_network.xml')
params = {
:azure_dns_name=>'unknown_yet',
:azure_vm_name=>'vm01',
:ssh_user=>'jetstream',
:ssh_password=>'jetstream1!',
:media_location_prefix=>'auxpreview104',
:azure_os_disk_name=>'disk004Test',
:azure_source_image=>'SUSE__OpenSUSE64121-03192012-en-us-15GB',
:azure_vm_size=>'ExtraSmall',
:azure_storage_account=>'storageaccount001',
:bootstrap_proto=>'ssh',
:os_type=>'Linux',
:port=>'22',
:azure_network_name=>'test-network',
:azure_subnet_name=>'test-subnet'
}
deploy = @connection.deploys.create(params)
#this is a cheesy workaround to make equivalent-xml happy
# write and then re-read the xml
File.open(tmpFile('newDeployRcvd.xml'), 'w') {|f| f.write(@receivedXML) }
File.open(tmpFile('newDeploySbmt.xml'), 'w') {|f| f.write(submittedXML.to_xml) }
rcvd = Nokogiri::XML File.open(tmpFile('newDeployRcvd.xml'))
sbmt = Nokogiri::XML File.open(tmpFile('newDeploySbmt.xml'))
rcvd.should be_equivalent_to(sbmt).respecting_element_order
end
end
end

Просмотреть файл

@ -41,4 +41,19 @@ describe "storageaccounts" do
Nokogiri::XML(@postbody).should be_equivalent_to(Nokogiri::XML readFile('create_storageservice_for_service003.xml'))
end
end
context 'create a new storage account with affinity group' do
it 'using explicity parameters it should pass in expected body' do
params = {
:azure_dns_name => 'service004',
:azure_storage_account => 'ka001testeurope',
:azure_affinity_group => 'test-affinity-group'
}
storageaccount = @connection.storageaccounts.create(params)
@postname.should == 'storageservices'
@postverb.should == 'post'
Nokogiri::XML(@postbody).should be_equivalent_to(Nokogiri::XML readFile('create_storageservice_for_service004.xml'))
end
end
end