def test_run_with_failing_deploy(self): """Check a worker keeps on running even if deploy() raises an exception. """ history = [] def fake_deploy(**params): history.append(params) # always fail raise Exception('test') self.stubs.Set(bmdh, 'deploy', fake_deploy) self.mox.StubOutWithMock(db, 'bm_node_update') # update is called twice inside Worker.run for i in range(6): db.bm_node_update(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()) self.mox.ReplayAll() params_list = [{'fake1': ''}, {'fake2': ''}, {'fake3': ''}] for (dep_id, params) in enumerate(params_list): bmdh.QUEUE.put((dep_id, params)) self.wait_queue_empty(1) self.assertEqual(params_list, history) self.mox.VerifyAll()
def activate_bootloader(self, context, node, instance): """Configure Tilera boot loader for an instance Kernel and ramdisk images are downloaded by cache_tftp_images, and stored in /tftpboot/{uuid}/ This method writes the instances config file, and then creates symlinks for each MAC address in the instance. By default, the complete layout looks like this: /tftpboot/ ./{uuid}/ kernel ./fs_node_id/ """ (root_mb, swap_mb) = get_partition_sizes(instance) tilera_nfs_path = get_tilera_nfs_path(node['id']) image_file_path = get_image_file_path(instance) deployment_key = utils.random_alnum(32) db.bm_node_update(context, node['id'], {'deploy_key': deployment_key, 'image_path': image_file_path, 'pxe_config_path': tilera_nfs_path, 'root_mb': root_mb, 'swap_mb': swap_mb}) if os.path.exists(image_file_path) and \ os.path.exists(tilera_nfs_path): utils.execute('mount', '-o', 'loop', image_file_path, tilera_nfs_path, run_as_root=True)
def _update_state(context, node, instance, state): """Update the node state in baremetal DB If instance is not supplied, reset the instance_uuid field for this node. """ values = {'task_state': state} if not instance: values['instance_uuid'] = None values['instance_name'] = None db.bm_node_update(context, node['id'], values)
def activate_bootloader(self, context, node, instance): """Configure PXE boot loader for an instance Kernel and ramdisk images are downloaded by cache_tftp_images, and stored in /tftpboot/{uuid}/ This method writes the instances config file, and then creates symlinks for each MAC address in the instance. By default, the complete layout looks like this: /tftpboot/ ./{uuid}/ kernel ramdisk deploy_kernel deploy_ramdisk config ./pxelinux.cfg/ {mac} -> ../{uuid}/config """ instance_type = self.virtapi.instance_type_get( context, instance['instance_type_id']) image_info = get_tftp_image_info(instance, instance_type) (root_mb, swap_mb) = get_partition_sizes(instance) pxe_config_file_path = get_pxe_config_file_path(instance) image_file_path = get_image_file_path(instance) deployment_key = utils.random_alnum(32) deployment_iscsi_iqn = "iqn-%s" % instance['uuid'] db.bm_node_update( context, node['id'], { 'deploy_key': deployment_key, 'image_path': image_file_path, 'pxe_config_path': pxe_config_file_path, 'root_mb': root_mb, 'swap_mb': swap_mb }) pxe_config = build_pxe_config( node['id'], deployment_key, deployment_iscsi_iqn, image_info['deploy_kernel'][1], image_info['deploy_ramdisk'][1], image_info['kernel'][1], image_info['ramdisk'][1], ) utils.write_to_file(pxe_config_file_path, pxe_config) macs = self._collect_mac_addresses(context, node) for mac in macs: mac_path = get_pxe_mac_path(mac) utils.unlink_without_raise(mac_path) utils.create_link_without_raise(pxe_config_file_path, mac_path)
def activate_bootloader(self, context, node, instance): """Configure PXE boot loader for an instance Kernel and ramdisk images are downloaded by cache_tftp_images, and stored in /tftpboot/{uuid}/ This method writes the instances config file, and then creates symlinks for each MAC address in the instance. By default, the complete layout looks like this: /tftpboot/ ./{uuid}/ kernel ramdisk deploy_kernel deploy_ramdisk config ./pxelinux.cfg/ {mac} -> ../{uuid}/config """ instance_type = self.virtapi.instance_type_get( context, instance['instance_type_id']) image_info = get_tftp_image_info(instance, instance_type) (root_mb, swap_mb) = get_partition_sizes(instance) pxe_config_file_path = get_pxe_config_file_path(instance) image_file_path = get_image_file_path(instance) deployment_key = utils.random_alnum(32) deployment_iscsi_iqn = "iqn-%s" % instance['uuid'] db.bm_node_update(context, node['id'], {'deploy_key': deployment_key, 'image_path': image_file_path, 'pxe_config_path': pxe_config_file_path, 'root_mb': root_mb, 'swap_mb': swap_mb}) pxe_config = build_pxe_config( node['id'], deployment_key, deployment_iscsi_iqn, image_info['deploy_kernel'][1], image_info['deploy_ramdisk'][1], image_info['kernel'][1], image_info['ramdisk'][1], ) utils.write_to_file(pxe_config_file_path, pxe_config) macs = self._collect_mac_addresses(context, node) for mac in macs: mac_path = get_pxe_mac_path(mac) utils.unlink_without_raise(mac_path) utils.create_link_without_raise(pxe_config_file_path, mac_path)
def deactivate_bootloader(self, context, node, instance): """Delete PXE bootloader images and config.""" try: db.bm_node_update( context, node['id'], { 'deploy_key': None, 'image_path': None, 'pxe_config_path': None, 'root_mb': 0, 'swap_mb': 0 }) except exception.NodeNotFound: pass # NOTE(danms): the instance_type extra_specs do not need to be # present/correct at deactivate time, so pass something empty # to avoid an extra lookup instance_type = dict( extra_specs={ 'baremetal:deploy_ramdisk_id': 'ignore', 'baremetal:deploy_kernel_id': 'ignore' }) try: image_info = get_tftp_image_info(instance, instance_type) except exception.NovaException: pass else: for label in image_info.keys(): (uuid, path) = image_info[label] utils.unlink_without_raise(path) utils.unlink_without_raise(get_pxe_config_file_path(instance)) try: macs = self._collect_mac_addresses(context, node) except db_exc.DBError: pass else: for mac in macs: utils.unlink_without_raise(get_pxe_mac_path(mac)) utils.rmtree_without_raise( os.path.join(CONF.tftp_root, instance['uuid']))
def test_run_calls_deploy(self): """Check all queued requests are passed to deploy().""" history = [] def fake_deploy(**params): history.append(params) self.stubs.Set(bmdh, 'deploy', fake_deploy) self.mox.StubOutWithMock(db, 'bm_node_update') # update is called twice inside Worker.run for i in range(6): db.bm_node_update(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()) self.mox.ReplayAll() params_list = [{'fake1': ''}, {'fake2': ''}, {'fake3': ''}] for (dep_id, params) in enumerate(params_list): bmdh.QUEUE.put((dep_id, params)) self.wait_queue_empty(1) self.assertEqual(params_list, history) self.mox.VerifyAll()
def test_activate_node(self): self._create_node() self.instance['uuid'] = 'fake-uuid' self.config(pxe_deploy_timeout=1, group='baremetal') db.bm_node_update(self.context, 1, {'task_state': states.DEPLOYING, 'instance_uuid': 'fake-uuid'}) # test timeout self.assertRaises(exception.InstanceDeployFailure, self.driver.activate_node, self.context, self.node, self.instance) # test DEPLOYDONE db.bm_node_update(self.context, 1, {'task_state': states.DEPLOYDONE}) self.driver.activate_node(self.context, self.node, self.instance) # test no deploy -- state is just ACTIVE db.bm_node_update(self.context, 1, {'task_state': states.ACTIVE}) self.driver.activate_node(self.context, self.node, self.instance) # test node gone db.bm_node_destroy(self.context, 1) self.assertRaises(exception.InstanceDeployFailure, self.driver.activate_node, self.context, self.node, self.instance)
def test_activate_node(self): self._create_node() self.instance['uuid'] = 'fake-uuid' self.flags(pxe_deploy_timeout=1, group='baremetal') db.bm_node_update(self.context, 1, {'task_state': states.DEPLOYING, 'instance_uuid': 'fake-uuid'}) # test timeout self.assertRaises(exception.InstanceDeployFailure, self.driver.activate_node, self.context, self.node, self.instance) # test DEPLOYDONE db.bm_node_update(self.context, 1, {'task_state': states.DEPLOYDONE}) self.driver.activate_node(self.context, self.node, self.instance) # test no deploy -- state is just ACTIVE db.bm_node_update(self.context, 1, {'task_state': states.ACTIVE}) self.driver.activate_node(self.context, self.node, self.instance) # test node gone db.bm_node_destroy(self.context, 1) self.assertRaises(exception.InstanceDeployFailure, self.driver.activate_node, self.context, self.node, self.instance)
def run(self): while not self.stop: try: # Set timeout to check self.stop periodically (node_id, params) = QUEUE.get(block=True, timeout=self.queue_timeout) except Queue.Empty: pass else: # Requests comes here from BareMetalDeploy.post() LOG.info(_('start deployment for node %(node_id)s, ' 'params %(params)s') % {'node_id': node_id, 'params': params}) context = ironic_context.get_admin_context() try: db.bm_node_update(context, node_id, {'task_state': states.DEPLOYING}) deploy(**params) except Exception: LOG.error(_('deployment to node %s failed') % node_id) db.bm_node_update(context, node_id, {'task_state': states.DEPLOYFAIL}) else: LOG.info(_('deployment to node %s done') % node_id) db.bm_node_update(context, node_id, {'task_state': states.DEPLOYDONE})
def run(self): while not self.stop: try: # Set timeout to check self.stop periodically (node_id, params) = QUEUE.get(block=True, timeout=self.queue_timeout) except Queue.Empty: pass else: # Requests comes here from BareMetalDeploy.post() LOG.info( _('start deployment for node %(node_id)s, ' 'params %(params)s') % { 'node_id': node_id, 'params': params }) context = ironic_context.get_admin_context() try: db.bm_node_update(context, node_id, {'task_state': states.DEPLOYING}) deploy(**params) except Exception: LOG.error(_('deployment to node %s failed') % node_id) db.bm_node_update(context, node_id, {'task_state': states.DEPLOYFAIL}) else: LOG.info(_('deployment to node %s done') % node_id) db.bm_node_update(context, node_id, {'task_state': states.DEPLOYDONE})
def deactivate_bootloader(self, context, node, instance): """Delete PXE bootloader images and config.""" try: db.bm_node_update(context, node['id'], {'deploy_key': None, 'image_path': None, 'pxe_config_path': None, 'root_mb': 0, 'swap_mb': 0}) except exception.NodeNotFound: pass # NOTE(danms): the instance_type extra_specs do not need to be # present/correct at deactivate time, so pass something empty # to avoid an extra lookup instance_type = dict(extra_specs={ 'baremetal:deploy_ramdisk_id': 'ignore', 'baremetal:deploy_kernel_id': 'ignore'}) try: image_info = get_tftp_image_info(instance, instance_type) except exception.NovaException: pass else: for label in image_info.keys(): (uuid, path) = image_info[label] utils.unlink_without_raise(path) utils.unlink_without_raise(get_pxe_config_file_path(instance)) try: macs = self._collect_mac_addresses(context, node) except db_exc.DBError: pass else: for mac in macs: utils.unlink_without_raise(get_pxe_mac_path(mac)) utils.rmtree_without_raise( os.path.join(CONF.tftp_root, instance['uuid']))
def deactivate_bootloader(self, context, node, instance): """Delete Tilera bootloader images and config.""" try: db.bm_node_update(context, node['id'], {'deploy_key': None, 'image_path': None, 'pxe_config_path': None, 'root_mb': 0, 'swap_mb': 0}) except exception.NodeNotFound: pass tilera_nfs_path = get_tilera_nfs_path(node['id']) if os.path.ismount(tilera_nfs_path): utils.execute('rpc.mountd', run_as_root=True) utils.execute('umount', '-f', tilera_nfs_path, run_as_root=True) try: image_info = get_tftp_image_info(instance) except exception.NovaException: pass else: for label in image_info.keys(): (uuid, path) = image_info[label] utils.unlink_without_raise(path) try: self._collect_mac_addresses(context, node) except db_exc.DBError: pass if os.path.exists(os.path.join(CONF.tftp_root, instance['uuid'])): utils.rmtree_without_raise( os.path.join(CONF.tftp_root, instance['uuid']))