def test_activity_is_not_logged_when_leaving_power_settings_empty(self): # The bug was that we were recording a change to power_user or # power_passwd because it changed from NULL to ''. with session.begin(): self.system.power.power_type = PowerType.lazy_create(name=u'ilo') self.system.power.power_user = None self.system.power.power_passwd = None self.system.power.power_id = None PowerType.lazy_create(name=u'drac') self.assertEquals(len(self.system.activity), 0) b = self.browser login(b) self.go_to_system_view(tab='Power Settings') tab = b.find_element_by_id('power-settings') # change power type but leave the other fields empty BootstrapSelect(tab.find_element_by_name('power_type'))\ .select_by_visible_text('drac') tab.find_element_by_tag_name('form').submit() tab.find_element_by_xpath('.//span[@class="sync-status" and not(text())]') with session.begin(): session.refresh(self.system) self.assertEquals(len(self.system.activity), 1, 'Expecting only one activity row for power_type but found: %r' % self.system.activity) self.assertEquals(self.system.activity[0].field_name, u'power_type')
def test_activity_is_not_logged_when_leaving_power_settings_empty(self): # The bug was that we were recording a change to power_user or # power_passwd because it changed from NULL to ''. with session.begin(): self.system.power.power_type = PowerType.lazy_create(name=u'ilo') self.system.power.power_user = None self.system.power.power_passwd = None self.system.power.power_id = None PowerType.lazy_create(name=u'drac') self.assertEquals(len(self.system.activity), 0) b = self.browser login(b) self.go_to_system_view(tab='Power Settings') tab = b.find_element_by_id('power-settings') # change power type but leave the other fields empty BootstrapSelect(tab.find_element_by_name('power_type'))\ .select_by_visible_text('drac') tab.find_element_by_tag_name('form').submit() tab.find_element_by_xpath('.//button[text()="Save Changes"]') with session.begin(): session.refresh(self.system) self.assertEquals( len(self.system.activity), 1, 'Expecting only one activity row for power_type but found: %r' % self.system.activity) self.assertEquals(self.system.activity[0].field_name, u'power_type')
def test_successfully_deleted(self): response = self.s.delete(get_server_base() + 'powertypes/%s' % self.powertype.id) response.raise_for_status() with session.begin(): session.expire_all() with self.assertRaises(NoResultFound): PowerType.by_name(self.powertype_name)
def by_name(self, input, *args, **kw): if 'anywhere' in kw: search = PowerType.list_by_name(input, find_anywhere=True) else: search = PowerType.list_by_name(input) powers = [elem.name for elem in search] return dict(matches=powers)
def by_name(self,input,*args,**kw): if 'anywhere' in kw: search = PowerType.list_by_name(input,find_anywhere=True) else: search = PowerType.list_by_name(input) powers = [elem.name for elem in search] return dict(matches=powers)
def save(self, **kw): if kw['id']: edit = PowerType.by_id(kw['id']) edit.name = kw['name'] elif kw.get('name'): new = PowerType(name=kw['name']) session.add(new) else: flash(_(u"Invalid Power Type entry")) redirect(".") flash(_(u"OK")) redirect(".")
def test_power_commands_are_not_run_twice(self): # We will make the dummy power script sleep for this long: power_sleep = 4 # To reproduce this bug, we need to queue up three commands for the # same system (so they are run in sequence by beaker-provision), where # the commands take enough time that the second one will still be # running on the next iteration of the polling loop. The third command # will be run twice. assert power_sleep < get_conf().get('SLEEP_TIME') assert 2 * power_sleep > get_conf().get('SLEEP_TIME') with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc()) system.power.power_type = PowerType.lazy_create(name=u'dummy') system.power.power_id = power_sleep # make power script sleep system.action_power(action=u'off', service=u'testdata') system.action_power(action=u'off', service=u'testdata') system.action_power(action=u'off', service=u'testdata') wait_for_commands_to_finish(system, timeout=5 * power_sleep) with session.begin(): session.expire_all() self.assertEquals(system.command_queue[0].status, CommandStatus.completed) self.assertEquals(system.command_queue[1].status, CommandStatus.completed) self.assertEquals(system.command_queue[2].status, CommandStatus.completed) # The bug manifests as two "Completed" records for the power # command which ran twice self.assertEquals(system.dyn_activity .filter_by(field_name=u'Power', new_value=u'Completed') .count(), 3)
def test_power_quiescent_period_statefulness_not_elapsed(self): if daemons_running_externally(): raise SkipTest('cannot examine logs of remote beaker-provision') provision_process, = [p for p in processes if p.name == \ 'beaker-provision'] # Initial lookup of this system will reveal no state, so will delay # for the whole quiescent period try: provision_process.start_output_capture() with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc()) system.power.power_type = PowerType.lazy_create(name=u'dummy') system.power.power_quiescent_period = 1 system.power.power_id = u'' # make power script not sleep system.power.delay_until = None system.action_power(action=u'off', service=u'testdata') wait_for_commands_to_finish(system, timeout=10) finally: provision_output = provision_process.finish_output_capture() self.assertIn('Entering quiescent period, delaying 1 seconds for ' 'command %s' % system.command_queue[0].id, provision_output) # Increase the quiescent period, to ensure we enter it try: provision_process.start_output_capture() with session.begin(): system = System.by_id(system.id, User.by_user_name('admin')) system.power.power_quiescent_period = 10 system.action_power(action=u'on', service=u'testdata') wait_for_commands_to_finish(system, timeout=15) finally: provision_output = provision_process.finish_output_capture() self.assertIn('Entering quiescent period', provision_output)
def test_creating_a_system_with_power_settings(self): s = requests.Session() s.post(get_server_base() + 'login', data={'user_name': self.user.user_name, 'password': u'password'}).raise_for_status() fqdn = data_setup.unique_name(u'newsystem%s') data = { 'fqdn': fqdn, 'lab_controller_id': self.lc.id, 'power_type': u'apc_snmp_then_etherwake', 'power_address': u'dummyaddress', 'power_user': u'dummyuser', 'power_password': u'dummypassword', 'power_id': u'dummyvm', 'power_quiescent_period': 5, 'release_action': u'LeaveOn', 'reprovision_distro_tree': {'id': self.distro_tree.id}, } response = post_json(get_server_base() + 'systems/', session=s, data=data) with session.begin(): system = System.by_fqdn(fqdn, self.user) self.assertEquals(system.power.power_type, PowerType.by_name(u'apc_snmp_then_etherwake')) self.assertEquals(system.power.power_address, u'dummyaddress') self.assertEquals(system.power.power_user, u'dummyuser') self.assertEquals(system.power.power_passwd, u'dummypassword') self.assertEquals(system.power.power_id, u'dummyvm') self.assertEquals(system.power.power_quiescent_period, 5) self.assertEquals(system.release_action, ReleaseAction.leave_on) self.assertEquals(system.reprovision_distro_tree, self.distro_tree)
def delete_powertype(id): """ Deletes a power type by the given id. :param id: The id of the power type to be deleted. :status 204: Power type successfully deleted. :status 400: Power type is referenced by systems. :status 404: Power type can not be found. """ try: powertype = PowerType.by_id(id) except NoResultFound: raise NotFound404('Power type: %s does not exist' % id) systems_referenced = System.query.join( System.power).filter(Power.power_type == powertype).count() if systems_referenced: raise BadRequest400('Power type %s still referenced by %i systems' % (powertype.name, systems_referenced)) session.delete(powertype) activity = Activity(identity.current.user, u'HTTP', u'Deleted', u'PowerType', powertype.name) session.add(activity) return '', 204
def delete_powertype(id): """ Deletes a power type by the given id. :param id: The id of the power type to be deleted. :status 204: Power type successfully deleted. :status 400: Power type is referenced by systems. :status 404: Power type can not be found. """ try: powertype = PowerType.by_id(id) except NoResultFound: raise NotFound404('Power type: %s does not exist' % id) systems_referenced = System.query.join(System.power).filter( Power.power_type == powertype).count() if systems_referenced: raise BadRequest400('Power type %s still referenced by %i systems' % ( powertype.name, systems_referenced)) session.delete(powertype) activity = Activity(identity.current.user, u'HTTP', u'Deleted', u'PowerType', powertype.name) session.add(activity) return '', 204
def test_power_passwords_are_not_logged(self): if daemons_running_externally(): raise SkipTest('cannot examine logs of remote beaker-provision') provision_process, = [ p for p in processes if p.name == 'beaker-provision' ] try: provision_process.start_output_capture() with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc()) self.addCleanup(self.cleanup_system, system) system.power.power_type = PowerType.lazy_create(name=u'dummy') system.power.power_id = u'' # make power script not sleep system.power.power_passwd = u'dontleakmebro' system.action_power(action=u'off', service=u'testdata') wait_for_commands_to_finish(system, timeout=2 * get_conf().get('SLEEP_TIME')) finally: provision_output = provision_process.finish_output_capture() self.assert_('Handling command' in provision_output, provision_output) self.assert_('Launching power script' in provision_output, provision_output) self.assert_(system.power.power_passwd not in provision_output, provision_output)
def test_quiescent_period_only_applies_between_power_commands(self): # The purpose of the quiescent period is for power supplies with # peculiar characteristics that need time to discharge or similar. # But the quiescent period should not count any other commands like # clear_logs or configure_netboot, because those are not touching the # power supply. loop_interval = get_conf().get('SLEEP_TIME') quiescent_period = loop_interval * 3.0 with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc()) self.addCleanup(self.cleanup_system, system) system.power.power_type = PowerType.lazy_create(name=u'dummy') system.power.power_quiescent_period = quiescent_period system.power.power_id = u'' # make power script not sleep system.action_power(action=u'off', service=u'testdata') system.enqueue_command(action=u'clear_netboot', service=u'testdata') commands = system.command_queue[:2] assert_command_is_delayed(commands[1], quiescent_period - 0.5, timeout=2 * loop_interval) wait_for_command_to_finish(commands[0], timeout=2 * loop_interval) time.sleep(quiescent_period) # Now there should be no delays because the quiescent period has # already elapsed since the 'off' command above. with session.begin(): system.enqueue_command(action=u'clear_logs', service=u'testdata') system.action_power(action=u'on', service=u'testdata') commands = system.command_queue[:2] wait_for_command_to_finish(commands[1], timeout=2 * loop_interval) wait_for_command_to_finish(commands[0], timeout=2 * loop_interval)
def test_power_quiescent_period(self): # Test that we do in fact wait for the quiescent period to pass # before running a command if daemons_running_externally(): raise SkipTest('cannot examine logs of remote beaker-provision') provision_process, = [p for p in processes if p.name == \ 'beaker-provision'] # These times are needed to guarantee that we are actually waiting for # the quiescent period and not waiting for another poll loop quiescent_period = get_conf().get('SLEEP_TIME') * 3 timeout = get_conf().get('SLEEP_TIME') * 2 try: provision_process.start_output_capture() with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc()) system.power.power_type = PowerType.lazy_create(name=u'dummy') system.power.power_quiescent_period = quiescent_period system.power.power_id = u'' # make power script not sleep system.power.delay_until = None system.action_power(action=u'off', service=u'testdata') wait_for_commands_completed(system, timeout=timeout) self.fail('The quiescent period is not being respected') except AssertionError: # wait_for_commands() should timeout if the quiescent period is #respected pass finally: provision_output = provision_process.finish_output_capture() # The initial command seen for a system will always wait for the full # quiescent period self.assertIn('Entering quiescent period, delaying %s seconds for ' 'command %s' % (quiescent_period, system.command_queue[0].id), provision_output)
def test_quiescent_period_only_applies_between_power_commands(self): # The purpose of the quiescent period is for power supplies with # peculiar characteristics that need time to discharge or similar. # But the quiescent period should not count any other commands like # clear_logs or configure_netboot, because those are not touching the # power supply. quiescent_period = get_conf().get('SLEEP_TIME') * 2.0 with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc()) system.power.power_type = PowerType.lazy_create(name=u'dummy') system.power.power_quiescent_period = quiescent_period system.power.power_id = u'' # make power script not sleep system.action_power(action=u'off', service=u'testdata') system.enqueue_command(action=u'clear_netboot', service=u'testdata') commands = system.command_queue[:2] assert_command_is_delayed(commands[1], quiescent_period - 0.5, timeout=quiescent_period / 2) wait_for_command_to_finish(commands[0], timeout=quiescent_period / 2) time.sleep(quiescent_period) # Now there should be no delays because the quiescent period has # already elapsed since the 'off' command above. with session.begin(): system.enqueue_command(action=u'clear_logs', service=u'testdata') system.action_power(action=u'on', service=u'testdata') commands = system.command_queue[:2] wait_for_command_to_finish(commands[1], timeout=quiescent_period / 2) wait_for_command_to_finish(commands[0], timeout=quiescent_period / 2)
def setUp(self): self.powertype_name = unique_name('beerpowered%s') with session.begin(): self.powertype = PowerType(name=self.powertype_name) session.add(self.powertype) self.s = requests.Session() login(self.s)
def create_powertype(): """ Creates a new power type. The request must be :mimetype:`application/json`. :jsonparam string name: Name for the power type. :status 201: The power type was successfully created. """ data = read_json_request(request) with convert_internal_errors(): if PowerType.query.filter_by(**data).count(): raise Conflict409('Power type %s already exists' % data['name']) powertype = PowerType(**data) activity = Activity(identity.current.user, u'HTTP', u'Created', u'PowerType', powertype.name) session.add_all([powertype, activity]) response = jsonify(powertype.__json__()) response.status_code = 201 return response
def test_change_power_type(self): with session.begin(): system = data_setup.create_system(hypervisor=None) # set to 'apc_snmp_then_etherwake' run_client([ 'bkr', 'system-modify', '--power-type=apc_snmp_then_etherwake', system.fqdn ]) with session.begin(): session.refresh(system) self.assertEquals(system.power.power_type, PowerType.by_name(u'apc_snmp_then_etherwake')) # set back to ilo run_client(['bkr', 'system-modify', '--power-type=ilo', system.fqdn]) with session.begin(): session.refresh(system) self.assertEquals(system.power.power_type, PowerType.by_name(u'ilo'))
def save(self, **kw): if kw['id']: edit = PowerType.by_id(kw['id']) edit.name = kw['name'] elif kw.get('name'): new = PowerType(name=kw['name']) else: flash(_(u"Invalid Power Type entry")) redirect(".") flash( _(u"OK") ) redirect(".")
def configure_system_power(system, power_type=u'ilo', address=None, user=None, password=None, power_id=None): if address is None: address = u'%s_power_address' % system.fqdn if user is None: user = u'%s_power_user' % system.fqdn if password is None: password = u'%s_power_password' % system.fqdn if power_id is None: power_id = unique_name(u'%s') system.power = Power(power_type=PowerType.by_name(power_type), power_address=address, power_id=power_id, power_user=user, power_passwd=password)
def test_quiescent_period_is_obeyed_for_consecutive_commands(self): quiescent_period = 3 with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc()) system.power.power_type = PowerType.lazy_create(name=u'dummy') system.power.power_quiescent_period = quiescent_period system.power.power_id = u'' # make power script not sleep system.power.delay_until = None system.action_power(action=u'on', service=u'testdata') system.action_power(action=u'on', service=u'testdata') system.action_power(action=u'on', service=u'testdata') commands = system.command_queue[:3] assert_command_is_delayed(commands[2], quiescent_period - 0.5, 10) assert_command_is_delayed(commands[1], quiescent_period - 0.5, 10) assert_command_is_delayed(commands[0], quiescent_period - 0.5, 10)
def test_power_quiescent_period(self): # Test that we do in fact wait for the quiescent period to pass # before running a command. # This time is needed to guarantee that we are actually waiting for # the quiescent period and not waiting for another poll loop: quiescent_period = get_conf().get('SLEEP_TIME') * 3 with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc()) system.power.power_type = PowerType.lazy_create(name=u'dummy') system.power.power_quiescent_period = quiescent_period system.power.power_id = u'' # make power script not sleep system.power.delay_until = None system.action_power(action=u'off', service=u'testdata') command = system.command_queue[0] assert_command_is_delayed(command, quiescent_period - 0.5, 10)
def edit(self,**kw): values = [] if kw.get('id'): powertype = PowerType.by_id(kw['id']) values = dict( id = powertype.id, name = powertype.name, ) return dict( form = self.form, action = './save', options = {}, value = values, )
def test_create_new_powertype_successfully(self): with session.begin(): activity_count = Activity.query.count() login(self.s, self.admin_user, self.admin_password) expected_name = 'beerpower' response = post_json(get_server_base() + 'powertypes/', session=self.s, data=dict(name=expected_name)) self.assertEqual(201, response.status_code) self.assertEqual(expected_name, response.json()['name']) with session.begin(): powertype = PowerType.by_name(expected_name) self.assertEqual(expected_name, powertype.name) self.assertEqual(activity_count + 1, Activity.query.count())
def test_power_passwords_are_not_reported_in_failure_message(self): with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc()) self.addCleanup(self.cleanup_system, system) system.power.power_type = PowerType.lazy_create( name=u'testing-bz1358063') system.power.power_passwd = u'dontleakmebro' system.power.quiescent_period = 0 system.action_power(action=u'off', service=u'testdata') timeout = (2 * get_conf().get('SLEEP_TIME') + get_conf().get('POWER_ATTEMPTS') * 2**get_conf().get('POWER_ATTEMPTS')) wait_for_commands_to_finish(system, timeout=timeout) self.assertEqual(system.command_queue[0].status, CommandStatus.failed) self.assertIn( u'failed after 2 attempts with exit status 1:\npassword is ********', system.command_queue[0].error_message)
def _from_csv(cls, system, data, csv_type, log): """ Import data from CSV file into Power Objects """ csv_object = getattr(system, csv_type, None) if not csv_object: csv_object = Power() system.power = csv_object for key in data.keys(): if key in cls.reg_keys: if data[key]: newdata = smart_bool(data[key]) else: newdata = None current_data = getattr(csv_object, key, None) if unicode(newdata) != unicode(current_data): system.record_activity(user=identity.current.user, service=u'CSV', action=u'Changed', field=key, old=u'***', new=u'***') setattr(csv_object, key, newdata) # import power_type if 'power_type' in data: if not data['power_type']: log.append("%s: Invalid power_type None" % system.fqdn) return False try: power_type = PowerType.by_name(data['power_type']) except InvalidRequestError: log.append("%s: Invalid Power Type %s" % (system.fqdn, data['power_type'])) return False if csv_object.power_type != power_type: system.record_activity(user=identity.current.user, service=u'CSV', action=u'Changed', field=u'power_type', old=u'%s' % csv_object.power_type, new=u'%s' % power_type) csv_object.power_type = power_type return True
def edit(self, **kw): title = _(u'New Power Type') values = [] if kw.get('id'): powertype = PowerType.by_id(kw['id']) title = powertype.name values = dict( id=powertype.id, name=powertype.name, ) return dict( form=self.form, title=title, action='./save', options={}, value=values, )
def test_power_passwords_are_not_logged(self): if daemons_running_externally(): raise SkipTest('cannot examine logs of remote beaker-provision') provision_process, = [p for p in processes if p.name == 'beaker-provision'] try: provision_process.start_output_capture() with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc()) system.power.power_type = PowerType.lazy_create(name=u'dummy') system.power.power_id = u'' # make power script not sleep system.power.power_passwd = u'dontleakmebro' system.action_power(action=u'off', service=u'testdata') wait_for_commands_to_finish(system, timeout=2 * get_conf().get('SLEEP_TIME')) finally: provision_output = provision_process.finish_output_capture() self.assert_('Handling command' in provision_output, provision_output) self.assert_('Launching power script' in provision_output, provision_output) self.assert_(system.power.power_passwd not in provision_output, provision_output)
def test_blank_power_passwords(self): if daemons_running_externally(): raise SkipTest('cannot examine logs of remote beaker-provision') provision_process, = [p for p in processes if p.name == 'beaker-provision'] try: provision_process.start_output_capture() with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc()) system.power.address = None system.power.power_type = PowerType.lazy_create(name=u'dummy') system.power.power_id = u'' # make power script not sleep system.power.power_passwd = None system.action_power(action=u'off', service=u'testdata') wait_for_commands_to_finish(system, timeout=2 * get_conf().get('SLEEP_TIME')) finally: provision_output = provision_process.finish_output_capture() # The None type is passed in from the db. Later in the code it is converted # to the empty string, as it should be. self.assertIn("'passwd': None", provision_output, provision_output)
def test_create_system_set_power_settings(self): fqdn = data_setup.unique_name(u'mysystem%s') distro_tree = data_setup.create_distro_tree() run_client([ 'bkr', 'system-create', '--power-type', u'apc_snmp_then_etherwake', '--power-address', u'dummyaddress', '--power-user', u'dummyuser', '--power-password', u'dummypassword', '--power-id', u'dummyvm', '--power-quiescent-period', u'5', '--release-action', u'LeaveOn', '--reprovision-distro-tree', str(distro_tree.id), fqdn ]) with session.begin(): system = System.by_fqdn(fqdn, User.by_user_name(u'admin')) self.assertEquals(system.power.power_type, PowerType.by_name(u'apc_snmp_then_etherwake')) self.assertEquals(system.power.power_address, u'dummyaddress') self.assertEquals(system.power.power_user, u'dummyuser') self.assertEquals(system.power.power_passwd, u'dummypassword') self.assertEquals(system.power.power_id, u'dummyvm') self.assertEquals(system.power.power_quiescent_period, 5) self.assertEquals(system.release_action, ReleaseAction.leave_on) self.assertEquals(system.reprovision_distro_tree, distro_tree)
def test_deletes_power_type_successfully(self): powertype_name = unique_name('beerpowered%s') with session.begin(): pt = PowerType(name=powertype_name) session.add(pt) activity_count = Activity.query.count() b = self.browser b.get(get_server_base() + 'powertypes/') b.find_element_by_xpath('//li[contains(., "%s")]/button' % pt.name).click() b.find_element_by_xpath( '//ul[contains(@class, "power-types-list") and ' 'not(./li[contains(., "%s")])]' % pt.name) with session.begin(): session.expire_all() self.assertEqual( 0, session.query(PowerType).filter_by( name=powertype_name).count()) self.assertEqual(activity_count + 1, Activity.query.count())
def _from_csv(cls,system,data,csv_type,log): """ Import data from CSV file into Power Objects """ csv_object = getattr(system, csv_type, None) if not csv_object: csv_object = Power() system.power = csv_object for key in data.keys(): if key in cls.reg_keys: if data[key]: newdata = smart_bool(data[key]) else: newdata = None current_data = getattr(csv_object, key, None) if unicode(newdata) != unicode(current_data): system.record_activity(user=identity.current.user, service=u'CSV', action=u'Changed', field=key, old=u'***', new=u'***') setattr(csv_object,key,newdata) # import power_type if 'power_type' in data: if not data['power_type']: log.append("%s: Invalid power_type None" % system.fqdn) return False try: power_type = PowerType.by_name(data['power_type']) except InvalidRequestError: log.append("%s: Invalid Power Type %s" % (system.fqdn, data['power_type'])) return False if csv_object.power_type != power_type: system.record_activity(user=identity.current.user, service=u'CSV', action=u'Changed', field=u'power_type', old=u'%s' % csv_object.power_type, new=u'%s' % power_type) csv_object.power_type = power_type return True
def test_create_system_set_power_settings(self): fqdn = data_setup.unique_name(u'mysystem%s') distro_tree = data_setup.create_distro_tree() run_client(['bkr', 'system-create', '--power-type', u'apc_snmp_then_etherwake', '--power-address', u'dummyaddress', '--power-user', u'dummyuser', '--power-password', u'dummypassword', '--power-id', u'dummyvm', '--power-quiescent-period', u'5', '--release-action', u'LeaveOn', '--reprovision-distro-tree', str(distro_tree.id), fqdn]) with session.begin(): system = System.by_fqdn(fqdn, User.by_user_name(u'admin')) self.assertEquals(system.power.power_type, PowerType.by_name(u'apc_snmp_then_etherwake')) self.assertEquals(system.power.power_address, u'dummyaddress') self.assertEquals(system.power.power_user, u'dummyuser') self.assertEquals(system.power.power_passwd, u'dummypassword') self.assertEquals(system.power.power_id, u'dummyvm') self.assertEquals(system.power.power_quiescent_period, 5) self.assertEquals(system.release_action, ReleaseAction.leave_on) self.assertEquals(system.reprovision_distro_tree, distro_tree)
def test_creating_a_system_with_power_settings(self): s = requests.Session() s.post(get_server_base() + 'login', data={ 'user_name': self.user.user_name, 'password': u'password' }).raise_for_status() fqdn = data_setup.unique_name(u'newsystem%s') data = { 'fqdn': fqdn, 'lab_controller_id': self.lc.id, 'power_type': u'apc_snmp_then_etherwake', 'power_address': u'dummyaddress', 'power_user': u'dummyuser', 'power_password': u'dummypassword', 'power_id': u'dummyvm', 'power_quiescent_period': 5, 'release_action': u'LeaveOn', 'reprovision_distro_tree': { 'id': self.distro_tree.id }, } response = post_json(get_server_base() + 'systems/', session=s, data=data) with session.begin(): system = System.by_fqdn(fqdn, self.user) self.assertEquals(system.power.power_type, PowerType.by_name(u'apc_snmp_then_etherwake')) self.assertEquals(system.power.power_address, u'dummyaddress') self.assertEquals(system.power.power_user, u'dummyuser') self.assertEquals(system.power.power_passwd, u'dummypassword') self.assertEquals(system.power.power_id, u'dummyvm') self.assertEquals(system.power.power_quiescent_period, 5) self.assertEquals(system.release_action, ReleaseAction.leave_on) self.assertEquals(system.reprovision_distro_tree, self.distro_tree)
def remove(self, **kw): remove = PowerType.by_id(kw['id']) session.delete(remove) flash(_(u"%s Deleted") % remove.name) raise redirect(".")
def populate_db(user_name=None, password=None, user_display_name=None, user_email_address=None): logger.info('Populating tables with pre-defined values if necessary') session.begin() try: admin = Group.by_name(u'admin') except InvalidRequestError: admin = Group(group_name=u'admin', display_name=u'Admin') session.add(admin) try: lab_controller = Group.by_name(u'lab_controller') except InvalidRequestError: lab_controller = Group(group_name=u'lab_controller', display_name=u'Lab Controller') session.add(lab_controller) # Setup User account if user_name: user = User.lazy_create(user_name=user_name.decode('utf8')) if password: user.password = password.decode('utf8') if user_display_name: user.display_name = user_display_name.decode('utf8') if user_email_address: user.email_address = user_email_address.decode('utf8') # Ensure the user is in the 'admin' group as an owner. # Flush for lazy_create. session.flush() user_group_assoc = UserGroup.lazy_create( user_id=user.user_id, group_id=admin.group_id) user_group_assoc.is_owner = True # Create distro_expire perm if not present try: _ = Permission.by_name(u'distro_expire') except NoResultFound: distro_expire_perm = Permission(u'distro_expire') session.add(distro_expire_perm) # Create proxy_auth perm if not present try: _ = Permission.by_name(u'proxy_auth') except NoResultFound: proxy_auth_perm = Permission(u'proxy_auth') session.add(proxy_auth_perm) # Create tag_distro perm if not present try: _ = Permission.by_name(u'tag_distro') except NoResultFound: tag_distro_perm = Permission(u'tag_distro') admin.permissions.append(tag_distro_perm) # Create stop_task perm if not present try: _ = Permission.by_name(u'stop_task') except NoResultFound: stop_task_perm = Permission(u'stop_task') lab_controller.permissions.append(stop_task_perm) admin.permissions.append(stop_task_perm) # Create secret_visible perm if not present try: _ = Permission.by_name(u'secret_visible') except NoResultFound: secret_visible_perm = Permission(u'secret_visible') lab_controller.permissions.append(secret_visible_perm) admin.permissions.append(secret_visible_perm) # Create change_prio perm if not present try: _ = Permission.by_name(u'change_prio') except NoResultFound: change_prio_perm = Permission(u'change_prio') session.add(change_prio_perm) # Setup Hypervisors Table if Hypervisor.query.count() == 0: for h in [u'KVM', u'Xen', u'HyperV', u'VMWare']: session.add(Hypervisor(hypervisor=h)) # Setup kernel_type Table if KernelType.query.count() == 0: for type in [u'default', u'highbank', u'imx', u'omap', u'tegra']: session.add(KernelType(kernel_type=type, uboot=False)) for type in [u'mvebu']: session.add(KernelType(kernel_type=type, uboot=True)) # Setup base Architectures if Arch.query.count() == 0: for arch in [u'i386', u'x86_64', u'ia64', u'ppc', u'ppc64', u'ppc64le', u's390', u's390x', u'armhfp', u'aarch64', u'arm']: session.add(Arch(arch)) # Setup base power types if PowerType.query.count() == 0: for power_type in [u'apc_snmp', u'apc_snmp_then_etherwake', u'bladecenter', u'bladepap', u'drac', u'ether_wake', u'hyper-v', u'ilo', u'integrity', u'ipmilan', u'ipmitool', u'lpar', u'rsa', u'virsh', u'wti']: session.add(PowerType(power_type)) # Setup key types if Key.query.count() == 0: session.add(Key(u'DISKSPACE', True)) session.add(Key(u'COMMENT')) session.add(Key(u'CPUFAMILY', True)) session.add(Key(u'CPUFLAGS')) session.add(Key(u'CPUMODEL')) session.add(Key(u'CPUMODELNUMBER', True)) session.add(Key(u'CPUSPEED', True)) session.add(Key(u'CPUVENDOR')) session.add(Key(u'DISK', True)) session.add(Key(u'FORMFACTOR')) session.add(Key(u'HVM')) session.add(Key(u'MEMORY', True)) session.add(Key(u'MODEL')) session.add(Key(u'MODULE')) session.add(Key(u'NETWORK')) session.add(Key(u'NR_DISKS', True)) session.add(Key(u'NR_ETH', True)) session.add(Key(u'NR_IB', True)) session.add(Key(u'PCIID')) session.add(Key(u'PROCESSORS', True)) session.add(Key(u'RTCERT')) session.add(Key(u'SCRATCH')) session.add(Key(u'STORAGE')) session.add(Key(u'USBID')) session.add(Key(u'VENDOR')) session.add(Key(u'XENCERT')) session.add(Key(u'NETBOOT_METHOD')) if RetentionTag.query.count() == 0: session.add(RetentionTag(tag=u'scratch', is_default=1, expire_in_days=30)) session.add(RetentionTag(tag=u'60days', needs_product=False, expire_in_days=60)) session.add(RetentionTag(tag=u'120days', needs_product=False, expire_in_days=120)) session.add(RetentionTag(tag=u'active', needs_product=True)) session.add(RetentionTag(tag=u'audit', needs_product=True)) config_items = [ # name, description, numeric (u'root_password', u'Plaintext root password for provisioned systems', False), (u'root_password_validity', u"Maximum number of days a user's root password is valid for", True), (u'guest_name_prefix', u'Prefix for names of dynamic guests in OpenStack', False), (u'guest_private_network', u'Network address in CIDR format for private networks' ' of dynamic guests in OpenStack.', False), ] for name, description, numeric in config_items: ConfigItem.lazy_create(name=name, description=description, numeric=numeric) if ConfigItem.by_name(u'root_password').current_value() is None: ConfigItem.by_name(u'root_password').set(u'beaker', user=admin.users[0]) if ConfigItem.by_name(u'guest_private_network').current_value() is None: ConfigItem.by_name(u'guest_private_network').set(u'192.168.10.0/24', user=admin.users[0]) session.commit() session.close() logger.info('Pre-defined values populated')
def update_system(fqdn): system = _get_system_by_FQDN(fqdn) if not system.can_edit(identity.current.user): raise Forbidden403('Cannot edit system') data = read_json_request(request) # helper for recording activity below def record_activity(field, old, new, action=u'Changed'): system.record_activity(user=identity.current.user, service=u'HTTP', action=action, field=field, old=old, new=new) with convert_internal_errors(): # XXX what a nightmare... need to use a validation/conversion library, # and maybe simplify/relocate the activity recording stuff somehow changed = False renamed = False if 'fqdn' in data: new_fqdn = data['fqdn'].lower() if new_fqdn != system.fqdn: if System.query.filter(System.fqdn == new_fqdn).count(): raise Conflict409('System %s already exists' % new_fqdn) record_activity(u'FQDN', system.fqdn, new_fqdn) system.fqdn = new_fqdn changed = True renamed = True if 'owner' in data and data['owner'].get('user_name') != system.owner.user_name: if not system.can_change_owner(identity.current.user): raise Forbidden403('Cannot change owner') new_owner = User.by_user_name(data['owner'].get('user_name')) if new_owner is None: raise BadRequest400('No such user %s' % data['owner'].get('user_name')) record_activity(u'Owner', system.owner, new_owner) system.owner = new_owner changed = True if 'status' in data: new_status = SystemStatus.from_string(data['status']) if new_status != system.status: record_activity(u'Status', system.status, new_status) system.status = new_status if not new_status.bad and system.status_reason: # clear the status reason for "good" statuses record_activity(u'Status Reason', system.status_reason, None) system.status_reason = None changed = True if 'status_reason' in data: new_reason = data['status_reason'] or None if new_reason and not system.status.bad: raise ValueError('Cannot set status reason when status is %s' % system.status) if new_reason != system.status_reason: record_activity(u'Status Reason', system.status_reason, new_reason) system.status_reason = new_reason changed = True if 'type' in data: new_type = SystemType.from_string(data['type']) if new_type != system.type: record_activity(u'Type', system.type, new_type) system.type = new_type changed = True if 'arches' in data: new_arches = [Arch.by_name(a) for a in (data['arches'] or [])] added_arches = set(new_arches).difference(system.arch) removed_arches = set(system.arch).difference(new_arches) if added_arches or removed_arches: for added_arch in added_arches: record_activity(u'Arch', None, added_arch, u'Added') for removed_arch in removed_arches: record_activity(u'Arch', removed_arch, None, u'Removed') system.arch[:] = new_arches changed = True if 'lab_controller_id' in data: if data['lab_controller_id']: new_lc = LabController.by_id(data['lab_controller_id']) else: new_lc = None if new_lc != system.lab_controller: if system.open_reservation is not None: raise Conflict409('Unable to change lab controller while system ' 'is in use (return the system first)') record_activity(u'Lab Controller', system.lab_controller, new_lc) system.lab_controller = new_lc changed = True # If we're given any power-related keys, need to ensure system.power exists if not system.power and set(['power_type', 'power_address', 'power_user', 'power_password', 'power_id', 'power_quiescent_period'])\ .intersection(data.keys()): system.power = Power() if 'power_type' in data: new_power_type = PowerType.by_name(data['power_type']) if new_power_type != system.power.power_type: if not system.power.power_type: old_power_type = '' else: old_power_type = system.power.power_type.name record_activity(u'power_type', old_power_type, new_power_type.name) system.power.power_type = new_power_type changed = True if 'power_address' in data: new_power_address = data['power_address'] if not new_power_address: raise ValueError('Power address is required') if new_power_address != system.power.power_address: record_activity(u'power_address', system.power.power_address, data['power_address']) system.power.power_address = new_power_address changed = True if 'power_user' in data: new_power_user = data['power_user'] or u'' if new_power_user != (system.power.power_user or u''): record_activity(u'power_user', u'********', u'********') system.power.power_user = new_power_user changed = True if 'power_password' in data: new_power_password = data['power_password'] or u'' if new_power_password != (system.power.power_passwd or u''): record_activity(u'power_passwd', u'********', u'********') system.power.power_passwd = new_power_password changed = True if 'power_id' in data: new_power_id = data['power_id'] or u'' if new_power_id != (system.power.power_id or u''): record_activity(u'power_id', system.power.power_id, new_power_id) system.power.power_id = new_power_id changed = True if 'power_quiescent_period' in data: new_qp = int(data['power_quiescent_period']) if new_qp != system.power.power_quiescent_period: record_activity(u'power_quiescent_period', system.power.power_quiescent_period, new_qp) system.power.power_quiescent_period = new_qp changed = True if 'release_action' in data: new_release_action = ReleaseAction.from_string(data['release_action']) if new_release_action != (system.release_action or ReleaseAction.power_off): record_activity(u'release_action', (system.release_action or ReleaseAction.power_off), new_release_action) system.release_action = new_release_action changed = True if 'reprovision_distro_tree' in data: if (not data['reprovision_distro_tree'] or 'id' not in data['reprovision_distro_tree']): new_rpdt = None else: new_rpdt = DistroTree.by_id(data['reprovision_distro_tree']['id']) if new_rpdt != system.reprovision_distro_tree: record_activity(u'reprovision_distro_tree', unicode(system.reprovision_distro_tree), unicode(new_rpdt)) system.reprovision_distro_tree = new_rpdt changed = True if 'location' in data: new_location = data['location'] or None if new_location != system.location: record_activity(u'Location', system.location, new_location) system.location = new_location changed = True if 'lender' in data: new_lender = data['lender'] or None if new_lender != system.lender: record_activity(u'Lender', system.lender, new_lender) system.lender = new_lender changed = True if 'kernel_type' in data: new_kernel_type = KernelType.by_name(data['kernel_type']) if new_kernel_type != system.kernel_type: record_activity(u'Kernel Type', system.kernel_type, new_kernel_type) system.kernel_type = new_kernel_type changed = True if 'hypervisor' in data: if data['hypervisor']: new_hypervisor = Hypervisor.by_name(data['hypervisor']) else: new_hypervisor = None if new_hypervisor != system.hypervisor: record_activity(u'Hypervisor', system.hypervisor, new_hypervisor) system.hypervisor = new_hypervisor changed = True if 'vendor' in data: new_vendor = data['vendor'] or None if new_vendor != system.vendor: record_activity(u'Vendor', system.vendor, new_vendor) system.vendor = new_vendor changed = True if 'model' in data: new_model = data['model'] or None if new_model != system.model: record_activity(u'Model', system.model, new_model) system.model = new_model changed = True if 'serial_number' in data: new_serial_number = data['serial_number'] or None if new_serial_number != system.serial: record_activity(u'Serial Number', system.serial, new_serial_number) system.serial = new_serial_number changed = True if 'mac_address' in data: new_mac_address = data['mac_address'] or None if new_mac_address != system.mac_address: record_activity(u'MAC Address', system.mac_address, new_mac_address) system.mac_address = new_mac_address changed = True if 'memory' in data: new_memory = int(data['memory']) if data['memory'] else None if new_memory != system.memory: record_activity(u'Memory', system.memory, new_memory) system.memory = new_memory changed = True if 'numa_nodes' in data: new_numa_nodes = int(data['numa_nodes']) if data['numa_nodes'] else None if not system.numa: system.numa = Numa() if new_numa_nodes != system.numa.nodes: record_activity(u'NUMA/Nodes', system.numa.nodes, new_numa_nodes) system.numa.nodes = new_numa_nodes changed = True if changed: # XXX clear checksum!? system.date_modified = datetime.datetime.utcnow() response = jsonify(system.__json__()) if renamed: response.headers.add('Location', url('/view/%s' % system.fqdn)) return response
def update_system(fqdn): system = _get_system_by_FQDN(fqdn) if not system.can_edit(identity.current.user): raise Forbidden403('Cannot edit system') data = read_json_request(request) # helper for recording activity below def record_activity(field, old, new, action=u'Changed'): system.record_activity(user=identity.current.user, service=u'HTTP', action=action, field=field, old=old, new=new) with convert_internal_errors(): # XXX what a nightmare... need to use a validation/conversion library, # and maybe simplify/relocate the activity recording stuff somehow changed = False renamed = False if 'fqdn' in data: new_fqdn = data['fqdn'].lower() if new_fqdn != system.fqdn: if System.query.filter(System.fqdn == new_fqdn).count(): raise Conflict409('System %s already exists' % new_fqdn) record_activity(u'FQDN', system.fqdn, new_fqdn) system.fqdn = new_fqdn changed = True renamed = True if 'owner' in data and data['owner'].get( 'user_name') != system.owner.user_name: if not system.can_change_owner(identity.current.user): raise Forbidden403('Cannot change owner') new_owner = User.by_user_name(data['owner'].get('user_name')) if new_owner is None: raise BadRequest400('No such user %s' % data['owner'].get('user_name')) record_activity(u'Owner', system.owner, new_owner) system.owner = new_owner changed = True if 'status' in data: new_status = SystemStatus.from_string(data['status']) if new_status != system.status: record_activity(u'Status', system.status, new_status) system.status = new_status if not new_status.bad and system.status_reason: # clear the status reason for "good" statuses record_activity(u'Status Reason', system.status_reason, None) system.status_reason = None changed = True if 'status_reason' in data: new_reason = data['status_reason'] or None if new_reason and not system.status.bad: raise ValueError('Cannot set status reason when status is %s' % system.status) if new_reason != system.status_reason: record_activity(u'Status Reason', system.status_reason, new_reason) system.status_reason = new_reason changed = True if 'type' in data: new_type = SystemType.from_string(data['type']) if new_type != system.type: record_activity(u'Type', system.type, new_type) system.type = new_type changed = True if 'arches' in data: new_arches = [Arch.by_name(a) for a in (data['arches'] or [])] added_arches = set(new_arches).difference(system.arch) removed_arches = set(system.arch).difference(new_arches) if added_arches or removed_arches: for added_arch in added_arches: record_activity(u'Arch', None, added_arch, u'Added') for removed_arch in removed_arches: record_activity(u'Arch', removed_arch, None, u'Removed') system.arch[:] = new_arches changed = True if 'lab_controller_id' in data: if data['lab_controller_id']: new_lc = LabController.by_id(data['lab_controller_id']) else: new_lc = None if new_lc != system.lab_controller: if system.open_reservation is not None: raise Conflict409( 'Unable to change lab controller while system ' 'is in use (return the system first)') record_activity(u'Lab Controller', system.lab_controller, new_lc) system.lab_controller = new_lc changed = True # If we're given any power-related keys, need to ensure system.power exists if not system.power and set(['power_type', 'power_address', 'power_user', 'power_password', 'power_id', 'power_quiescent_period'])\ .intersection(data.keys()): system.power = Power() if 'power_type' in data: new_power_type = PowerType.by_name(data['power_type']) if new_power_type != system.power.power_type: if not system.power.power_type: old_power_type = '' else: old_power_type = system.power.power_type.name record_activity(u'power_type', old_power_type, new_power_type.name) system.power.power_type = new_power_type changed = True if 'power_address' in data: new_power_address = data['power_address'] if not new_power_address: raise ValueError('Power address is required') if new_power_address != system.power.power_address: record_activity(u'power_address', system.power.power_address, data['power_address']) system.power.power_address = new_power_address changed = True if 'power_user' in data: new_power_user = data['power_user'] or u'' if new_power_user != (system.power.power_user or u''): record_activity(u'power_user', u'********', u'********') system.power.power_user = new_power_user changed = True if 'power_password' in data: new_power_password = data['power_password'] or u'' if new_power_password != (system.power.power_passwd or u''): record_activity(u'power_passwd', u'********', u'********') system.power.power_passwd = new_power_password changed = True if 'power_id' in data: new_power_id = data['power_id'] or u'' if new_power_id != (system.power.power_id or u''): record_activity(u'power_id', system.power.power_id, new_power_id) system.power.power_id = new_power_id changed = True if 'power_quiescent_period' in data: new_qp = int(data['power_quiescent_period']) if new_qp != system.power.power_quiescent_period: record_activity(u'power_quiescent_period', system.power.power_quiescent_period, new_qp) system.power.power_quiescent_period = new_qp changed = True if 'release_action' in data: new_release_action = ReleaseAction.from_string( data['release_action']) if new_release_action != (system.release_action or ReleaseAction.power_off): record_activity( u'release_action', (system.release_action or ReleaseAction.power_off), new_release_action) system.release_action = new_release_action changed = True if 'reprovision_distro_tree' in data: if (not data['reprovision_distro_tree'] or 'id' not in data['reprovision_distro_tree']): new_rpdt = None else: new_rpdt = DistroTree.by_id( data['reprovision_distro_tree']['id']) if new_rpdt != system.reprovision_distro_tree: record_activity(u'reprovision_distro_tree', unicode(system.reprovision_distro_tree), unicode(new_rpdt)) system.reprovision_distro_tree = new_rpdt changed = True if 'location' in data: new_location = data['location'] or None if new_location != system.location: record_activity(u'Location', system.location, new_location) system.location = new_location changed = True if 'lender' in data: new_lender = data['lender'] or None if new_lender != system.lender: record_activity(u'Lender', system.lender, new_lender) system.lender = new_lender changed = True if 'kernel_type' in data: new_kernel_type = KernelType.by_name(data['kernel_type']) if new_kernel_type != system.kernel_type: record_activity(u'Kernel Type', system.kernel_type, new_kernel_type) system.kernel_type = new_kernel_type changed = True if 'hypervisor' in data: if data['hypervisor']: new_hypervisor = Hypervisor.by_name(data['hypervisor']) else: new_hypervisor = None if new_hypervisor != system.hypervisor: record_activity(u'Hypervisor', system.hypervisor, new_hypervisor) system.hypervisor = new_hypervisor changed = True if 'vendor' in data: new_vendor = data['vendor'] or None if new_vendor != system.vendor: record_activity(u'Vendor', system.vendor, new_vendor) system.vendor = new_vendor changed = True if 'model' in data: new_model = data['model'] or None if new_model != system.model: record_activity(u'Model', system.model, new_model) system.model = new_model changed = True if 'serial_number' in data: new_serial_number = data['serial_number'] or None if new_serial_number != system.serial: record_activity(u'Serial Number', system.serial, new_serial_number) system.serial = new_serial_number changed = True if 'mac_address' in data: new_mac_address = data['mac_address'] or None if new_mac_address != system.mac_address: record_activity(u'MAC Address', system.mac_address, new_mac_address) system.mac_address = new_mac_address changed = True if 'memory' in data: new_memory = int(data['memory']) if data['memory'] else None if new_memory != system.memory: record_activity(u'Memory', system.memory, new_memory) system.memory = new_memory changed = True if 'numa_nodes' in data: new_numa_nodes = int( data['numa_nodes']) if data['numa_nodes'] else None if not system.numa: system.numa = Numa() if new_numa_nodes != system.numa.nodes: record_activity(u'NUMA/Nodes', system.numa.nodes, new_numa_nodes) system.numa.nodes = new_numa_nodes changed = True if changed: # XXX clear checksum!? system.date_modified = datetime.datetime.utcnow() response = jsonify(system.__json__()) if renamed: response.headers.add('Location', url('/view/%s' % system.fqdn)) return response
def remove(self, **kw): remove = PowerType.by_id(kw['id']) session.delete(remove) flash( _(u"%s Deleted") % remove.name ) raise redirect(".")