@@ -18,23 +18,27 @@ import (
1818
1919var metaDataFmt = `
2020instance-id: iid-%s;
21- #hostname: %s
22- #local-hostname: %s`
21+ `
2322
24- var userDataFmt = `#cloud-config
23+ var userDataTmpl = `#cloud-config
2524users:
26- - name: %s
25+ - name: {{.User}}
2726 lock_passwd: false
2827 sudo: ALL=(ALL) NOPASSWD:ALL
2928 shell: /bin/bash
3029 # this is the outcome of the command openssl passwd -1 -salt SaltSalt $PASSWORD
31- passwd: %s
30+ passwd: {{.PasswdHash}}
3231
3332write_files:
3433- path: /provision.sh
3534 content: |
36- %s
35+ {{.Provision | indentByFour }}
3736
37+ {{- if ne .Initd "" }}
38+ - path: /etc/init.d/{{.Name}}
39+ content: |
40+ {{.Initd | indentByFour }}
41+ {{- end}}
3842
3943- path: /remove_cloud_init.sh
4044 content: |
@@ -44,7 +48,7 @@ write_files:
4448 sudo rm -rf /etc/cloud/; sudo rm -rf /var/lib/cloud/
4549
4650
47- password: %s
51+ # password: {{.Passwd}}
4852chpasswd: { expire: False }
4953ssh_pwauth: True
5054
@@ -56,6 +60,10 @@ apt_upgrade: true
5660
5761runcmd:
5862 - bash /provision.sh
63+ {{- if ne .Initd "" }}
64+ - chmod +x /etc/init.d/{{.Name}}
65+ - update-rc.d {{.Name}} defaults
66+ {{- end}}
5967 - bash /remove_cloud_init.sh
6068 - shutdown
6169
@@ -64,12 +72,15 @@ power_state:
6472`
6573
6674type ProvisionConf struct {
75+ Name string `json:"name"`
6776 CloudImgURL string `json:"cloud_img_url"`
6877 CloudImgName string `json:"cloud_img_name"`
6978 User string `json:"user"`
7079 Passwd string `json:"passwd"`
7180 RootImgGB int `json:"root_img_gb"`
7281 Provision string
82+ Initd string
83+ PasswdHash string
7384}
7485
7586type NetIf struct {
@@ -94,40 +105,62 @@ type GuestConf struct {
94105}
95106
96107func createMetaDataFile (path , guest string ) error {
97- s := fmt .Sprintf (metaDataFmt , guest , guest , guest )
108+ s := fmt .Sprintf (metaDataFmt , guest )
98109 if err := ioutil .WriteFile (path , []byte (s ), 0644 ); err != nil {
99110 return err
100111 }
101112 return nil
102113}
103114
104- func createUserDataFile (path , user , passwd , script string ) error {
105- cmd := exec .Command ("openssl" , "passwd" , "-1" , "-salt" , "SaltSalt" , passwd )
106- hash , err := cmd .CombinedOutput ()
115+ func indentByFour (s string ) string {
116+ return regexp .MustCompile ("\n " ).ReplaceAllString (s , "\n " )
117+ }
118+
119+ func userData (p * ProvisionConf ) (string , error ) {
120+ t , err := template .New ("udtmpl" ).
121+ Funcs (template.FuncMap {"indentByFour" : indentByFour }).
122+ Parse (userDataTmpl )
123+ if err != nil {
124+ return "" , fmt .Errorf ("failed to parse template: %v" , err )
125+ }
126+
127+ var xml bytes.Buffer
128+ if err := t .Execute (& xml , p ); err != nil {
129+ return "" , fmt .Errorf ("failed to execute template: %v" , err )
130+ }
131+
132+ return xml .String (), nil
133+ }
134+
135+ func createUserDataFile (path string , p * ProvisionConf ) error {
136+ cmd := exec .Command ("openssl" , "passwd" , "-1" , "-salt" , "SaltSalt" , p .Passwd )
137+ out , err := cmd .CombinedOutput ()
107138 if err != nil {
108139 return fmt .Errorf ("failed to executed %v: %v" , cmd .Args , err )
109140 }
110141
111- re := regexp .MustCompile ("\n " )
112- indentedScript := re .ReplaceAllString (script , "\n " )
113- s := fmt .Sprintf (userDataFmt , user , hash , indentedScript , passwd )
142+ p .PasswdHash = string (out )
143+
144+ s , err := userData (p )
145+ if err != nil {
146+ return fmt .Errorf ("failed to create user-data string from config %+v: %v" , p , err )
147+ }
114148
115149 if err := ioutil .WriteFile (path , []byte (s ), 0644 ); err != nil {
116150 return err
117151 }
118152 return nil
119153}
120154
121- func createConfigIsoImage (path , guest , user , passwd , prov string ) error {
122- var metaDataPath = "meta-data"
123- var userDataPath = "user-data"
124-
125- if err := createMetaDataFile (metaDataPath , guest ); err != nil {
155+ func createConfigIsoImage (path string , p * ProvisionConf ) error {
156+ userDataPath := "user-data"
157+ metaDataPath := "meta-data"
158+ if err := createMetaDataFile (metaDataPath , p .Name ); err != nil {
126159 return fmt .Errorf ("failed to create meta-data file for cloud-init: %v" , err )
127160 }
128161 //defer os.Remove(metaDataPath)
129162
130- if err := createUserDataFile (userDataPath , user , passwd , prov ); err != nil {
163+ if err := createUserDataFile (userDataPath , p ); err != nil {
131164 return fmt .Errorf ("failed to create user-data file for cloud-init: %v" , err )
132165 }
133166 //defer os.Remove(userDataPath)
@@ -168,13 +201,13 @@ var domTmpl = `
168201 <currentMemory unit='MiB'>{{.MemoryMB}}</currentMemory>
169202
170203 <!-- hugepages -->
171- {{if .HugepageSupport}}
204+ {{- if .HugepageSupport}}
172205 <memoryBacking>
173206 <hugepages>
174207 <page size='{{.HugepageSize}}' unit='{{.HugepageSizeUnit}}' nodeset='{{.HugepageNodeSet}}'/>
175208 </hugepages>
176209 </memoryBacking>
177- {{end}}
210+ {{- end}}
178211
179212 <vcpu placement='static'>{{.NumVcpus}}</vcpu>
180213 <!-- cputune><shares>4096</shares>
@@ -322,7 +355,7 @@ func GuestImagePaths(l *libvirt.Libvirt, poolName, guest string) (rootImgPath, c
322355 return
323356}
324357
325- func createVolumes (l * libvirt.Libvirt , guest string , c * ProvisionConf ) (rootImgPath , configIsoPath string , e error ) {
358+ func createVolumes (l * libvirt.Libvirt , c * ProvisionConf ) (rootImgPath , configIsoPath string , e error ) {
326359 baseu , err := url .Parse (c .CloudImgURL )
327360 if err != nil {
328361 e = err
@@ -341,18 +374,18 @@ func createVolumes(l *libvirt.Libvirt, guest string, c *ProvisionConf) (rootImgP
341374 return
342375 }
343376
344- rootImgPath , configIsoPath , err = GuestImagePaths (l , DefaultPool (), guest )
377+ rootImgPath , configIsoPath , err = GuestImagePaths (l , DefaultPool (), c . Name )
345378 if err != nil {
346379 e = fmt .Errorf ("failed to compute guest image paths: %v" , err )
347380 return
348381 }
349382
350- if err := createConfigIsoImage (ConfigIsoName (guest ), guest , c . User , c . Passwd , c . Provision ); err != nil {
351- e = fmt .Errorf ("failed to create configuration iso image %s: %v" , ConfigIsoName , err )
383+ if err := createConfigIsoImage (ConfigIsoName (c . Name ) , c ); err != nil {
384+ e = fmt .Errorf ("failed to create configuration iso image %s: %v" , ConfigIsoName ( c . Name ) , err )
352385 return
353386 }
354387
355- if err := copyFile (ConfigIsoName (guest ), configIsoPath ); err != nil {
388+ if err := copyFile (ConfigIsoName (c . Name ), configIsoPath ); err != nil {
356389 e = fmt .Errorf ("failed to copy configuration iso under storage pool's directory: %v" , err )
357390 return
358391 }
@@ -373,9 +406,9 @@ func createVolumes(l *libvirt.Libvirt, guest string, c *ProvisionConf) (rootImgP
373406 return
374407 }
375408
376- vol , err := l .StorageVolLookupByName (pool , RootImgName (guest ))
409+ vol , err := l .StorageVolLookupByName (pool , RootImgName (c . Name ))
377410 if err != nil {
378- e = fmt .Errorf ("failed to lookup storage volume %s under pool %s: %v" , RootImgName , pool .Name , err )
411+ e = fmt .Errorf ("failed to lookup storage volume %s under pool %s: %v" , RootImgName ( c . Name ) , pool .Name , err )
379412 return
380413 }
381414
@@ -422,7 +455,7 @@ func ConfigIsoName(guest string) string {
422455
423456func Provision (l * libvirt.Libvirt , p * ProvisionConf , g * GuestConf ) error {
424457 var err error
425- g .RootImgPath , g .ConfigIsoPath , err = createVolumes (l , g . Name , p )
458+ g .RootImgPath , g .ConfigIsoPath , err = createVolumes (l , p )
426459 if err != nil {
427460 return fmt .Errorf ("failed to create volumes: %v" , err )
428461 }
0 commit comments