Merge lp:~nuclearbob/utah/cobbler-desktop into lp:utah

Proposed by Max Brustkern
Status: Merged
Merged at revision: 693
Proposed branch: lp:~nuclearbob/utah/cobbler-desktop
Merge into: lp:utah
Diff against target: 245 lines (+103/-32)
2 files modified
utah/config.py (+6/-2)
utah/provisioning/baremetal/cobbler.py (+97/-30)
To merge this branch: bzr merge lp:~nuclearbob/utah/cobbler-desktop
Reviewer Review Type Date Requested Status
Joe Talbott (community) Approve
Review via email: mp+123281@code.launchpad.net

Description of the change

This branch adds support for mini and desktop images to the CobblerMachine class. Desktop images currently require nfs, and are configured via the nfs options in the updated config.py. I haven't yet incorporated a dependency or check for nfs, so feedback on the ideal way to do that would be welcome. I've tested both types in magners-orchestra. Currently, the desktop install requires this latecommand:
chroot /target apt-get update
To get python-jsonschema from the PPA correctly in magners-orchestra, but once we have a different fix in place for that, we won't need that in the preseed anymore.

To post a comment you must log in.
Revision history for this message
Joe Talbott (joetalbott) wrote :

Looks good to me.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'utah/config.py'
2--- utah/config.py 2012-08-22 15:20:25 +0000
3+++ utah/config.py 2012-09-07 14:03:40 +0000
4@@ -42,6 +42,9 @@
5 machineid=None,
6 name=None,
7 new=False,
8+ nfscommand=['sudo', os.path.join('/', 'etc', 'init.d', 'nfs-kernel-server'), 'reload'],
9+ nfsconfigfile=os.path.join('/', 'etc', 'exports'),
10+ nfsoptions='*(ro,async,no_root_squash,no_subtree_check)',
11 powertimeout=5,
12 preseed=None,
13 qemupath='qemu:///system',
14@@ -55,6 +58,7 @@
15 """
16 LOCALDEFAULTS = dict(
17 bridge=getbridge(),
18+ hostname=socket.gethostname(),
19 sshprivatekey=os.path.join(os.path.expanduser('~'), '.ssh', 'utah'),
20 sshpublickey=os.path.join(os.path.expanduser('~'), '.ssh', 'utah.pub'),
21 sshknownhosts=os.path.join(os.path.expanduser('~'), '.ssh', 'known_hosts'),
22@@ -66,9 +70,9 @@
23 These depend on other config options, so they're added last.
24 """
25 LOCALDEFAULTS['logfile'] = os.path.join(DEFAULTS['logpath'],
26- socket.gethostname() + '.log')
27+ LOCALDEFAULTS['hostname'] + '.log')
28 LOCALDEFAULTS['debuglog'] = os.path.join(DEFAULTS['logpath'],
29- socket.gethostname() + '-debug.log')
30+ LOCALDEFAULTS['hostname'] + '-debug.log')
31
32 DEFAULTS.update(LOCALDEFAULTS)
33
34
35=== modified file 'utah/provisioning/baremetal/cobbler.py'
36--- utah/provisioning/baremetal/cobbler.py 2012-08-30 08:34:34 +0000
37+++ utah/provisioning/baremetal/cobbler.py 2012-09-07 14:03:40 +0000
38@@ -2,7 +2,9 @@
39 Support bare metal provisioning through cobbler.
40 """
41
42+import netifaces
43 import os
44+import pipes
45 import shutil
46 import tempfile
47 import time
48@@ -42,17 +44,14 @@
49 'Image file required for cobbler installation')
50 self._custominit(arch=self.arch, boot=boot,
51 installtype=self.installtype, series=self.series)
52- # TODO: support mini,
53- # then desktop once we can figure out how
54+ # TODO: verify we have nfs support for desktop image
55+
56+ # TODO: Rework cinitrd to be less of a confusing collection of kludges
57 self.cinitrd = None
58 if self.installtype in ['alternate', 'server']:
59 self.cinitrd = os.path.join('install', 'netboot',
60 'ubuntu-installer', self.arch,
61 'initrd.gz')
62- else:
63- raise UTAHBMProvisioningException(
64- 'Only alternate and server images currently supported '
65- 'for cobbler provisioning')
66 if self.arch == 'amd64':
67 self.carch = 'x86_64'
68 else:
69@@ -72,19 +71,34 @@
70
71 # TODO: try to remove this step, mount the iso and import that
72 # with a specified kernel/preseed/initrd from the tmpdir
73- self.logger.info('Extracting image to ' + self.tmpdir)
74- self.image.extractall()
75+ if self.installtype in ['alternate', 'desktop', 'server']:
76+ self.logger.info('Extracting image to ' + self.tmpdir)
77+ self.image.extractall()
78
79- self._preparekernel()
80- cinitrd = os.path.join(self.tmpdir, self.cinitrd)
81+ kernel = self._preparekernel()
82+ if self.cinitrd is None:
83+ cinitrd = None
84+ else:
85+ cinitrd = os.path.join(self.tmpdir, self.cinitrd)
86 initrd = self._prepareinitrd(initrd=cinitrd)
87 self._unpackinitrd(initrd=initrd)
88 self._setuplatecommand()
89+ if self.installtype == 'desktop':
90+ self.logger.info('Configuring latecommand for desktop')
91+ myfile = open(os.path.join(self.tmpdir, 'initrd.d',
92+ 'utah-latecommand'), 'a')
93+ myfile.write(
94+"""
95+chroot /target sh -c 'sed "/eth[0-9]/d" -i /etc/network/interfaces'
96+cp /etc/resolv.conf /target/etc/resolv.conf
97+""")
98+ myfile.close()
99 self._setuppreseed()
100 initrd = self._repackinitrd()
101
102- os.chmod(cinitrd, 0755)
103- shutil.copyfile(initrd, cinitrd)
104+ if cinitrd is not None and initrd != cinitrd:
105+ os.chmod(cinitrd, 0755)
106+ shutil.copyfile(initrd, cinitrd)
107
108 self.logger.info('Setting up system with cobbler')
109 self.logger.debug('Removing old system')
110@@ -93,28 +107,67 @@
111 self._cobble(['profile', 'remove', '--name=' + self.cname])
112 self.logger.info('Removing old distro')
113 self._cobble(['distro', 'remove', '--name=' + self.cname])
114- # TODO: support more image types, maybe do this without unpacking ISO
115- self.logger.info('Importing image')
116- self._cobble(['import', '--name=' + self.cname,
117- '--path=' + self.tmpdir, '--arch=' + self.carch])
118- # TODO: figure out if I need kopts in both places
119+
120+ preseed = os.path.join(self.tmpdir, 'initrd.d', 'preseed.cfg')
121+
122+ if self.installtype in ['alternate', 'server']:
123+ # TODO: support more image types,
124+ # maybe do this without unpacking ISO
125+ self.logger.info('Importing image')
126+ self._cobble(['import', '--name=' + self.cname,
127+ '--path=' + self.tmpdir, '--arch=' + self.carch])
128+ elif self.installtype in ['mini', 'desktop']:
129+ self.logger.info('Creating distro')
130+ self._cobble(['distro', 'add', '--name=' + self.cname,
131+ '--kernel=' + kernel, '--initrd=' + initrd])
132+ self.logger.info('Creating profile')
133+ self._cobble(['profile', 'add', '--name=' + self.cname,
134+ '--distro=' + self.cname])
135+
136+ if self.installtype == 'desktop':
137+ self.logger.info('Setting up NFS for desktop install')
138+ self.logger.debug('Adding export to NFS config file')
139+# nfsfile = open(config.nfsconfigfile, 'a')
140+# nfsfile.write("\n" + self.tmpdir + ' ' + config.nfsoptions + "\n")
141+# nfsfile.close()
142+ pipe = pipes.Template()
143+ pipe.append('sudo tee -a ' + config.nfsconfigfile + ' >/dev/null',
144+ '-.')
145+ pipe.open('/dev/null', 'w').write(self.tmpdir + ' ' +
146+ config.nfsoptions + "\n")
147+ self.logger.debug('Reloading NFS config')
148+ self._runargs(config.nfscommand)
149+ self.logger.debug('Adding NFS boot options')
150+ try:
151+ iface = config.nfsiface
152+ except AttributeError:
153+ iface = config.bridge
154+ ip = netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr']
155+ self.cmdline += (' root=/dev/nfs netboot=nfs nfsroot=' +
156+ ip + ':' + self.tmpdir)
157+ self.cmdline = self.cmdline.strip()
158+
159 self.logger.info('Adding kernel boot options to distro')
160 self._cobble(['distro', 'edit', '--name=' + self.cname,
161 '--kopts=' + self.cmdline])
162- self.logger.info('Adding kernel boot options '
163- 'and kickstart to profile')
164- preseed = os.path.join(self.tmpdir, 'initrd.d', 'preseed.cfg')
165+
166+ self.logger.info('Adding kickstart to profile')
167 self._cobble(['profile', 'edit', '--name=' + self.cname,
168- '--kickstart=' + preseed,
169- '--kopts=' + self.cmdline])
170+ '--kickstart=' + preseed])
171+
172 self.logger.info('Adding system')
173 self._cobble(['system', 'add', '--name=' + self.name,
174 '--profile=' + self.cname, '--netboot-enabled=Y']
175 + ['--' + arg + '=' + self.cargs[arg]
176 for arg in self.cargs])
177
178- self.logger.info('Syncing cobbler')
179- self._cobble(['sync'])
180+ # Things seem to be working fine without this, but sometimes things still get broken
181+ #self.logger.info('Syncing cobbler')
182+ #self._cobble(['sync'])
183+ try:
184+ self._runargs(config.cobblerfix)
185+ except AttributeError:
186+ pass
187 self.restart()
188
189 self.logger.info('Waiting for installation to begin')
190@@ -122,11 +175,21 @@
191 self._cobble(['system', 'edit', '--name=' + self.name,
192 '--netboot-enabled=N'])
193
194+ self.logger.info('System installing')
195+ self.logger.info('Checking every ' + str(checktimeout) +
196+ ' seconds until system is installed')
197+ self.logger.info('Will time out after ' + str(installtimeout)
198+ + ' seconds')
199+ retry(self.sshcheck, checktimeout, logmethod=self.logger.info)
200+
201 if self.debug:
202 self.logger.info('Leaving temp directory '
203 'because debug is enabled: ' + self.tmpdir)
204 else:
205 self.logger.info('Cleaning up temp directory')
206+ if self.installtype == 'desktop':
207+ self.logger.info('Removing NFS share')
208+ self._removenfs()
209 # Cribbed from http://svn.python.org
210 # /projects/python/trunk/Mac/BuildScript/build-installer.py
211 for dirpath, dirnames, filenames in os.walk(self.tmpdir):
212@@ -138,12 +201,6 @@
213 os.chmod(filename, 0775)
214 shutil.rmtree(self.tmpdir)
215
216- self.logger.info('System installing')
217- self.logger.info('Checking every ' + str(checktimeout) +
218- ' seconds until system is installed')
219- self.logger.info('Will time out after ' + str(installtimeout)
220- + ' seconds')
221- retry(self.sshcheck, checktimeout, logmethod=self.logger.info)
222 self.provisioned = True
223 self.active = True
224 uuid_check_command = ('[ "{uuid}" == "$(cat /etc/utah/uuid)" ]'
225@@ -204,10 +261,20 @@
226 """
227 If the machine has an inventory, tell the inventory to release the
228 machine when the object is deleted.
229+ If we exported a directory over NFS, remove it.
230 """
231+ if self.installtype == 'desktop':
232+ self._removenfs()
233 if self.inventory is not None:
234 self.inventory.release(machine=self)
235
236+ def _removenfs(self):
237+ self.logger.info('Removing NFS share')
238+ self._runargs(['sudo', 'sed', '/' + self.tmpdir.replace('/', '\/') +
239+ '/d', '-i', config.nfsconfigfile])
240+ self.logger.debug('Reloading NFS config')
241+ self._runargs(config.nfscommand)
242+
243 def activecheck(self):
244 """
245 Start the machine if needed, and check for SSH login.

Subscribers

People subscribed via source and target branches