Attempt to use methods, and if they fail, fallback to the next method in the cache.
(
method, method_type, arg
)
| 1562 | |
| 1563 | |
| 1564 | def _attempt_method_get( |
| 1565 | method, method_type, arg |
| 1566 | ): # type: (Method, str, str) -> Optional[str] |
| 1567 | """ |
| 1568 | Attempt to use methods, and if they fail, fallback to the next method in the cache. |
| 1569 | """ |
| 1570 | if not METHOD_CACHE[method_type] and not FALLBACK_CACHE[method_type]: |
| 1571 | _warn_critical("No usable methods found for MAC type '%s'" % method_type) |
| 1572 | return None |
| 1573 | |
| 1574 | if DEBUG: |
| 1575 | log.debug( |
| 1576 | "Attempting get() (method='%s', method_type='%s', arg='%s')", |
| 1577 | str(method), |
| 1578 | method_type, |
| 1579 | arg, |
| 1580 | ) |
| 1581 | |
| 1582 | result = None |
| 1583 | try: |
| 1584 | result = method.get(arg) |
| 1585 | except CalledProcessError as ex: |
| 1586 | # Don't mark return code 1 on a process as unusable! |
| 1587 | # Example of return code 1 on ifconfig from WSL: |
| 1588 | # Blake:goesc$ ifconfig eth8 |
| 1589 | # eth8: error fetching interface information: Device not found |
| 1590 | # Blake:goesc$ echo $? |
| 1591 | # 1 |
| 1592 | # Methods where an exit code of 1 makes it invalid should handle the |
| 1593 | # CalledProcessError, inspect the return code, and set self.unusable = True |
| 1594 | if ex.returncode != 1: |
| 1595 | log.warning( |
| 1596 | "Cached Method '%s' failed for '%s' lookup with process exit " |
| 1597 | "code '%d' != 1, marking unusable. Exception: %s", |
| 1598 | str(method), |
| 1599 | method_type, |
| 1600 | ex.returncode, |
| 1601 | str(ex), |
| 1602 | ) |
| 1603 | method.unusable = True |
| 1604 | except Exception as ex: |
| 1605 | log.warning( |
| 1606 | "Cached Method '%s' failed for '%s' lookup with unhandled exception: %s", |
| 1607 | str(method), |
| 1608 | method_type, |
| 1609 | str(ex), |
| 1610 | ) |
| 1611 | method.unusable = True |
| 1612 | |
| 1613 | # When an unhandled exception occurs (or exit code other than 1), remove |
| 1614 | # the method from the cache and reinitialize with next candidate. |
| 1615 | if not result and method.unusable: |
| 1616 | new_method = _remove_unusable(method, method_type) |
| 1617 | |
| 1618 | if not new_method: |
| 1619 | return None |
| 1620 | |
| 1621 | return _attempt_method_get(new_method, method_type, arg) |
no test coverage detected