def set_chamber_slots(max_chamber_slots=None): active_chamber_slots_key, max_chamber_slots_key = get_chamber_slots_keys() max_slots = str(DEFAULT_MAX_CHAMBER_SLOTS ) if not max_chamber_slots else max_chamber_slots aplib.cache_data(active_chamber_slots_key, []) aplib.cache_data(max_chamber_slots_key, max_slots) return True
def reset_globals(): """ Reset Globals Used by Supercontainer in SC-PreSeq """ log.debug("Chamber globals: reset...") container = aplib.get_my_container_key() S_KEY = '_'.join(container.split('|')[:-1]) cp_key = 'chamber_profile_' + S_KEY cc_key = 'chamber_corners_' + S_KEY aplib.cache_data(cp_key, None) aplib.cache_data(cc_key, None) log.debug("Chamber globals reset done!") return
def prestep__restore_container(): """Restore running status container read local slots status from /tftpboot/slot_status/slot_status, restore start containers :return: """ area = 'SYSBI' slot_status_file = r'/tftpboot/slot_status/slot_status' with open(slot_status_file, 'r') as f: slot_status = [cell.strip() for cell in f.readlines() if ':' in cell] lib.cache_data('slot_status', slot_status) log.info('Local: {}'.format(slot_status)) log.debug('******************') for i in range(1, 9): log.info('{}'.format(slot_status[(i - 1) * 12:i * 12])) log.debug('******************') keep_status = ['ERRO', 'FAIL', 'PASS', 'IDLE', 'NULL'] for ctr in slot_status: station = 'Station' cell = 'AUTO:UUT{:02}_{:02}'.format( int(ctr.split(':')[1].split('-')[0]), int(ctr.split(':')[1].split('-')[1])) log.info('Station: {}, Cell: {}'.format(station, cell)) if any(status in ctr for status in keep_status): log.info('Container [{}] Keep {}'.format(cell, ctr)) continue log.info('Container ctr restore to running'.format(ctr)) while True: run_apollo_container(prod_line='UAG_C3K', area=area, test_station=station, container=cell, mode='PROD') if lib.get_container_status(cell) == 'RUNNING': time.sleep(60) break log.info('{} running meet issue, re-start'.format(cell)) continue return lib.PASS
def prestep__chamber_staging(area): """ Chamber Staging Run by Supercontainer Operator selects which UUT slots to run for the chamber. :param (str) area: Test Area :return: """ info = aplib.get_pre_sequence_info() active_chamber_slots = '0' max_chamber_slots = len(info.containers) log.debug("MAX Chamber SLots = {0}".format(max_chamber_slots)) ans_good = False while not ans_good: ans = aplib.ask_question( "Enter sequential UUT slots for chamber testing [Default = 1-{0}]:\n" " Ex1. 1-10,12,15\n" " Ex2. 2,4,6,8\n" " Ex3. 2-11\n".format(max_chamber_slots)) ans = '1-{0}'.format(max_chamber_slots) if ans == '' else ans ans_good = True if re.match("(^[0-9]+[0-9,\-]*$)", ans) else False if ans.upper() == 'ABORT': raise apexceptions.AbortException( "Operator aborted chamber staging of UUT slots.") active_chamber_slots = common_utils.expand_comma_dash_num_list(ans) if max(active_chamber_slots) > max_chamber_slots: log.warning( "Chamber UUT slot selection exceeds maximum available; please re-enter." ) ans_good = False log.debug( "Active Chamber SLots accepted: {0}".format(active_chamber_slots)) ACTIVECS_KEY, MAXCS_KEY = get_chamber_slots_keys() aplib.cache_data(ACTIVECS_KEY, active_chamber_slots) aplib.cache_data(MAXCS_KEY, str(max_chamber_slots)) # Reset globals reset_globals() return aplib.PASS
def change_slot_status(slot, status, skip_error=True): """Change Slot Status Change slot status in local file :param slot: sample: Station_B_01 = 1-1: first 1 is Rack number , second 1 is Cell number :param status: sample: status: Pass, Fail1, Fail2, Idel. pass: product_name,1-1,Pass Fail1: product_name,1-1,Fail1,num-num. #num-num:re-test cell Fail2: product_name,1-1,Fail2 IDEL: :param skip_error: :return: """ log.info('{} {} change lock...'.format(slot, status)) with locking.named_priority_lock(lockname='slot_status_lock', release_timeout=60, wait_timeout=30 * 60): slot_status = lib.get_cached_data('slot_status') log.debug('>>>>> ') for i in range(1, 9): log.info('{}'.format(slot_status[(i - 1) * 12:i * 12])) log.debug('>>>>> '.format(slot_status)) if 'ERRO' in slot_status[slot_index[slot]] and skip_error: log.debug('ERROR cannot change') else: if "ERRO" in status: status = "0ERRO1" slot_status[slot_index[slot]] = "{}:{}".format(status, slot) lib.cache_data('slot_status', slot_status) log.debug('<<<<< ') for i in range(1, 9): log.info('{}'.format(slot_status[(i - 1) * 12:i * 12])) log.debug('<<<<< ') cap_slot_status() log.info('Change local OK') return True
def _allocate_card(self, action, priority=100, card_name='card', keep_last=False): """ Allocate Card (INTERNAL) Activating a linecard or Supervisor = start using it. Deactivating a linecard or Supervisor = done using it and no longer need to talk to the card. This routine uses an "active card" list maintained in global cache to keep track of all linecards/Supervisors in use. Also a 'remove from list' is performed on all non-running containers still in the 'active card list' (could happen with abort or exception w/ no cleanup). :param (str) action: 'deactivate', 'activate', 'show' :param (int) priority: lower number is higher priority :param (bool) keep_last: Future feature (NOT USED); use to keep last container when deactivating to stay powered on for something else prior to cleanup. :return: True|False """ log.debug("Configuration Data") self.ud.derive_device_info() card_config = self.ud.uut_config.get(card_name.lower(), None) if not card_config: log.warning("No configuration data for the UUT card: {0}".format( card_name)) log.warning( "Please check the card name and the Apollo x_config.py.") return False log.debug("Card config = {0}".format(card_config)) container_key = aplib.get_my_container_key() container = container_key.split("|")[-1] pl, ar, ts, _ = container_key.split("|", 3) active_name = '_'.join([pl, ar, ts, 'ActiveModular']) with locking.ContainerPriorityLock('__active_modular__', priority=priority): log.debug("Lock : {0}".format(active_name)) log.debug("Priority: {0}".format(priority)) active_cards = aplib.get_cached_data(active_name) if active_cards: idx = active_cards.index( container) if container in active_cards else -1 else: active_cards = [] if action == 'activate': log.debug("Active {0}.".format(card_name)) if not active_cards: log.debug("First {0} container to use: '{1}'".format( card_name.lower(), container)) active_cards = [container] aplib.cache_data(active_name, active_cards) else: if container not in active_cards: log.debug( "Adding {0} container to the active list: {1}". format(card_name.lower(), container)) active_cards.append(container) aplib.cache_data(active_name, active_cards) else: log.debug("{0} container already active: {1}".format( card_name, container)) elif action == 'deactivate': log.debug("Deactive {0}.".format(card_name)) for c in active_cards: # Check & remove orphaned containers (not running but still in the active list due to no cleanup). status = aplib.get_container_status(c) log.debug("{0:<10} = {1}{2}".format( c, status, '*' if status != 'RUNNING' else '')) if status != 'RUNNING': idx = active_cards.index(c) active_cards.pop(idx) if len(active_cards) > 1: if idx >= 0: log.info("Deactivating {0} container: '{1}'...".format( card_name.lower(), container)) active_cards.pop(idx) aplib.cache_data(active_name, active_cards) log.info( "{0} container deactivated.".format(card_name)) else: log.info("{0} container already deactivated.".format( card_name)) elif len(active_cards) == 1: if not keep_last: log.info( "Only one {0} container remains active and it will be deactivated." .format(card_name.lower())) aplib.cache_data(active_name, []) else: log.warning( "Only one {0} container remains active; deactivate is bypassed." .format(card_name.lower())) log.warning( "This should only be done when the chassis needs to stay powered on." ) else: log.info( "No {0} containers were activated; nothing to deactivate." .format(card_name.lower())) elif action == 'show': log.debug("Show {0}.".format(card_name)) else: log.error("Unknown action for {0} allocation.".format( card_name.lower())) return False msg = "Active {0}s".format(card_name) log.info(msg) log.info("-" * len(msg)) for lc in active_cards: log.info("{0} {1}".format(lc, '*' if lc == container else '')) return True
def set_global_corners(forced_corners=None): """ Set Global ChamberCorners Used by the UUT Container PRE-SEQ. This sets the corners to be used by ALL UUTs in the chamber via a global data cache. IMPORTANT: Global cache key is the station path (i.e. chamber). Differing product families are allowed to run but their corner selections MUST match; if not then it will abort. Example set in product_definition: 'chamber_corners': [('NTNV', False), ('HTLV', True), ('HTHV', True), ('LTLV', True)] Example of globally saved after processing: OrderedDict([('NTNV', ('AMBIENT', 'NOMINAL', False)), ('HTLV', ('HOT', 'LOW', True)), ('HTHV', ('HOT', 'HIGH', True)), ('LTLV', ('COLD', 'LOW', True))]) :param (list) forced_corners: :return: """ log.debug("Global Corners: set...") # Check for a product-specific corner definition. _lookup = { 'HT': HOT, 'LT': COLD, 'NT': AMBIENT, 'HV': 'HIGH', 'LV': 'LOW', 'NV': 'NOMINAL' } container = aplib.get_my_container_key() try: udd = aplib.apdicts.userdict.get('udd') if not udd: log.error("The UutDescriptor Dict was not available.") log.error( "Please confirm proper application of the application software!" ) raise Exception("The UutDescriptor Dict was not available.") chamber_corners = udd.get('chamber_corners') if forced_corners: listed_corners = collections.OrderedDict(forced_corners) log.debug("Chamber Corners Source: FORCED.") elif chamber_corners: listed_corners = collections.OrderedDict(chamber_corners) log.debug("Chamber Corners Source: UUT DESCRIPTOR.") else: log.warning( "No UutDescriptor chamber_corners, or forced_corners available." ) log.warning( "Check the product definitions and common definition for 'chamber_corners'." ) log.warning( "The default '2-Corner' sequence (HTLV, LTHV) will be used.") listed_corners = [('LTHV', True), ('HTLV', True)] processed_corners = [] if listed_corners: for lc in listed_corners: name = lc[0] if isinstance(lc, tuple) else lc adt = lc[1] if isinstance(lc, tuple) and len(lc) > 1 else False if len(name) == 4: temp = _lookup.get(name[:2], AMBIENT) volt = _lookup.get(name[2:4], 'NOMINAL') elif len(name) == 2: temp = _lookup.get(name, AMBIENT) volt = 'NOMINAL' else: temp = AMBIENT volt = 'NOMINAL' processed_corners.append((name, (temp, volt, adt))) corners = collections.OrderedDict( processed_corners) if processed_corners else None except (KeyError, AttributeError): log.warning( "Chamber corner data is not available or not in correct form.") return False log.debug('-' * 20) log.debug("{0} : Chamber Corners = {1}".format(container, listed_corners)) # Now check for proper form of corners dict. for corner in corners: if not isinstance(corners[corner], tuple): log.error("Product specific corners are not in the proper form.") raise apexceptions.AbortException # Get the current corner definition (possibly set by another container in the same chamber) S_KEY = '_'.join(container.split('|')[:-1]) cc_key = 'chamber_corners_' + S_KEY with locking.named_priority_lock('__corners__' + S_KEY): try: log.debug("Chamber corner cache key (set) = {0}".format(cc_key)) established_corners = aplib.get_cached_data(cc_key) except (KeyError, apexceptions.ApolloException): established_corners = None if not forced_corners: # Save the product-specific corner selections for use by SEQ. if not established_corners: established_corners = corners aplib.cache_data(cc_key, established_corners) log.debug( "*** A new chamber corner set has been established. ***") # All UUT corner definitions must match. This allows different PIDs in the same chamber BUT requires them # to all have the same corner definition. if corners != established_corners: log.error("Chamber corners: REJECTED!") log.error( "There is a mismatch of chamber_corners in {0}. This is NOT allowed." .format(container)) log.error( "Please correct the situation before running the chamber. Inspect UUT product definitions." ) raise apexceptions.AbortException( "MISMATCH of chamber corners in {0}.".format(container)) else: log.debug("Chamber corners: ACCEPTED. {0}".format( established_corners)) else: aplib.cache_data(cc_key, corners) log.debug("Chamber corners: FORCED. {0}".format(corners)) return True
def set_global_profile(forced_profile=None): """ Set Global Chamber Profile Used by the UUT Container PRE-SEQ. This sets the profile to be used by ALL UUTs in the chamber via a global data cache. IMPORTANT: Global cache key is the station path (i.e. chamber). Differing product families are allowed to run but their profile selections MUST match; if not then it will abort. :param (list) forced_profile: :return: """ log.debug("Global Profile: set...") container = aplib.get_my_container_key() # Source the profile. try: udd = aplib.apdicts.userdict.get('udd') if not udd: log.error("The UutDescriptor Dict was not available.") log.error( "Please confirm proper application of the application software!" ) raise Exception("The UutDescriptor Dict was not available.") chamber_profile = udd.get('chamber_profile') if forced_profile: profile = collections.OrderedDict(forced_profile) log.debug("Chamber Profile Source: FORCED.") elif chamber_profile: profile = collections.OrderedDict(chamber_profile) log.debug("Chamber Profile Source: UUT DESCRIPTOR.") else: log.warning( "No UutDescriptor chamber_profile, or forced_profile available." ) log.warning( "Check the product definitions and common definition for 'chamber_profile'." ) log.warning("The default commercial profile will be used.") profile = collections.OrderedDict(DEFAULT_PROFILES['commercial']) except (KeyError, AttributeError): log.error( "Chamber profile data is not available or not in correct form.") return False log.debug('-' * 50) log.debug("{0} : Chamber Profile = {1}".format(container, profile)) # Get the current profile definition (possibly set by another container in the same chamber) # Global cache key is the station path (i.e. chamber) S_KEY = '_'.join(container.split('|')[:-1]) cp_key = 'chamber_profile_' + S_KEY with locking.named_priority_lock('__profile__' + S_KEY): try: log.debug("Chamber profile cache key (set) = {0}".format(cp_key)) established_profile = aplib.get_cached_data(cp_key) except (KeyError, apexceptions.ApolloException): established_profile = None if not forced_profile: # Save the product-specific profile selections for use by SEQ. if not established_profile: established_profile = profile aplib.cache_data(cp_key, established_profile) log.debug( "*** A new chamber profile set has been established. ***") # All UUT profile definitions must match. This allows different PIDs in the same chamber BUT requires # them to all have the same profile definition. if profile != established_profile: log.error("Chamber profile: REJECTED!") log.error( "There is a mismatch of chamber_profiles in {0}. This is NOT allowed." .format(container)) log.error( "Please correct the situation before running the chamber. Inspect UUT product definitions." ) raise apexceptions.AbortException( "MISMATCH of chamber profiles in {0}.".format(container)) else: log.debug("Chamber profile: ACCEPTED. {0}".format( established_profile)) else: aplib.cache_data(cp_key, profile) log.debug("Chamber profile: FORCED. {0}".format(profile)) return True