async def response(self): """Initiate query validation and execution.""" device = getattr(devices, self.query_location) log.debug(f"Received query for {self.query_data}") log.debug(f"Matched device config: {device}") supported, transport = validate_nos(device.nos) connect = None output = params.messages.general connect = Connect(device, self.query_data, transport) if supported and transport == "rest": output = await connect.rest() elif supported and transport == "scrape": if device.proxy: output = await connect.scrape_proxied() else: output = await connect.scrape_direct() else: raise ConfigError('"{nos}" is not supported.', nos=device.nos) if output == "" or output == "\n": raise ResponseEmpty(params.messages.no_output, device_name=device.display_name) log.debug( f"Output for query: {self.query_data.json()}:\n{repr(output)}") return output
def supported_nos(cls, value): """Validate that nos is supported by hyperglass. Raises: UnsupportedDevice: Raised if nos is unsupported. Returns: {str} -- Valid NOS """ if value in SCRAPE_HELPERS.keys(): value = SCRAPE_HELPERS[value] supported, _ = validate_nos(value) if not supported: raise UnsupportedDevice('"{nos}" is not supported.', nos=value) return value
async def execute(query: Query) -> Union[str, Sequence[Dict]]: """Initiate query validation and execution.""" output = params.messages.general log.debug("Received query for {}", query.json()) log.debug("Matched device config: {}", query.device) supported, driver_name = validate_nos(query.device.nos) mapped_driver = DRIVER_MAP.get(driver_name, NetmikoConnection) driver = mapped_driver(query.device, query) timeout_args = { "unformatted_msg": params.messages.connection_error, "device_name": query.device.name, "error": params.messages.request_timeout, } if query.device.proxy: timeout_args["proxy"] = query.device.proxy.name signal.signal(signal.SIGALRM, handle_timeout(**timeout_args)) signal.alarm(params.request_timeout - 1) if query.device.proxy: proxy = driver.setup_proxy() with proxy() as tunnel: response = await driver.collect( tunnel.local_bind_host, tunnel.local_bind_port ) else: response = await driver.collect() output = await driver.parsed_response(response) if output == "" or output == "\n": raise ResponseEmpty(params.messages.no_output, device_name=query.device.name) log.debug("Output for query: {}:\n{}", query.json(), repr(output)) signal.alarm(0) return output
def validate_nos_commands(cls, values: "Device") -> "Device": """Validate & rewrite NOS, set default commands.""" nos = values.get("nos", "") if not nos: # Ensure nos is defined. raise ValueError( f'Device {values["name"]} is missing a `nos` (Network Operating System).' ) if nos in SCRAPE_HELPERS.keys(): # Rewrite NOS to helper value if needed. nos = SCRAPE_HELPERS[nos] # Verify NOS is supported by hyperglass. supported, _ = validate_nos(nos) if not supported: raise UnsupportedDevice('"{nos}" is not supported.', nos=nos) values["nos"] = nos commands = values.get("commands") if commands is None: # If no commands are defined, set commands to the NOS. inferred = values["nos"] # If the _telnet prefix is added, remove it from the command # profile so the commands are the same regardless of # protocol. if "_telnet" in inferred: inferred = inferred.replace("_telnet", "") values["commands"] = inferred return values