Merge lp:~julian-edwards/gwacl/user-data-config into lp:gwacl

Proposed by Julian Edwards
Status: Merged
Approved by: Julian Edwards
Approved revision: 147
Merged at revision: 149
Proposed branch: lp:~julian-edwards/gwacl/user-data-config
Merge into: lp:gwacl
Diff against target: 192 lines (+37/-11)
5 files modified
example/management/run.go (+16/-5)
helpers_apiobjects_test.go (+2/-0)
management_base_test.go (+1/-1)
xmlobjects.go (+7/-1)
xmlobjects_test.go (+11/-4)
To merge this branch: bzr merge lp:~julian-edwards/gwacl/user-data-config
Reviewer Review Type Date Requested Status
Raphaël Badin (community) Approve
Review via email: mp+172260@code.launchpad.net

Commit message

Add UserData to LinuxProvisioningConfiguration.

Description of the change

This branch adds UserData to LinuxProvisioningConfiguration. The instance's /var/lib/waagent/ovf-env.xml will end up containing the LinuxProvisioningConfiguration XML exactly as passed even though the API doesn't process unused XML nodes. This will be used to drive an updated cloud-init (WIP) instead of the hacky cloud-drive VHD solution previously proposed.

I also changed the management example to pass some dummy userdata and to optionally pause after setting up the VM so users can play with it before shutting down. Additionally I gave the instance a fixed user/pass of ubuntu/Ubuntu123 since random passwords are no use to man nor beast and is certainly not a security hazard on a short-lived private instance.

Long term, I want a new command line utility to manage VMs.

To post a comment you must log in.
Revision history for this message
Raphaël Badin (rvb) wrote :

Looks good, but I've got a question (see [1]), hence "needs info".

[0]

46 + var wait string
47 + fmt.Println("Pausing so you can play with the newly-created VM")
48 + fmt.Println("To clear up, type something and press enter to continue")
49 + fmt.Scan(&wait)

That's great (I was planning to do something like that myself today :)). How about printing more details about the host to help the testing:

    request := &gwacl.GetDeploymentRequest{ServiceName: hostServiceName, DeploymentName: machineName}
    deploy, err := api.GetDeployment(request)
    fqdn, err := deploy.GetFQDN()
    fmt.Println("host:", fqdn)
    // The user name should be a variable!!!!
    fmt.Println("user:test")
    fmt.Println("password:", password)

[1]

138 + <UserData>%s</UserData>

What about escaping? Shouldn't this be base64 escaped or do you think it should be the caller's responsibility to do something like that?
My take on this is that gwacl should probably base64-encode this to avoid messing with the XML structure.

[2]

24 + location := "West US"
25 + release := "13.04"

Why this change? I don't mind the location change but precise is our target platform at the moment so I'd rather keep that as our default for experimenting.

review: Needs Information
Revision history for this message
Julian Edwards (julian-edwards) wrote :

