~billy-olsen/+junk/virt-maas-deploy

« back to all changes in this revision

Viewing changes to vmaas.py

  • Committer: billy.olsen at canonical
  • Date: 2015-05-10 06:30:04 UTC
  • Revision ID: billy.olsen@canonical.com-20150510063004-62ylzhnpf7x1ee0o
Configure networks, boot juju machine after MAAS starts up.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
 
7
7
import argparse
8
8
import libvirt
 
9
import os
9
10
import subprocess
10
 
import os
 
11
import sys
11
12
 
12
13
 
13
14
def sudo(*args):
29
30
    
30
31
    def __init__(self, network, user='dtadmin', password='ubuntu',
31
32
                 release='trusty', arch='amd64', disk_size='60G', vcpus=2,
32
 
                 memory=4096, guest='maas'):
 
33
                 memory=4096, guest='maas', **kwargs):
33
34
        self.user = user
34
35
        self.password = password
35
36
        self.release = release
87
88
        virsh('vol-resize', '--pool', self.pool.name(), self.image_name,
88
89
              self.disk_size)
89
90
 
90
 
    def add_img_to_pool(self, img):
 
91
    def add_img_to_pool(self, img, move=False):
91
92
        """
92
93
        Imports an image into the libvirt storage pool.
93
94
        """
95
96
        if img in self.pool.listVolumes():
96
97
            return
97
98
 
98
 
        sudo('cp', img, '/var/lib/libvirt/images')
 
99
        cmd = 'cp'
 
100
        if move:
 
101
            cmd = 'mv'
 
102
 
 
103
        sudo(cmd, img, '/var/lib/libvirt/images')
99
104
        self.pool.refresh()
100
105
 
101
106
    def create_seed_image(self):
106
111
        run('write-mime-multipart', '--output=cloud-init.txt',
107
112
            'config/cloud-init.cfg',
108
113
            'config/cloud-init-config-maas.txt:text/x-shellscript',
 
114
            'config/cloud-init-ubuntu-curtin.cfg',
109
115
            'config/cloud-init-final-msg.cfg')
110
116
 
111
117
        run('cloud-localds', self.seed_name, 'cloud-init.txt',
112
118
            'config/meta-data')
113
119
 
114
 
        self.add_img_to_pool(self.seed_name)
 
120
        self.add_img_to_pool(self.seed_name, move=True)
115
121
 
116
122
    def create_maas_guest(self):
117
123
        """
142
148
        print("Creating guest {}".format(self.guest))
143
149
        run(*cmd)
144
150
 
 
151
    def wait_for_maas_completion(self):
 
152
        """
 
153
        Polls the virsh console to wait for the MAAS installation to
 
154
        complete. Note: an alternative implementation could be to open a
 
155
        small webserver/socket and let the MAAS cloud-init scripts do a
 
156
        get/put request on this URI to indicate it is done. For now we'll
 
157
        just 'keep it simple' and poll the output of the console.
 
158
        """
 
159
        finished = False
 
160
        
 
161
        print("""
 
162
              Waiting for MAAS installation to complete.
 
163
              This may take a few minutes, current cloud-init progress
 
164
              is being saved in the maas-install.log file.
 
165
              """)
 
166
        stty_settings = None
 
167
        try:
 
168
            # Note: the virsh console screws with the current tty settings, so
 
169
            # save those off in order to restore this.
 
170
            stty_settings = subprocess.check_output(['stty', '-g']).strip()
 
171
            count = 0
 
172
            printed = 0
 
173
            with open('maas-install.log', 'w') as f:
 
174
                cmd = ['virsh', 'console', self.guest]
 
175
                process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
 
176
                for c in iter(lambda: process.stdout.readline(), ''):
 
177
                    count = count + 1
 
178
                    f.write(c)
 
179
                        
 
180
                    if c.find('MAAS controller is now configured') >= 0:
 
181
                        print("MAAS setup complete, terminating virsh console")
 
182
                        finished = True
 
183
                        process.terminate()
 
184
                        break
 
185
 
 
186
                    # Give some progress with some dots across the screen for
 
187
                    # every 20 lines of output, that way there's some visual
 
188
                    # indicator things are still working.
 
189
                    if (count % 20) == 0:
 
190
                        sys.stdout.write('.')
 
191
                        printed = printed + 1
 
192
 
 
193
                        if (printed % 80) == 0:
 
194
                            sys.stdout.write('\n')
 
195
        except subprocess.CalledProcessError as e:
 
196
            # An exception when process.terminate() is invoked because
 
197
            # virsh console will return -1. A pty is required to
 
198
            # gracefully exit, so we work around it
 
199
            if not finished:
 
200
                raise e
 
201
        finally:
 
202
            if stty_settings is not None:
 
203
                try:
 
204
                    subprocess.call(['stty', stty_settings])
 
205
                except:
 
206
                    pass
 
207
                
 
208
 
 
209
    def create_juju_guest(self):
 
210
        """
 
211
        Creates the Juju guest within Libvirt.
 
212
        """
 
213
        print("Creating the Juju Bootstrap virtual node...")
 
214
        fname = 'juju-root.img'
 
215
        virsh('vol-create-as', self.pool.name(), fname, '20G',
 
216
              '--format', 'qcow2')
 
217
        
 
218
        disk_tmpl = 'vol={pool}/{image},format={format},bus=virtio,io=native'
 
219
        cmd = [
 
220
            'sudo',
 
221
            'virt-install',
 
222
            '--name', 'juju',
 
223
            '--ram', str(self.memory),
 
224
            '--vcpus', str(self.vcpus),
 
225
            '--network', self.networks[0],
 
226
            '--disk', disk_tmpl.format(pool=self.pool.name(), image=fname,
 
227
                                       format='qcow2'),
 
228
            '--boot', 'network,hd,menu=off',
 
229
            '--noautoconsole',
 
230
            '--vnc'
 
231
        ]
 
232
        print("Creating juju guest")
 
233
        run(*cmd)
 
234
 
145
235
    def __call__(self):
146
236
        self.create_cloud_image()
147
237
        self.create_seed_image()
148
238
        self.create_maas_guest()
149
239
 
 
240
        # Wait for the cloud-init MAAS scripts to finish
 
241
        self.wait_for_maas_completion()
 
242
 
 
243
        # Create the juju guest
 
244
        self.create_juju_guest()
 
245
 
150
246
 
151
247
if __name__ == '__main__':
152
248
    parser = argparse.ArgumentParser(description="Creates a virtual MAAS deployment")
153
249
    
154
 
    parser.add_argument('-n', '--network', type=str, action='append')
 
250
    parser.add_argument('-n', '--network', type=str, action='append', required=True)
155
251
    parser.add_argument('--disk-size', type=str, default='60G')
156
252
    parser.add_argument('--vcpus', type=int, default=2)
157
253
    parser.add_argument('--memory', type=str, default='2048')
 
254
    parser.add_argument('--noprompt', type=bool, default=False)
158
255
    args = parser.parse_args()
159
256
    
160
 
    run('editor', 'config/meta-data')
 
257
    if not args.noprompt:
 
258
        run('editor', 'config/meta-data')
161
259
    
162
260
    install = Installer(**args.__dict__)
163
 
    install()
 
 
b'\\ No newline at end of file'
 
261
    install()