Merge lp:~nuclearbob/utah/baremetal-standardization into lp:utah

Proposed by Max Brustkern
Status: Merged
Approved by: Javier Collado
Approved revision: 759
Merged at revision: 777
Proposed branch: lp:~nuclearbob/utah/baremetal-standardization
Merge into: lp:utah
Diff against target: 630 lines (+157/-167)
9 files modified
examples/run_test_bamboo_feeder.py (+2/-2)
examples/run_test_cobbler.py (+2/-2)
examples/run_utah_tests.py (+0/-1)
utah/config.py (+2/-3)
utah/provisioning/baremetal/bamboofeeder.py (+8/-26)
utah/provisioning/baremetal/cobbler.py (+85/-110)
utah/provisioning/baremetal/power.py (+18/-3)
utah/provisioning/inventory/sqlite.py (+17/-17)
utah/provisioning/provisioning.py (+23/-3)
To merge this branch: bzr merge lp:~nuclearbob/utah/baremetal-standardization
Reviewer Review Type Date Requested Status
Javier Collado (community) Approve
Max Brustkern (community) Needs Resubmitting
Review via email: mp+136502@code.launchpad.net

Description of the change

This branch contains a number of changes I started working on at UDS to simplify and improve the existing bare metal provisioning methods. I'll detail them below.

To post a comment you must log in.
Revision history for this message
Max Brustkern (nuclearbob) wrote :

CobblerMachine now uses the standardized cleanup functions, and removes the machine from cobbler as part of that. I improved some docstrings. I added an option to the _cobbler method of CobblerMachine to not raise an exception on failure for commands that may fail sometimes (i.e. power control and pre-emptively deleting the system info from cobbler.) I removed an old cobbler sync command that has been commented out for a while and the obsolete cobblerfix workaround for the lab. I moved processing of power-related arguments from the two separate machines into a new __init__ function for the PowerMixin. I cleaned up some indentation on exceptions. I changed the pipe involed with uInitrd manipulation to attempt to suppress the standard error of dd.

754. By Max Brustkern

Removed boot argument since the Machine class handles that now

Revision history for this message
Javier Collado (javier.collado) wrote :

pyflakes returns the following problems:
utah/provisioning/baremetal/cobbler.py:70: undefined name 'subprocess'
utah/provisioning/inventory/sqlite.py:138: local variable 'pid' is assigned to but never used

First one should really be fixed.

review: Needs Fixing
Revision history for this message
Max Brustkern (nuclearbob) wrote :

Definitely. That's a doozy. I'll go over both of these, and revisit integrating static analysis into my editor, or choosing a new editor that supports it.

755. By Max Brustkern

Merge default yaml work
Merged latest changes from dev branch

756. By Max Brustkern

Resolved pep8 and pyflakes errors

757. By Max Brustkern

Moved inventory cleanup after cleanup initialization

758. By Max Brustkern

Removing direct interaction with nfsfile since we need sudo for that

Revision history for this message
Max Brustkern (nuclearbob) wrote :

I've fixed static analysis errors and tested this with cobbler in magners, and it seems to be working well.

review: Needs Resubmitting
759. By Max Brustkern

Renamed Cobbler inventory to more genertic Baremetal

Revision history for this message
Javier Collado (javier.collado) wrote :

The problems in my previous comment are fixed. Thanks.