On Monday 01 Jul 2013 06:58:25 you wrote:
> Review: Needs Information
>
> Looks good, but I've got a question (see [1]), hence "needs info".
>
> [0]
>
> 46 + var wait string
> 47 + fmt.Println("Pausing so you can play with the newly-created
VM")
> 48 + fmt.Println("To clear up, type something and press enter to
> continue") 49 + fmt.Scan(&wait)
>
> That's great (I was planning to do something like that myself today :)).
> How about printing more details about the host to help the testing:
>
> request := &gwacl.GetDeploymentRequest{ServiceName: hostServiceName,
> DeploymentName: machineName} deploy, err := api.GetDeployment(request)
> fqdn, err := deploy.GetFQDN()
> fmt.Println("host:", fqdn)
> // The user name should be a variable!!!!
> fmt.Println("user:test")
> fmt.Println("password:", password)

Yes, but I was going to leave it to another branch, it does not belong in this
one.

>
> [1]
>
> 138 + <UserData>%s</UserData>
>
> What about escaping? Shouldn't this be base64 escaped or do you think it
> should be the caller's responsibility to do something like that? My take on
> this is that gwacl should probably base64-encode this to avoid messing with
> the XML structure.

Caller's responsibility. It's stored on the VM host *as supplied*.

>
> [2]
>
> 24 + location := "West US"
> 25 + release := "13.04"
>
> Why this change? I don't mind the location change but precise is our target
> platform at the moment so I'd rather keep that as our default for
> experimenting.

I found both to be more reliable.

Revision history for this message
Raphaël Badin (rvb) wrote :

> On Monday 01 Jul 2013 06:58:25 you wrote:
> > Review: Needs Information
> >
> > Looks good, but I've got a question (see [1]), hence "needs info".
> >
> > [0]
> >
> > 46 + var wait string
> > 47 + fmt.Println("Pausing so you can play with the newly-created
> VM")
> > 48 + fmt.Println("To clear up, type something and press enter to
> > continue") 49 + fmt.Scan(&wait)
> >
> > That's great (I was planning to do something like that myself today :)).
> > How about printing more details about the host to help the testing:
> >
> > request := &gwacl.GetDeploymentRequest{ServiceName: hostServiceName,
> > DeploymentName: machineName} deploy, err := api.GetDeployment(request)
> > fqdn, err := deploy.GetFQDN()
> > fmt.Println("host:", fqdn)
> > // The user name should be a variable!!!!
> > fmt.Println("user:test")
> > fmt.Println("password:", password)
>
> Yes, but I was going to leave it to another branch, it does not belong in this
> one.

Okay.

> > [1]
> >
> > 138 + <UserData>%s</UserData>
> >
> > What about escaping? Shouldn't this be base64 escaped or do you think it
> > should be the caller's responsibility to do something like that? My take on
> > this is that gwacl should probably base64-encode this to avoid messing with
> > the XML structure.
>
> Caller's responsibility. It's stored on the VM host *as supplied*.

All right. It's probably worth a comment in the code then.

review: Approve
146. By Julian Edwards

doc comment for linux provisioning config

147. By Julian Edwards

merge trunk

Revision history for this message
Julian Edwards (julian-edwards) wrote :

Thanks mate, comment added.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'example/management/run.go'
--- example/management/run.go 2013-07-01 16:15:45 +0000
+++ example/management/run.go 2013-07-02 00:36:23 +0000
@@ -21,11 +21,13 @@
21var certFile string21var certFile string
22var subscriptionID string22var subscriptionID string
23var verbose bool23var verbose bool
24var pause bool
2425
25func getParams() error {26func getParams() error {
26 flag.StringVar(&certFile, "cert", "", "Name of your management certificate file (in PEM format).")27 flag.StringVar(&certFile, "cert", "", "Name of your management certificate file (in PEM format).")
27 flag.StringVar(&subscriptionID, "subscriptionid", "", "Your Azure subscription ID.")28 flag.StringVar(&subscriptionID, "subscriptionid", "", "Your Azure subscription ID.")
28 flag.BoolVar(&verbose, "verbose", false, "Print debugging output")29 flag.BoolVar(&verbose, "verbose", false, "Print debugging output")
30 flag.BoolVar(&pause, "pause", false, "Wait for user input after the VM is brought up (useful for further testing)")
2931
30 flag.Parse()32 flag.Parse()
3133
@@ -85,8 +87,8 @@
85}87}
8688
87func ExerciseHostedServicesAPI(api *gwacl.ManagementAPI) {89func ExerciseHostedServicesAPI(api *gwacl.ManagementAPI) {
88 location := "East US"90 location := "West US"
89 release := "12.04"91 release := "13.04"
9092
91 fmt.Printf("Getting OS Image for release '%s' and location '%s'...\n", release, location)93 fmt.Printf("Getting OS Image for release '%s' and location '%s'...\n", release, location)
92 images, err := api.ListOSImages()94 images, err := api.ListOSImages()
@@ -133,10 +135,12 @@
133135
134 fmt.Println("Adding VM deployment...")136 fmt.Println("Adding VM deployment...")
135 hostname := makeRandomIdentifier("gwaclhost", 25)137 hostname := makeRandomIdentifier("gwaclhost", 25)
136 // Azure is strict about passwords, so make it really ugly.138 // Random passwords are no use to man nor beast here if you want to
137 password := makeRandomIdentifier("Password-!£$%^&*-", 32)139 // test with your instance, so we'll use a fixed one. It's not really a
140 // security hazard in such a short-lived private instance.
141 password := "Ubuntu123"
138 vhdName := makeRandomIdentifier("gwacldisk", 16)142 vhdName := makeRandomIdentifier("gwacldisk", 16)
139 configurationSet := gwacl.NewLinuxProvisioningConfiguration(hostname, "test", password, false)143 configurationSet := gwacl.NewLinuxProvisioningConfiguration(hostname, "ubuntu", password, "TEST_USER_DATA", false)
140144
141 storageAccount := makeRandomIdentifier("gwacl", 24)145 storageAccount := makeRandomIdentifier("gwacl", 24)
142 storageLabel := makeRandomIdentifier("gwacl", 64)146 storageLabel := makeRandomIdentifier("gwacl", 64)
@@ -196,4 +200,11 @@
196 checkError(err)200 checkError(err)
197 fmt.Printf("Got %d instance(s)\n", len(instances))201 fmt.Printf("Got %d instance(s)\n", len(instances))
198 fmt.Println("Done listing VM\n")202 fmt.Println("Done listing VM\n")
203
204 if pause {
205 var wait string
206 fmt.Println("Pausing so you can play with the newly-created VM")
207 fmt.Println("To clear up, type something and press enter to continue")
208 fmt.Scan(&wait)
209 }
199}210}
200211
=== modified file 'helpers_apiobjects_test.go'
--- helpers_apiobjects_test.go 2013-06-27 11:53:50 +0000
+++ helpers_apiobjects_test.go 2013-07-02 00:36:23 +0000
@@ -46,6 +46,7 @@
46 hostname := MakeRandomString(10)46 hostname := MakeRandomString(10)
47 username := MakeRandomString(10)47 username := MakeRandomString(10)
48 password := MakeRandomString(10)48 password := MakeRandomString(10)
49 userdata := MakeRandomString(10)
49 disableSSH := MakeRandomBool()50 disableSSH := MakeRandomBool()
5051
51 return &LinuxProvisioningConfiguration{52 return &LinuxProvisioningConfiguration{
@@ -53,6 +54,7 @@
53 Hostname: hostname,54 Hostname: hostname,
54 Username: username,55 Username: username,
55 Password: password,56 Password: password,
57 UserData: userdata,
56 DisableSSHPasswordAuthentication: disableSSH}58 DisableSSHPasswordAuthentication: disableSSH}
57}59}
5860
5961
=== modified file 'management_base_test.go'
--- management_base_test.go 2013-06-27 16:35:06 +0000
+++ management_base_test.go 2013-07-02 00:36:23 +0000
@@ -495,7 +495,7 @@
495 api := makeAPI(c)495 api := makeAPI(c)
496 recordedRequests := setUpDispatcher("operationID")496 recordedRequests := setUpDispatcher("operationID")
497 serviceName := "serviceName"497 serviceName := "serviceName"
498 configurationSet := NewLinuxProvisioningConfiguration("testHostname12345", "test", "test123#@!", false)498 configurationSet := NewLinuxProvisioningConfiguration("testHostname12345", "test", "test123#@!", "user-data", false)
499 vhd := NewOSVirtualHardDisk("hostCaching", "diskLabel", "diskName", "http://mediaLink", "sourceImageName", "os")499 vhd := NewOSVirtualHardDisk("hostCaching", "diskLabel", "diskName", "http://mediaLink", "sourceImageName", "os")
500 role := NewRole("ExtraSmall", "test-role-123", []LinuxProvisioningConfiguration{*configurationSet}, []OSVirtualHardDisk{*vhd})500 role := NewRole("ExtraSmall", "test-role-123", []LinuxProvisioningConfiguration{*configurationSet}, []OSVirtualHardDisk{*vhd})
501 deployment := NewDeploymentForCreateVMDeployment("test-machine-name", "Staging", "testLabel", []Role{*role}, "testNetwork")501 deployment := NewDeploymentForCreateVMDeployment("test-machine-name", "Staging", "testLabel", []Role{*role}, "testNetwork")
502502
=== modified file 'xmlobjects.go'
--- xmlobjects.go 2013-06-28 10:21:26 +0000
+++ xmlobjects.go 2013-07-02 00:36:23 +0000
@@ -45,6 +45,7 @@
45 Hostname string `xml:"HostName"`45 Hostname string `xml:"HostName"`
46 Username string `xml:"UserName"`46 Username string `xml:"UserName"`
47 Password string `xml:"UserPassword"`47 Password string `xml:"UserPassword"`
48 UserData string `xml:"UserData"`
48 DisableSSHPasswordAuthentication bool `xml:"DisableSshPasswordAuthentication"`49 DisableSSHPasswordAuthentication bool `xml:"DisableSshPasswordAuthentication"`
49}50}
5051
@@ -52,14 +53,19 @@
52 return toxml(c)53 return toxml(c)
53}54}
5455
56// NewLinuxProvisioningConfiguration creates and returns a
57// LinuxProvisioningConfiguration which is used when deploying a Linux VM
58// instance. Note that UserData is passed to Azure *as-is* which also stores
59// it as passed, so consider base64 encoding it.
55func NewLinuxProvisioningConfiguration(60func NewLinuxProvisioningConfiguration(
56 Hostname, Username, Password string,61 Hostname, Username, Password, UserData string,
57 DisableSSHPasswordAuthentication bool) *LinuxProvisioningConfiguration {62 DisableSSHPasswordAuthentication bool) *LinuxProvisioningConfiguration {
58 return &LinuxProvisioningConfiguration{63 return &LinuxProvisioningConfiguration{
59 ConfigurationSetType: "LinuxProvisioningConfiguration",64 ConfigurationSetType: "LinuxProvisioningConfiguration",
60 Hostname: Hostname,65 Hostname: Hostname,
61 Username: Username,66 Username: Username,
62 Password: Password,67 Password: Password,
68 UserData: UserData,
63 DisableSSHPasswordAuthentication: DisableSSHPasswordAuthentication,69 DisableSSHPasswordAuthentication: DisableSSHPasswordAuthentication,
64 }70 }
65}71}
6672
=== modified file 'xmlobjects_test.go'
--- xmlobjects_test.go 2013-06-28 10:21:26 +0000
+++ xmlobjects_test.go 2013-07-02 00:36:23 +0000
@@ -31,10 +31,12 @@
31 <HostName>%s</HostName>31 <HostName>%s</HostName>
32 <UserName>%s</UserName>32 <UserName>%s</UserName>
33 <UserPassword>%s</UserPassword>33 <UserPassword>%s</UserPassword>
34 <UserData>%s</UserData>
34 <DisableSshPasswordAuthentication>%v</DisableSshPasswordAuthentication>35 <DisableSshPasswordAuthentication>%v</DisableSshPasswordAuthentication>
35 </LinuxProvisioningConfiguration>`)36 </LinuxProvisioningConfiguration>`)
36 expected := fmt.Sprintf(template, config.Hostname, config.Username,37 expected := fmt.Sprintf(template, config.Hostname, config.Username,
37 config.Password, config.DisableSSHPasswordAuthentication)38 config.Password, config.UserData,
39 config.DisableSSHPasswordAuthentication)
38 c.Check(xml, Equals, expected)40 c.Check(xml, Equals, expected)
39}41}
4042
@@ -125,6 +127,7 @@
125 <HostName>%s</HostName>127 <HostName>%s</HostName>
126 <UserName>%s</UserName>128 <UserName>%s</UserName>
127 <UserPassword>%s</UserPassword>129 <UserPassword>%s</UserPassword>
130 <UserData>%s</UserData>
128 <DisableSshPasswordAuthentication>%v</DisableSshPasswordAuthentication>131 <DisableSshPasswordAuthentication>%v</DisableSshPasswordAuthentication>
129 </ConfigurationSet>132 </ConfigurationSet>
130 </ConfigurationSets>133 </ConfigurationSets>
@@ -132,7 +135,8 @@
132 </Role>`)135 </Role>`)
133 expected := fmt.Sprintf(template, role.RoleName,136 expected := fmt.Sprintf(template, role.RoleName,
134 config.ConfigurationSetType, config.Hostname, config.Username,137 config.ConfigurationSetType, config.Hostname, config.Username,
135 config.Password, config.DisableSSHPasswordAuthentication, role.RoleSize)138 config.Password, config.UserData,
139 config.DisableSSHPasswordAuthentication, role.RoleSize)
136 c.Check(xml, Equals, expected)140 c.Check(xml, Equals, expected)
137}141}
138142
@@ -160,6 +164,7 @@
160 <HostName>%s</HostName>164 <HostName>%s</HostName>
161 <UserName>%s</UserName>165 <UserName>%s</UserName>
162 <UserPassword>%s</UserPassword>166 <UserPassword>%s</UserPassword>
167 <UserData>%s</UserData>
163 <DisableSshPasswordAuthentication>%v</DisableSshPasswordAuthentication>168 <DisableSshPasswordAuthentication>%v</DisableSshPasswordAuthentication>
164 </ConfigurationSet>169 </ConfigurationSet>
165 </ConfigurationSets>170 </ConfigurationSets>
@@ -180,7 +185,7 @@
180 expected := fmt.Sprintf(template, deployment.Name,185 expected := fmt.Sprintf(template, deployment.Name,
181 deployment.DeploymentSlot, deployment.Label,186 deployment.DeploymentSlot, deployment.Label,
182 role.RoleName, config.ConfigurationSetType, config.Hostname,187 role.RoleName, config.ConfigurationSetType, config.Hostname,
183 config.Username, config.Password,188 config.Username, config.Password, config.UserData,
184 config.DisableSSHPasswordAuthentication, role.RoleSize,189 config.DisableSSHPasswordAuthentication, role.RoleSize,
185 deployment.VirtualNetworkName, dns.Name, dns.Address)190 deployment.VirtualNetworkName, dns.Name, dns.Address)
186 c.Check(xml, Equals, expected)191 c.Check(xml, Equals, expected)
@@ -750,13 +755,15 @@
750 hostname := MakeRandomString(10)755 hostname := MakeRandomString(10)
751 username := MakeRandomString(10)756 username := MakeRandomString(10)
752 password := MakeRandomString(10)757 password := MakeRandomString(10)
758 userdata := MakeRandomString(10)
753 disablessh := MakeRandomBool()759 disablessh := MakeRandomBool()
754760
755 config := NewLinuxProvisioningConfiguration(761 config := NewLinuxProvisioningConfiguration(
756 hostname, username, password, disablessh)762 hostname, username, password, userdata, disablessh)
757 c.Check(config.Hostname, Equals, hostname)763 c.Check(config.Hostname, Equals, hostname)
758 c.Check(config.Username, Equals, username)764 c.Check(config.Username, Equals, username)
759 c.Check(config.Password, Equals, password)765 c.Check(config.Password, Equals, password)
766 c.Check(config.UserData, Equals, userdata)
760 c.Check(config.DisableSSHPasswordAuthentication, Equals, disablessh)767 c.Check(config.DisableSSHPasswordAuthentication, Equals, disablessh)
761 c.Check(config.ConfigurationSetType, Equals, "LinuxProvisioningConfiguration")768 c.Check(config.ConfigurationSetType, Equals, "LinuxProvisioningConfiguration")
762}769}

Subscribers

People subscribed via source and target branches

to all changes: