forked from HomeAssistant/fn_nas
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
03f8f3fa21 |
@@ -69,39 +69,46 @@ class FlynasCoordinator(DataUpdateCoordinator):
|
|||||||
|
|
||||||
async def get_ssh_connection(self):
|
async def get_ssh_connection(self):
|
||||||
"""从连接池获取或创建SSH连接"""
|
"""从连接池获取或创建SSH连接"""
|
||||||
# 如果连接池中有可用连接且没有超过最大活动命令数
|
# 避免递归调用,改为循环等待
|
||||||
while len(self.ssh_pool) > 0 and self.active_commands < self.max_connections:
|
start_time = time.time()
|
||||||
conn = self.ssh_pool.pop()
|
while True:
|
||||||
if await self.is_connection_alive(conn):
|
# 如果连接池中有可用连接且没有超过最大活动命令数
|
||||||
self.active_commands += 1
|
while len(self.ssh_pool) > 0 and self.active_commands < self.max_connections:
|
||||||
return conn
|
conn = self.ssh_pool.pop()
|
||||||
else:
|
if await self.is_connection_alive(conn):
|
||||||
await self.close_connection(conn)
|
self.active_commands += 1
|
||||||
|
return conn
|
||||||
# 如果没有可用连接,创建新连接
|
else:
|
||||||
if self.active_commands < self.max_connections:
|
await self.close_connection(conn)
|
||||||
try:
|
|
||||||
conn = await asyncssh.connect(
|
# 如果没有可用连接,创建新连接
|
||||||
self.host,
|
if self.active_commands < self.max_connections:
|
||||||
port=self.port,
|
try:
|
||||||
username=self.username,
|
conn = await asyncssh.connect(
|
||||||
password=self.password,
|
self.host,
|
||||||
known_hosts=None,
|
port=self.port,
|
||||||
connect_timeout=10
|
username=self.username,
|
||||||
)
|
password=self.password,
|
||||||
self.active_commands += 1
|
known_hosts=None,
|
||||||
self.ssh_closed = False
|
connect_timeout=10
|
||||||
|
)
|
||||||
# 确定是否需要sudo权限
|
self.active_commands += 1
|
||||||
await self.determine_sudo_setting(conn)
|
self.ssh_closed = False
|
||||||
|
|
||||||
return conn
|
# 确定是否需要sudo权限
|
||||||
except Exception as e:
|
await self.determine_sudo_setting(conn)
|
||||||
_LOGGER.error("创建SSH连接失败: %s", str(e), exc_info=True)
|
|
||||||
raise UpdateFailed(f"SSH连接失败: {str(e)}")
|
return conn
|
||||||
else:
|
except Exception as e:
|
||||||
|
_LOGGER.error("创建SSH连接失败: %s", str(e), exc_info=True)
|
||||||
|
raise UpdateFailed(f"SSH连接失败: {str(e)}")
|
||||||
|
|
||||||
|
# 等待0.1秒后重试,避免递归
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
return await self.get_ssh_connection()
|
|
||||||
|
# 设置超时(30秒)
|
||||||
|
if time.time() - start_time > 30:
|
||||||
|
raise UpdateFailed("获取SSH连接超时")
|
||||||
|
|
||||||
async def determine_sudo_setting(self, conn):
|
async def determine_sudo_setting(self, conn):
|
||||||
"""确定是否需要使用sudo权限"""
|
"""确定是否需要使用sudo权限"""
|
||||||
@@ -179,52 +186,58 @@ class FlynasCoordinator(DataUpdateCoordinator):
|
|||||||
async def run_command(self, command: str, retries=2) -> str:
|
async def run_command(self, command: str, retries=2) -> str:
|
||||||
"""使用连接池执行命令"""
|
"""使用连接池执行命令"""
|
||||||
conn = None
|
conn = None
|
||||||
try:
|
current_retries = retries
|
||||||
conn = await self.get_ssh_connection()
|
|
||||||
|
while current_retries >= 0:
|
||||||
# 根据sudo设置执行命令
|
try:
|
||||||
if self.use_sudo:
|
conn = await self.get_ssh_connection()
|
||||||
password = self.root_password if self.root_password else self.password
|
|
||||||
if password:
|
# 根据sudo设置执行命令
|
||||||
full_command = f"sudo -S {command}"
|
if self.use_sudo:
|
||||||
result = await conn.run(full_command, input=password + "\n", check=True)
|
password = self.root_password if self.root_password else self.password
|
||||||
|
if password:
|
||||||
|
full_command = f"sudo -S {command}"
|
||||||
|
result = await conn.run(full_command, input=password + "\n", check=True)
|
||||||
|
else:
|
||||||
|
full_command = f"sudo {command}"
|
||||||
|
result = await conn.run(full_command, check=True)
|
||||||
else:
|
else:
|
||||||
full_command = f"sudo {command}"
|
result = await conn.run(command, check=True)
|
||||||
result = await conn.run(full_command, check=True)
|
|
||||||
else:
|
return result.stdout.strip()
|
||||||
result = await conn.run(command, check=True)
|
except asyncssh.process.ProcessError as e:
|
||||||
|
if e.exit_status in [4, 32]:
|
||||||
return result.stdout.strip()
|
return ""
|
||||||
except asyncssh.process.ProcessError as e:
|
_LOGGER.error("Command failed: %s (exit %d)", command, e.exit_status)
|
||||||
if e.exit_status in [4, 32]:
|
# 连接可能已损坏,关闭它
|
||||||
return ""
|
await self.close_connection(conn)
|
||||||
_LOGGER.error("Command failed: %s (exit %d)", command, e.exit_status)
|
conn = None
|
||||||
# 连接可能已损坏,关闭它
|
if current_retries > 0:
|
||||||
await self.close_connection(conn)
|
current_retries -= 1
|
||||||
conn = None
|
continue
|
||||||
if retries > 0:
|
else:
|
||||||
return await self.run_command(command, retries-1)
|
raise UpdateFailed(f"Command failed: {command}") from e
|
||||||
else:
|
except asyncssh.Error as e:
|
||||||
raise UpdateFailed(f"Command failed: {command}") from e
|
_LOGGER.error("SSH连接错误: %s", str(e))
|
||||||
except asyncssh.Error as e:
|
await self.close_connection(conn)
|
||||||
_LOGGER.error("SSH连接错误: %s", str(e))
|
conn = None
|
||||||
await self.close_connection(conn)
|
if current_retries > 0:
|
||||||
conn = None
|
current_retries -= 1
|
||||||
if retries > 0:
|
continue
|
||||||
return await self.run_command(command, retries-1)
|
else:
|
||||||
else:
|
raise UpdateFailed(f"SSH错误: {str(e)}") from e
|
||||||
raise UpdateFailed(f"SSH错误: {str(e)}") from e
|
except Exception as e:
|
||||||
except Exception as e:
|
_LOGGER.error("意外错误: %s", str(e), exc_info=True)
|
||||||
_LOGGER.error("意外错误: %s", str(e), exc_info=True)
|
await self.close_connection(conn)
|
||||||
await self.close_connection(conn)
|
conn = None
|
||||||
conn = None
|
if current_retries > 0:
|
||||||
if retries > 0:
|
current_retries -= 1
|
||||||
return await self.run_command(command, retries-1)
|
continue
|
||||||
else:
|
else:
|
||||||
raise UpdateFailed(f"意外错误: {str(e)}") from e
|
raise UpdateFailed(f"意外错误: {str(e)}") from e
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
await self.release_ssh_connection(conn)
|
await self.release_ssh_connection(conn)
|
||||||
|
|
||||||
async def async_connect(self):
|
async def async_connect(self):
|
||||||
"""建立SSH连接(使用连接池)"""
|
"""建立SSH连接(使用连接池)"""
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"domain": "fn_nas",
|
"domain": "fn_nas",
|
||||||
"name": "飞牛NAS",
|
"name": "飞牛NAS",
|
||||||
"version": "1.3.1",
|
"version": "1.3.3",
|
||||||
"documentation": "https://github.com/anxms/fn_nas",
|
"documentation": "https://github.com/anxms/fn_nas",
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"codeowners": ["@anxms"],
|
"codeowners": ["@anxms"],
|
||||||
|
Reference in New Issue
Block a user