(I still need to learn how to test bare metal provisioning at some point).

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'examples/run_test_bamboo_feeder.py'
--- examples/run_test_bamboo_feeder.py 2012-12-08 02:10:12 +0000
+++ examples/run_test_bamboo_feeder.py 2012-12-10 20:39:20 +0000
@@ -23,7 +23,7 @@
23from utah.exceptions import UTAHException23from utah.exceptions import UTAHException
24from utah.group import check_user_group, print_group_error_message24from utah.group import check_user_group, print_group_error_message
25from utah.provisioning.baremetal.bamboofeeder import BambooFeederMachine25from utah.provisioning.baremetal.bamboofeeder import BambooFeederMachine
26from utah.provisioning.inventory.sqlite import ManualCobblerSQLiteInventory26from utah.provisioning.inventory.sqlite import ManualBaremetalSQLiteInventory
27from utah.run import run_tests27from utah.run import run_tests
28from utah.url import url_argument28from utah.url import url_argument
2929
@@ -81,7 +81,7 @@
81 machine = None81 machine = None
8282
83 try:83 try:
84 inventory = ManualCobblerSQLiteInventory(84 inventory = ManualBaremetalSQLiteInventory(
85 db=os.path.join('~', '.utah-bamboofeeder-inventory'),85 db=os.path.join('~', '.utah-bamboofeeder-inventory'),
86 lockfile=os.path.join('~', '.utah-bamboofeeder-lock'))86 lockfile=os.path.join('~', '.utah-bamboofeeder-lock'))
87 kw = {}87 kw = {}
8888
=== modified file 'examples/run_test_cobbler.py'
--- examples/run_test_cobbler.py 2012-12-08 02:10:12 +0000
+++ examples/run_test_cobbler.py 2012-12-10 20:39:20 +0000
@@ -21,7 +21,7 @@
21from utah import config21from utah import config
22from utah.exceptions import UTAHException22from utah.exceptions import UTAHException
23from utah.group import check_user_group, print_group_error_message23from utah.group import check_user_group, print_group_error_message
24from utah.provisioning.inventory.sqlite import ManualCobblerSQLiteInventory24from utah.provisioning.inventory.sqlite import ManualBaremetalSQLiteInventory
25from utah.run import run_tests25from utah.run import run_tests
26from utah.url import url_argument26from utah.url import url_argument
2727
@@ -95,7 +95,7 @@
95 sys.exit(4)95 sys.exit(4)
9696
97 try:97 try:
98 inventory = ManualCobblerSQLiteInventory()98 inventory = ManualBaremetalSQLiteInventory()
99 kw = {}99 kw = {}
100 for arg in ['image', 'preseed', 'rewrite']:100 for arg in ['image', 'preseed', 'rewrite']:
101 value = vars(args)[arg]101 value = vars(args)[arg]
102102
=== modified file 'examples/run_utah_tests.py'
--- examples/run_utah_tests.py 2012-12-08 02:10:12 +0000
+++ examples/run_utah_tests.py 2012-12-10 20:39:20 +0000
@@ -22,7 +22,6 @@
22from utah.url import url_argument22from utah.url import url_argument
23from utah.group import check_user_group, print_group_error_message23from utah.group import check_user_group, print_group_error_message
24from utah.timeout import timeout, UTAHTimeout24from utah.timeout import timeout, UTAHTimeout
25from utah import config
26from run_install_test import run_install_test25from run_install_test import run_install_test
2726
2827
2928
=== modified file 'utah/config.py'
--- utah/config.py 2012-12-10 13:01:20 +0000
+++ utah/config.py 2012-12-10 20:39:20 +0000
@@ -99,10 +99,9 @@
99 name=None,99 name=None,
100 # Default setting of installing a new machine vs. using an existing one100 # Default setting of installing a new machine vs. using an existing one
101 new=False,101 new=False,
102 # Command to reload NFS configuration
103 # NFS options currently only used for cobbler-based desktop installs102 # NFS options currently only used for cobbler-based desktop installs
104 nfscommand=['sudo', os.path.join('/', 'etc', 'init.d',103 # NFS service command
105 'nfs-kernel-server'), 'reload'],104 nfscommand=['sudo', 'service', 'nfs-kernel-server'],
106 # Path to NFS config file105 # Path to NFS config file
107 nfsconfigfile=os.path.join('/', 'etc', 'exports'),106 nfsconfigfile=os.path.join('/', 'etc', 'exports'),
108 # Default options for NFS shares107 # Default options for NFS shares
109108
=== modified file 'utah/provisioning/baremetal/bamboofeeder.py'
--- utah/provisioning/baremetal/bamboofeeder.py 2012-12-08 02:10:12 +0000
+++ utah/provisioning/baremetal/bamboofeeder.py 2012-12-10 20:39:20 +0000
@@ -39,30 +39,20 @@
39 """39 """
40 Provide a class to provision an ARM board from a bamboo-feeder setup.40 Provide a class to provision an ARM board from a bamboo-feeder setup.
41 """41 """
42 def __init__(self, cargs=None, inventory=None, name=None, powercmd=None,42 def __init__(self, inventory=None, machineinfo=None, name=None,
43 preboot=None, *args, **kw):43 preboot=None, *args, **kw):
44 # TODO: change the name of cargs here and elsewhere44 # TODO: change the name of cargs here and elsewhere
45 # TODO: respect rewrite setting45 # TODO: respect rewrite setting
46 if name is None:46 if name is None:
47 raise UTAHBMProvisioningException(47 raise UTAHBMProvisioningException(
48 'Machine name reqired for bamboo-feeder machine')48 'Machine name reqired for bamboo-feeder machine')
49 if powercmd is not None:
50 self.powercmd = powercmd
51 elif cargs is not None:
52 self.power = {}
53 for item in cargs:
54 if 'power' in item:
55 self.power[item] = cargs[item]
56 else:
57 raise UTAHBMProvisioningException(
58 'No power control information specified')
59 try:49 try:
60 self.macaddress = cargs['mac-address']50 self.macaddress = machineinfo['mac-address']
61 except AttributeError:51 except AttributeError:
62 raise UTAHBMProvisioningException(52 raise UTAHBMProvisioningException('No MAC address specified')
63 'No MAC address specified')
64 self.inventory = inventory53 self.inventory = inventory
65 super(BambooFeederMachine, self).__init__(*args, name=name, **kw)54 super(BambooFeederMachine, self).__init__(*args,
55 machineinfo=machineinfo, name=name, **kw)
66 if self.inventory is not None:56 if self.inventory is not None:
67 self.cleanfunction(self.inventory.release, machine=self)57 self.cleanfunction(self.inventory.release, machine=self)
68 self._depcheck()58 self._depcheck()
@@ -147,10 +137,10 @@
147 headersize = filesize - datasize137 headersize = filesize - datasize
148 self.logger.debug('uInitrd header size is ' + str(headersize))138 self.logger.debug('uInitrd header size is ' + str(headersize))
149 pipe = pipes.Template()139 pipe = pipes.Template()
150 pipe.prepend('dd if=$IN bs=1 skip=' + str(headersize), 'f-')140 pipe.prepend('dd if=$IN bs=1 skip=' + str(headersize) +
141 ' 2>/dev/null', 'f-')
151 pipe.append('gunzip', '--')142 pipe.append('gunzip', '--')
152 pipe.append('cpio -ivd 2>/dev/null', '-.')143 pipe.append('cpio -ivd 2>/dev/null', '-.')
153 # TODO: suppress dd output
154 pipe.copy(self.initrd, '/dev/null')144 pipe.copy(self.initrd, '/dev/null')
155145
156 def _repackinitrd(self):146 def _repackinitrd(self):
@@ -293,15 +283,7 @@
293283
294 self.provisioned = True284 self.provisioned = True
295 self.active = True285 self.active = True
296 # TODO: Make this a method that this and CobblerMachine can call286 self._uuid_check()
297 uuid_check_command = ('[ "{uuid}" == "$(cat /etc/utah/uuid)" ]'
298 .format(uuid=self.uuid))
299 if self.run(uuid_check_command)[0] != 0:
300 self.provisioned = False
301 raise UTAHBMProvisioningException(
302 'Installed UUID differs from Machine UUID; '
303 'installation probably failed. '
304 'Try restarting cobbler or running cobbler sync')
305 self.logger.info('System installed')287 self.logger.info('System installed')
306 self.cleanfunction(self.run, (288 self.cleanfunction(self.run, (
307 'dd', 'bs=512k', 'count=10', 'if=/dev/zero', 'of=/dev/mmcblk0'),289 'dd', 'bs=512k', 'count=10', 'if=/dev/zero', 'of=/dev/mmcblk0'),
308290
=== modified file 'utah/provisioning/baremetal/cobbler.py'
--- utah/provisioning/baremetal/cobbler.py 2012-12-08 02:10:12 +0000
+++ utah/provisioning/baremetal/cobbler.py 2012-12-10 20:39:20 +0000
@@ -21,6 +21,7 @@
21import os21import os
22import pipes22import pipes
23import shutil23import shutil
24import subprocess
24import tempfile25import tempfile
25import time26import time
2627
@@ -39,31 +40,28 @@
39 """40 """
40 Provide a class to provision a machine via cobbler.41 Provide a class to provision a machine via cobbler.
41 """42 """
42 # TODO: may need to fix DHCP/hostname issues, may just be magners43 def __init__(self, inventory=None, machineinfo=None,
43 def __init__(self, cargs=None, inventory=None, name=None, preseed=None,44 name=None, *args, **kw):
44 *args, **kw):45 # TODO: support for reusing existing machines
45 if name is None:46 if name is None:
46 raise UTAHBMProvisioningException(47 raise UTAHBMProvisioningException(
47 'Machine name reqired for cobbler machine')48 'Machine name reqired for cobbler machine')
48 if cargs is None:49 if machineinfo is None:
49 raise UTAHBMProvisioningException(50 raise UTAHBMProvisioningException(
50 'No cobbler arguments given for machine creation')51 'No cobbler arguments given for machine creation')
51 else:52 else:
52 self.cargs = cargs53 self.machineinfo = machineinfo
53 self.power = {}54 self.power = {}
54 for item in cargs:
55 if 'power' in item:
56 self.power[item] = cargs[item]
57 self.inventory = inventory55 self.inventory = inventory
58 if preseed is None:56 super(CobblerMachine, self).__init__(*args, machineinfo=machineinfo,
59 preseed = '/etc/utah/default-preseed.cfg'57 name=name, **kw)
60 super(CobblerMachine, self).__init__(*args, name=name,58 if self.inventory is not None:
61 preseed=preseed, **kw)59 self.cleanfunction(self.inventory.release, machine=self)
62 if self.image is None:60 if self.image is None:
63 raise UTAHBMProvisioningException(61 raise UTAHBMProvisioningException(
64 'Image file required for cobbler installation')62 'Image file required for cobbler installation')
65 self._custominit()63 self._custominit()
66 # TODO: verify we have nfs support for desktop image64 self._depcheck()
6765
68 # TODO: Rework cinitrd to be less of a confusing collection of kludges66 # TODO: Rework cinitrd to be less of a confusing collection of kludges
69 self.cinitrd = None67 self.cinitrd = None
@@ -79,13 +77,27 @@
79 self.logger.debug('Cobbler arch is ' + self.carch)77 self.logger.debug('Cobbler arch is ' + self.carch)
80 self.logger.debug('Cobbler machine init finished')78 self.logger.debug('Cobbler machine init finished')
8179
82 def _provision(self, checktimeout=config.checktimeout,80 def _load(self):
81 """
82 Verify the machine is in cobbler.
83 """
84 # TODO: consider reworking _cobble to provide this
85 # (only if we'll be using cobbler for a while longer)
86 machines = subprocess.check_output(['sudo', 'cobbler', 'system',
87 'find']).splitlines()
88 if self.name not in machines:
89 raise UTAHBMProvisioningException('No machine named ' + self.name
90 + ' exists in cobbler')
91 else:
92 return True
93
94 def _create(self, checktimeout=config.checktimeout,
83 installtimeout=config.installtimeout):95 installtimeout=config.installtimeout):
84 """96 """
85 Install a machine.97 Install a machine.
86 """98 """
87 # TODO: support for reusing existing machines
88 self.tmpdir = tempfile.mkdtemp(prefix='/tmp/' + self.name + '_')99 self.tmpdir = tempfile.mkdtemp(prefix='/tmp/' + self.name + '_')
100 self.cleanfile(self.tmpdir)
89 os.chdir(self.tmpdir)101 os.chdir(self.tmpdir)
90102
91 # TODO: try to remove this step, mount the iso and import that103 # TODO: try to remove this step, mount the iso and import that
@@ -102,6 +114,7 @@
102 initrd = self._prepareinitrd(initrd=cinitrd)114 initrd = self._prepareinitrd(initrd=cinitrd)
103 self._unpackinitrd(initrd=initrd)115 self._unpackinitrd(initrd=initrd)
104 self._setuplatecommand()116 self._setuplatecommand()
117 # TODO: see if this is needed for all quantal desktops
105 if self.installtype == 'desktop':118 if self.installtype == 'desktop':
106 self.logger.info('Configuring latecommand for desktop')119 self.logger.info('Configuring latecommand for desktop')
107 myfile = open(os.path.join(self.tmpdir, 'initrd.d',120 myfile = open(os.path.join(self.tmpdir, 'initrd.d',
@@ -118,18 +131,12 @@
118 shutil.copyfile(initrd, cinitrd)131 shutil.copyfile(initrd, cinitrd)
119132
120 self.logger.info('Setting up system with cobbler')133 self.logger.info('Setting up system with cobbler')
121 self.logger.debug('Removing old system')134 self._cleanupcobbler()
122 self._cobble(['system', 'remove', '--name=' + self.name])
123 self.logger.info('Removing old profile')
124 self._cobble(['profile', 'remove', '--name=' + self.cname])
125 self.logger.info('Removing old distro')
126 self._cobble(['distro', 'remove', '--name=' + self.cname])
127135
128 preseed = os.path.join(self.tmpdir, 'initrd.d', 'preseed.cfg')136 preseed = os.path.join(self.tmpdir, 'initrd.d', 'preseed.cfg')
129137
130 if self.installtype in ['alternate', 'server']:138 if self.installtype in ['alternate', 'server']:
131 # TODO: support more image types,139 # TODO: maybe do this without unpacking ISO
132 # maybe do this without unpacking ISO
133 self.logger.info('Importing image')140 self.logger.info('Importing image')
134 self._cobble(['import', '--name=' + self.cname,141 self._cobble(['import', '--name=' + self.cname,
135 '--path=' + self.tmpdir, '--arch=' + self.carch])142 '--path=' + self.tmpdir, '--arch=' + self.carch])
@@ -144,16 +151,14 @@
144 if self.installtype == 'desktop':151 if self.installtype == 'desktop':
145 self.logger.info('Setting up NFS for desktop install')152 self.logger.info('Setting up NFS for desktop install')
146 self.logger.debug('Adding export to NFS config file')153 self.logger.debug('Adding export to NFS config file')
147# nfsfile = open(config.nfsconfigfile, 'a')154 self.cleanfunction(self._removenfs)
148# nfsfile.write("\n" + self.tmpdir + ' ' + config.nfsoptions + "\n")
149# nfsfile.close()
150 pipe = pipes.Template()155 pipe = pipes.Template()
151 pipe.append('sudo tee -a ' + str(config.nfsconfigfile) +156 pipe.append('sudo tee -a ' + str(config.nfsconfigfile) +
152 ' >/dev/null', '-.')157 ' >/dev/null', '-.')
153 pipe.open('/dev/null', 'w').write(self.tmpdir + ' ' +158 pipe.open('/dev/null', 'w').write(self.tmpdir + ' ' +
154 config.nfsoptions + "\n")159 config.nfsoptions + "\n")
155 self.logger.debug('Reloading NFS config')160 self.logger.debug('Reloading NFS config')
156 self._runargs(config.nfscommand)161 self._runargs(config.nfscommand + ['reload'])
157 self.logger.debug('Adding NFS boot options')162 self.logger.debug('Adding NFS boot options')
158 try:163 try:
159 iface = config.nfsiface164 iface = config.nfsiface
@@ -164,6 +169,7 @@
164 ip + ':' + self.tmpdir)169 ip + ':' + self.tmpdir)
165 self.cmdline = self.cmdline.strip()170 self.cmdline = self.cmdline.strip()
166171
172 self.cleanfunction(self._cleanupcobbler)
167 self.logger.info('Adding kernel boot options to distro')173 self.logger.info('Adding kernel boot options to distro')
168 self._cobble(['distro', 'edit', '--name=' + self.cname,174 self._cobble(['distro', 'edit', '--name=' + self.cname,
169 '--kopts=' + self.cmdline])175 '--kopts=' + self.cmdline])
@@ -175,17 +181,9 @@
175 self.logger.info('Adding system')181 self.logger.info('Adding system')
176 self._cobble(['system', 'add', '--name=' + self.name,182 self._cobble(['system', 'add', '--name=' + self.name,
177 '--profile=' + self.cname, '--netboot-enabled=Y']183 '--profile=' + self.cname, '--netboot-enabled=Y']
178 + ['--' + arg + '=' + self.cargs[arg]184 + ['--' + arg + '=' + self.machineinfo[arg]
179 for arg in self.cargs])185 for arg in self.machineinfo])
180186
181 # Things seem to be working fine without this,
182 # but sometimes things still get broken
183 #self.logger.info('Syncing cobbler')
184 #self._cobble(['sync'])
185 try:
186 self._runargs(config.cobblerfix)
187 except AttributeError:
188 pass
189 self.restart()187 self.restart()
190188
191 self.logger.info('Waiting for installation to begin')189 self.logger.info('Waiting for installation to begin')
@@ -204,45 +202,26 @@
204 self.logger.info('Removing NFS share')202 self.logger.info('Removing NFS share')
205 self._removenfs()203 self._removenfs()
206204
207 if self.debug:
208 self.logger.info('Leaving temp directory '
209 'because debug is enabled: ' + self.tmpdir)
210 else:
211 self.logger.info('Cleaning up temp directory')
212 self._cleanuptmpdir()
213
214 self.provisioned = True205 self.provisioned = True
215 self.active = True206 self.active = True
216 uuid_check_command = ('[ "{uuid}" == "$(cat /etc/utah/uuid)" ]'207 self._uuid_check()
217 .format(uuid=self.uuid))
218 if self.run(uuid_check_command)[0] != 0:
219 self.provisioned = False
220 raise UTAHBMProvisioningException(
221 'Installed UUID differs from CobblerMachine UUID; '
222 'installation probably failed. '
223 'Try restarting cobbler or running cobbler sync')
224 self.logger.info('System installed')208 self.logger.info('System installed')
225 return True209 return True
226210
227 def destroy(self, *args, **kw):211 def _cobble(self, cmd, failok=False):
228 """
229 Destroy the machine, and call super to release it in the inventory.
230 """
231 # TODO: Remove the machine from cobbler
232 # TODO: Consider actually wrecking the install
233 super(CobblerMachine, self).destroy(*args, **kw)
234 self.__del__()
235 del self
236
237 def _cobble(self, cmd):
238 """212 """
239 Pull out all cobbler commands so that we can later support changing213 Pull out all cobbler commands so that we can later support changing
240 users, remote login, not sudo, etc.214 users, remote login, not sudo, etc.
241 """215 """
242 if self._runargs(['sudo', 'cobbler'] + cmd) != 0:216 retcode = self._runargs(['sudo', 'cobbler'] + cmd)
217 if retcode != 0:
243 error_msg = 'Cobbler command failed: ' + ' '.join(cmd)218 error_msg = 'Cobbler command failed: ' + ' '.join(cmd)
244 self.logger.error(error_msg)219 if failok:
245 raise UTAHBMProvisioningException(error_msg)220 self.logger.debug(error_msg)
221 return retcode
222 else:
223 self.logger.error(error_msg)
224 raise UTAHBMProvisioningException(error_msg)
246225
247 def _start(self):226 def _start(self):
248 """227 """
@@ -250,9 +229,11 @@
250 If that fails, use the powercommand generated by PowerMachine.229 If that fails, use the powercommand generated by PowerMachine.
251 """230 """
252 self.logger.debug('Starting system')231 self.logger.debug('Starting system')
253 try:232 retcode = self._cobble(['system', 'poweron', '--name=' + self.name],
254 self._cobble(['system', 'poweron', '--name=' + self.name])233 failok=True)
255 except UTAHBMProvisioningException:234 if retcode != 0:
235 self.logger.info('Cobbler power command failed; falling back to '
236 'manual command')
256 self._runargs(self.powercommand() + ['on'])237 self._runargs(self.powercommand() + ['on'])
257 self.active = True238 self.active = True
258239
@@ -262,52 +243,46 @@
262 If that fails, use the powercommand generated by PowerMachine.243 If that fails, use the powercommand generated by PowerMachine.
263 """244 """
264 self.logger.debug('Stopping system')245 self.logger.debug('Stopping system')
265 try:246 retcode = self._cobble(['system', 'poweroff', '--name=' + self.name],
266 self._cobble(['system', 'poweroff', '--name=' + self.name])247 failok=True)
267 except UTAHBMProvisioningException:248 if retcode != 0:
249 self.logger.info('Cobbler power command failed; falling back to '
250 'manual command')
268 self._runargs(self.powercommand() + ['off'])251 self._runargs(self.powercommand() + ['off'])
269 self.active = False252 self.active = False
270253
271 def __del__(self):
272 """
273 If the machine has an inventory, tell the inventory to release the
274 machine when the object is deleted.
275 If we exported a directory over NFS, remove it.
276 """
277 if self.installtype == 'desktop':
278 self._removenfs()
279 if not self.debug:
280 self._cleanuptmpdir()
281 if self.inventory is not None:
282 self.inventory.release(machine=self)
283
284 def _removenfs(self):254 def _removenfs(self):
255 """
256 Remove our NFS configuration and reload NFS.
257 """
285 self.logger.info('Removing NFS share')258 self.logger.info('Removing NFS share')
286 self._runargs(['sudo', 'sed', '/' + self.tmpdir.replace('/', '\/') +259 self._runargs(['sudo', 'sed', '/' + self.tmpdir.replace('/', '\/') +
287 '/d', '-i', config.nfsconfigfile])260 '/d', '-i', config.nfsconfigfile])
288 self.logger.debug('Reloading NFS config')261 self.logger.debug('Reloading NFS config')
289 self._runargs(config.nfscommand)262 self._runargs(config.nfscommand + ['reload'])
290263
291 def _cleanuptmpdir(self):264 def _depcheck(self):
292 if os.path.isdir(self.tmpdir):265 """
293 # Cribbed from http://svn.python.org266 Check for NFS if installtype is desktop.
294 # /projects/python/trunk/Mac/BuildScript/build-installer.py267 """
295 for dirpath, dirnames, filenames in os.walk(self.tmpdir):268 super(CobblerMachine, self)._depcheck()
296 for name in (dirnames + filenames):269 if self.installtype == 'desktop':
297 absolute_name = os.path.join(dirpath, name)270 cmd = config.nfscommand + ['status']
298 if not os.path.islink(absolute_name):271 if self._runargs(cmd) != 0:
299 self.logger.debug('Changing permissions of '272 raise UTAHBMProvisioningException('NFS needed for desktop'
300 + absolute_name)273 ' install')
301 os.chmod(absolute_name, 0775)274 if not os.path.isfile(config.nfsconfigfile):
302 shutil.rmtree(self.tmpdir)275 raise UTAHBMProvisioningException('NFS config file: ' +
303276 config.nfsconfigfile + ' not available')
304 def activecheck(self):277
305 """278 def _cleanupcobbler(self):
306 Start the machine if needed, and check for SSH login.279 """
307 """280 Remove our system, profile, and distro from Cobbler.
308 # TODO: Consider moving this to SSHMixin281 """
309 self.logger.debug('Checking if machine is active')282 self.logger.debug('Removing old system')
310 self.provisioncheck()283 self._cobble(['system', 'remove', '--name=' + self.name], failok=True)
311 if not self.active:284 self.logger.info('Removing old profile')
312 self._start()285 self._cobble(['profile', 'remove', '--name=' + self.cname],
313 self.sshcheck()286 failok=True)
287 self.logger.info('Removing old distro')
288 self._cobble(['distro', 'remove', '--name=' + self.cname], failok=True)
314289
=== modified file 'utah/provisioning/baremetal/power.py'
--- utah/provisioning/baremetal/power.py 2012-12-08 02:10:12 +0000
+++ utah/provisioning/baremetal/power.py 2012-12-10 20:39:20 +0000
@@ -28,7 +28,23 @@
28 """28 """
29 Provide power cycle commands for the Sentry CDU.29 Provide power cycle commands for the Sentry CDU.
30 """30 """
31 def __init__(self, machineinfo=None, powercmd=None, *args, **kw):
32 """
33 Store power control info for later use.
34 """
35 if powercmd is not None:
36 self.powercmd = powercmd
37 elif machineinfo is not None:
38 self.power = {}
39 for item in machineinfo:
40 if 'power' in item:
41 self.power[item] = machineinfo[item]
42 super(PowerMixin, self).__init__(*args, **kw)
43
31 def powercommand(self):44 def powercommand(self):
45 """
46 Return the command used to control power for this machine.
47 """
32 try:48 try:
33 cmd = self.powercmd49 cmd = self.powercmd
34 except AttributeError:50 except AttributeError:
@@ -41,9 +57,8 @@
41 '-p', self.power['power-pass'],57 '-p', self.power['power-pass'],
42 '-o']58 '-o']
43 else:59 else:
44 raise UTAHProvisioningException('Power type ' +60 raise UTAHBMProvisioningException('Power type ' +
45 self.power['power-type'] +61 self.power['power-type'] + ' not supported')
46 ' not supported')
47 except AttributeError:62 except AttributeError:
48 raise UTAHBMProvisioningException('Power commands not defined'63 raise UTAHBMProvisioningException('Power commands not defined'
49 ' for this machine')64 ' for this machine')
5065
=== modified file 'utah/provisioning/inventory/sqlite.py'
--- utah/provisioning/inventory/sqlite.py 2012-12-08 02:10:12 +0000
+++ utah/provisioning/inventory/sqlite.py 2012-12-10 20:39:20 +0000
@@ -93,7 +93,7 @@
93 return False93 return False
9494
9595
96class ManualCobblerSQLiteInventory(SQLiteInventory):96class ManualBaremetalSQLiteInventory(SQLiteInventory):
97 """97 """
98 Keep an inventory of manually entered machines for use with cobbler.98 Keep an inventory of manually entered machines for use with cobbler.
99 All columns other than machineid, name, and state are assumed to be99 All columns other than machineid, name, and state are assumed to be
@@ -107,7 +107,7 @@
107 if not os.path.isfile(db):107 if not os.path.isfile(db):
108 raise UTAHProvisioningInventoryException(108 raise UTAHProvisioningInventoryException(
109 'No machine database found at ' + db)109 'No machine database found at ' + db)
110 super(ManualCobblerSQLiteInventory, self).__init__(*args, db=db,110 super(ManualBaremetalSQLiteInventory, self).__init__(*args, db=db,
111 lockfile=lockfile,111 lockfile=lockfile,
112 **kw)112 **kw)
113 machines_count = (self.connection113 machines_count = (self.connection
@@ -128,37 +128,37 @@
128 raise UTAHProvisioningInventoryException(128 raise UTAHProvisioningInventoryException(
129 'No machines meet criteria')129 'No machines meet criteria')
130 else:130 else:
131 for machineinfo in result:131 for minfo in result:
132 cargs = dict(machineinfo)132 machineinfo = dict(minfo)
133 if cargs['state'] == 'available':133 if machineinfo['state'] == 'available':
134 return self._take(cargs, *args, **kw)134 return self._take(machineinfo, *args, **kw)
135 for machineinfo in result:135 for minfo in result:
136 cargs = dict(machineinfo)136 machineinfo = dict(minfo)
137 pid = cargs['pid']137 pid = machineinfo['pid']
138 try:138 try:
139 if not (psutil.pid_exists(pid) and ('utah' in139 if not (psutil.pid_exists(pid) and ('utah' in
140 ' '.join(psutil.Process(pid).cmdline)140 ' '.join(psutil.Process(pid).cmdline)
141 or 'run_test_cobbler.py' in141 or 'run_test_cobbler.py' in
142 ' '.join(psutil.Process(pid).cmdline))):142 ' '.join(psutil.Process(pid).cmdline))):
143 return self._take(cargs, *args, **kw)143 return self._take(machineinfo, *args, **kw)
144 except ValueError:144 except ValueError:
145 continue145 continue
146146
147 raise UTAHProvisioningInventoryException(147 raise UTAHProvisioningInventoryException(
148 'All machines meeting criteria are currently unavailable')148 'All machines meeting criteria are currently unavailable')
149149
150 def _take(self, cargs, *args, **kw):150 def _take(self, machineinfo, *args, **kw):
151 machineid = cargs.pop('machineid')151 machineid = machineinfo.pop('machineid')
152 name = cargs.pop('name')152 name = machineinfo.pop('name')
153 state = cargs.pop('state')153 state = machineinfo.pop('state')
154 pid = cargs.pop('pid')154 machineinfo.pop('pid')
155 update = self.connection.execute(155 update = self.connection.execute(
156 "UPDATE machines SET pid=?, state='provisioned' WHERE machineid=?"156 "UPDATE machines SET pid=?, state='provisioned' WHERE machineid=?"
157 "AND state=?",157 "AND state=?",
158 [os.getpid(), machineid, state]).rowcount158 [os.getpid(), machineid, state]).rowcount
159 if update == 1:159 if update == 1:
160 machine = CobblerMachine(*args, cargs=cargs,160 machine = CobblerMachine(*args, inventory=self,
161 inventory=self, name=name, **kw)161 machineinfo=machineinfo, name=name, **kw)
162 self.machines.append(machine)162 self.machines.append(machine)
163 return machine163 return machine
164 elif update == 0:164 elif update == 0:
165165
=== modified file 'utah/provisioning/provisioning.py'
--- utah/provisioning/provisioning.py 2012-12-06 16:30:34 +0000
+++ utah/provisioning/provisioning.py 2012-12-10 20:39:20 +0000
@@ -454,12 +454,12 @@
454 from libvirt if it is registered there.454 from libvirt if it is registered there.
455 For a physical machine, this should free it up to be used by another455 For a physical machine, this should free it up to be used by another
456 process in the future, and destroy sensitive data if any exists.456 process in the future, and destroy sensitive data if any exists.
457 Destroying the install on a physical machine is optional, but it457 Destroying the install on a physical machine is optional.
458 should be powered off if remote power management is available.
459 Now returns False by default to work with multiple inheritance.
460 """458 """
459 self.provisioned = False
461 self.__del__()460 self.__del__()
462 del self461 del self
462 return True
463463
464 def _load(self):464 def _load(self):
465 """465 """
@@ -664,6 +664,16 @@
664 def __del__(self):664 def __del__(self):
665 self.cleanup()665 self.cleanup()
666666
667 def _uuid_check(self):
668 uuid_check_command = ('[ "{uuid}" == "$(cat /etc/utah/uuid)" ]'
669 .format(uuid=self.uuid))
670 if self.run(uuid_check_command)[0] != 0:
671 self.provisioned = False
672 raise UTAHProvisioningException(
673 'Installed UUID differs from Machine UUID; '
674 'installation probably failed. '
675 'Try rerunning install.')
676
667677
668class SSHMixin(object):678class SSHMixin(object):
669 """679 """
@@ -885,6 +895,16 @@
885 utah.timeout.timeout(timeout, retry, self.sshcheck, checktimeout,895 utah.timeout.timeout(timeout, retry, self.sshcheck, checktimeout,
886 logmethod=logmethod)896 logmethod=logmethod)
887897
898 def activecheck(self):
899 """
900 Start the machine if needed, and check for SSH login.
901 """
902 self.logger.debug('Checking if machine is active')
903 self.provisioncheck()
904 if not self.active:
905 self._start()
906 self.sshcheck()
907
888908
889class CustomInstallMixin(object):909class CustomInstallMixin(object):
890 """910 """

Subscribers

People subscribed via source and target branches