mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 11:06:30 +00:00
add resource check
incorrect pass / hw handling in a loader
This commit is contained in:
@@ -39,6 +39,7 @@ public enum CommandType
|
|||||||
None = 0,
|
None = 0,
|
||||||
Ok = 3,
|
Ok = 3,
|
||||||
Login = 10,
|
Login = 10,
|
||||||
|
CheckResource = 12,
|
||||||
ListRequest = 15,
|
ListRequest = 15,
|
||||||
ListFiles = 18,
|
ListFiles = 18,
|
||||||
Load = 20,
|
Load = 20,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
cdef enum CommandType:
|
cdef enum CommandType:
|
||||||
OK = 3
|
OK = 3
|
||||||
LOGIN = 10
|
LOGIN = 10
|
||||||
|
CHECK_RESOURCE = 12
|
||||||
LIST_REQUEST = 15
|
LIST_REQUEST = 15
|
||||||
LIST_FILES = 18
|
LIST_FILES = 18
|
||||||
LOAD = 20
|
LOAD = 20
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ cdef class RemoteCommand:
|
|||||||
command_type_names = {
|
command_type_names = {
|
||||||
3: "OK",
|
3: "OK",
|
||||||
10: "LOGIN",
|
10: "LOGIN",
|
||||||
|
12: "CHECK_RESOURCE",
|
||||||
15: "LIST_REQUEST",
|
15: "LIST_REQUEST",
|
||||||
18: "LIST_FILES",
|
18: "LIST_FILES",
|
||||||
20: "LOAD",
|
20: "LOAD",
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ cdef class ApiClient:
|
|||||||
|
|
||||||
cdef request(self, str method, str url, object payload, bint is_stream)
|
cdef request(self, str method, str url, object payload, bint is_stream)
|
||||||
cdef list_files(self, str folder, str search_file)
|
cdef list_files(self, str folder, str search_file)
|
||||||
|
cdef check_resource(self)
|
||||||
cdef load_bytes(self, str filename, str folder)
|
cdef load_bytes(self, str filename, str folder)
|
||||||
cdef upload_file(self, str filename, bytes resource, str folder)
|
cdef upload_file(self, str filename, bytes resource, str folder)
|
||||||
cdef load_big_file_cdn(self, str folder, str big_part)
|
cdef load_big_file_cdn(self, str folder, str big_part)
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ cdef class ApiClient:
|
|||||||
token = response.json()["token"]
|
token = response.json()["token"]
|
||||||
self.set_token(token)
|
self.set_token(token)
|
||||||
except HTTPError as e:
|
except HTTPError as e:
|
||||||
constants.logerror(response.json())
|
res = response.json()
|
||||||
|
constants.logerror(str(res))
|
||||||
if response.status_code == HTTPStatus.CONFLICT:
|
if response.status_code == HTTPStatus.CONFLICT:
|
||||||
res = response.json()
|
raise Exception(f"Error {res['ErrorCode']}: {res['Message']}")
|
||||||
raise Exception(res['Message'])
|
|
||||||
|
|
||||||
|
|
||||||
cdef set_token(self, str token):
|
cdef set_token(self, str token):
|
||||||
@@ -104,6 +104,11 @@ cdef class ApiClient:
|
|||||||
constants.log(<str> f'Get files list by {folder}')
|
constants.log(<str> f'Get files list by {folder}')
|
||||||
return response.json()
|
return response.json()
|
||||||
|
|
||||||
|
cdef check_resource(self):
|
||||||
|
cdef str hardware = HardwareService.get_hardware_info()
|
||||||
|
payload = json.dumps({ "hardware": hardware }, indent=4)
|
||||||
|
response = self.request('post', f'{self.api_url}/resources/check', payload, is_stream=False)
|
||||||
|
|
||||||
cdef load_bytes(self, str filename, str folder):
|
cdef load_bytes(self, str filename, str folder):
|
||||||
cdef str hardware = HardwareService.get_hardware_info()
|
cdef str hardware = HardwareService.get_hardware_info()
|
||||||
hw_hash = Security.get_hw_hash(hardware)
|
hw_hash = Security.get_hw_hash(hardware)
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ cdef class CommandProcessor:
|
|||||||
if command.command_type == CommandType.LOGIN:
|
if command.command_type == CommandType.LOGIN:
|
||||||
self.api_client.set_credentials(Credentials.from_msgpack(command.data))
|
self.api_client.set_credentials(Credentials.from_msgpack(command.data))
|
||||||
self.remote_handler.send(command.client_id, self.ok_response.serialize())
|
self.remote_handler.send(command.client_id, self.ok_response.serialize())
|
||||||
|
elif command.command_type == CommandType.CHECK_RESOURCE:
|
||||||
|
self.api_client.check_resource()
|
||||||
|
self.remote_handler.send(command.client_id, RemoteCommand(CommandType.OK).serialize())
|
||||||
elif command.command_type == CommandType.LOAD:
|
elif command.command_type == CommandType.LOAD:
|
||||||
file_data = FileData.from_msgpack(command.data)
|
file_data = FileData.from_msgpack(command.data)
|
||||||
file_bytes = self.api_client.load_bytes(file_data.filename, file_data.folder)
|
file_bytes = self.api_client.load_bytes(file_data.filename, file_data.folder)
|
||||||
@@ -61,9 +64,6 @@ cdef class CommandProcessor:
|
|||||||
data = UploadFileData.from_msgpack(command.data)
|
data = UploadFileData.from_msgpack(command.data)
|
||||||
file_bytes = self.api_client.upload_big_small_resource(data.resource, data.filename, data.folder)
|
file_bytes = self.api_client.upload_big_small_resource(data.resource, data.filename, data.folder)
|
||||||
self.remote_handler.send(command.client_id, RemoteCommand(CommandType.OK).serialize())
|
self.remote_handler.send(command.client_id, RemoteCommand(CommandType.OK).serialize())
|
||||||
elif command.command_type == CommandType.EXIT:
|
|
||||||
t = Thread(target=self.stop) # non-block worker:
|
|
||||||
t.start()
|
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
cdef enum CommandType:
|
cdef enum CommandType:
|
||||||
OK = 3
|
OK = 3
|
||||||
LOGIN = 10
|
LOGIN = 10
|
||||||
|
CHECK_RESOURCE = 12
|
||||||
LIST_REQUEST = 15
|
LIST_REQUEST = 15
|
||||||
LIST_FILES = 18
|
LIST_FILES = 18
|
||||||
LOAD = 20
|
LOAD = 20
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ cdef class RemoteCommand:
|
|||||||
command_type_names = {
|
command_type_names = {
|
||||||
3: "OK",
|
3: "OK",
|
||||||
10: "LOGIN",
|
10: "LOGIN",
|
||||||
|
12: "CHECK_RESOURCE",
|
||||||
15: "LIST_REQUEST",
|
15: "LIST_REQUEST",
|
||||||
18: "LIST_FILES",
|
18: "LIST_FILES",
|
||||||
20: "LOAD",
|
20: "LOAD",
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
|
using MessagePack;
|
||||||
|
|
||||||
namespace Azaion.LoaderUI;
|
namespace Azaion.LoaderUI;
|
||||||
|
|
||||||
public class ApiCredentials(string email, string pw)
|
[MessagePackObject]
|
||||||
|
public class ApiCredentials
|
||||||
{
|
{
|
||||||
public string Email { get; set; } = email;
|
[Key(nameof(Email))]
|
||||||
public string Password { get; set; } = pw;
|
public string Email { get; set; } = null!;
|
||||||
|
|
||||||
|
[Key(nameof(Password))]
|
||||||
|
public string Password { get; set; } = null!;
|
||||||
|
|
||||||
public bool IsValid() =>
|
public bool IsValid() =>
|
||||||
!string.IsNullOrWhiteSpace(Email) && !string.IsNullOrWhiteSpace(Password);
|
!string.IsNullOrWhiteSpace(Email) && !string.IsNullOrWhiteSpace(Password);
|
||||||
|
|||||||
@@ -10,9 +10,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MessagePack" Version="3.1.4" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.5" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
|
||||||
|
<PackageReference Include="NetMQ" Version="4.0.1.13" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
|
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
|
||||||
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.1" />
|
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.1" />
|
||||||
|
|||||||
@@ -6,4 +6,8 @@ public static class Constants
|
|||||||
public const string API_URL = "https://api.azaion.com";
|
public const string API_URL = "https://api.azaion.com";
|
||||||
public const string AZAION_SUITE_EXE = "Azaion.Suite.exe";
|
public const string AZAION_SUITE_EXE = "Azaion.Suite.exe";
|
||||||
public const string SUITE_FOLDER = "suite";
|
public const string SUITE_FOLDER = "suite";
|
||||||
|
public const string INFERENCE_EXE = "azaion-inference";
|
||||||
|
public const string EXTERNAL_LOADER_PATH = "azaion-loader.exe";
|
||||||
|
public const int EXTERNAL_LOADER_PORT = 5020;
|
||||||
|
public const string EXTERNAL_LOADER_HOST = "127.0.0.1";
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using MessagePack;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using NetMQ;
|
||||||
|
using NetMQ.Sockets;
|
||||||
|
|
||||||
|
|
||||||
namespace Azaion.LoaderUI;
|
namespace Azaion.LoaderUI;
|
||||||
@@ -23,17 +28,40 @@ public partial class Login
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetControlsStatus(bool isLoading)
|
||||||
|
{
|
||||||
|
LoginBtn.IsEnabled = !isLoading;
|
||||||
|
TbEmail.IsEnabled = !isLoading;
|
||||||
|
TbPassword.IsEnabled = !isLoading;
|
||||||
|
LoginBtn.Cursor = isLoading ? Cursors.Wait : Cursors.Arrow;
|
||||||
|
Cursor = isLoading ? Cursors.Wait : Cursors.Arrow;
|
||||||
|
}
|
||||||
|
|
||||||
private async void LoginClick(object sender, RoutedEventArgs e)
|
private async void LoginClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var creds = new ApiCredentials(TbEmail.Text, TbPassword.Password);
|
var creds = new ApiCredentials
|
||||||
|
{
|
||||||
|
Email = TbEmail.Text,
|
||||||
|
Password = TbPassword.Password
|
||||||
|
};
|
||||||
if (!creds.IsValid())
|
if (!creds.IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LoginBtn.Cursor = Cursors.Wait;
|
SetControlsStatus(isLoading: true);
|
||||||
Cursor = Cursors.Wait;
|
|
||||||
|
|
||||||
_azaionApi.Login(creds);
|
_azaionApi.Login(creds);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Validate(creds);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
_logger.LogError(exception, exception.Message);
|
||||||
|
TbStatus.Foreground = Brushes.Red;
|
||||||
|
TbStatus.Text = exception.Message;
|
||||||
|
SetControlsStatus(isLoading: false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TbStatus.Foreground = Brushes.Black;
|
||||||
var installerVersion = await GetInstallerVer();
|
var installerVersion = await GetInstallerVer();
|
||||||
var localVersion = GetLocalVer();
|
var localVersion = GetLocalVer();
|
||||||
|
|
||||||
@@ -44,12 +72,81 @@ public partial class Login
|
|||||||
TbStatus.Text = $"Installed {installerVersion}!";
|
TbStatus.Text = $"Installed {installerVersion}!";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
TbStatus.Text = $"Your version is up to date!";
|
TbStatus.Text = "Your version is up to date!";
|
||||||
|
|
||||||
Process.Start(Constants.AZAION_SUITE_EXE, $"-e {creds.Email} -p {creds.Password}");
|
Process.Start(Constants.AZAION_SUITE_EXE, $"-e {creds.Email} -p {creds.Password}");
|
||||||
|
await Task.Delay(800);
|
||||||
|
TbStatus.Text = "Loading...";
|
||||||
|
while (!Process.GetProcessesByName(Constants.INFERENCE_EXE).Any())
|
||||||
|
await Task.Delay(500);
|
||||||
|
await Task.Delay(500);
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Validate(ApiCredentials creds)
|
||||||
|
{
|
||||||
|
var dealer = new DealerSocket();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var process = new Process();
|
||||||
|
process.StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = Constants.EXTERNAL_LOADER_PATH,
|
||||||
|
Arguments = $"--port {Constants.EXTERNAL_LOADER_PORT} --api {Constants.API_URL}",
|
||||||
|
CreateNoWindow = true
|
||||||
|
};
|
||||||
|
process.Start();
|
||||||
|
dealer.Options.Identity = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString("N"));
|
||||||
|
dealer.Connect($"tcp://{Constants.EXTERNAL_LOADER_HOST}:{Constants.EXTERNAL_LOADER_PORT}");
|
||||||
|
|
||||||
|
var result = SendCommand(dealer, RemoteCommand.Create(CommandType.Login, creds));
|
||||||
|
if (result.CommandType != CommandType.Ok)
|
||||||
|
throw new Exception(result.Message);
|
||||||
|
|
||||||
|
result = SendCommand(dealer, RemoteCommand.Create(CommandType.CheckResource));
|
||||||
|
if (result.CommandType != CommandType.Ok)
|
||||||
|
throw new Exception(result.Message);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, e.Message);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SendCommand(dealer, RemoteCommand.Create(CommandType.Exit));
|
||||||
|
dealer.Close();
|
||||||
|
dealer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private RemoteCommand SendCommand(DealerSocket dealer, RemoteCommand command, int retryCount = 30, int retryDelayMs = 800)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dealer.SendFrame(MessagePackSerializer.Serialize(command));
|
||||||
|
|
||||||
|
var tryNum = 0;
|
||||||
|
while (tryNum++ < retryCount)
|
||||||
|
{
|
||||||
|
if (!dealer.TryReceiveFrameBytes(TimeSpan.FromMilliseconds(retryDelayMs), out var bytes))
|
||||||
|
continue;
|
||||||
|
var res = MessagePackSerializer.Deserialize<RemoteCommand>(bytes);
|
||||||
|
if (res.CommandType == CommandType.Error)
|
||||||
|
throw new Exception(res.Message);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception($"Sent {command} {retryCount} times, with wait time {retryDelayMs}ms for each call. No response from client.");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, e.Message);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task DownloadAndRunInstaller()
|
private async Task DownloadAndRunInstaller()
|
||||||
{
|
{
|
||||||
var (installerName, stream) = await _azaionApi.DownloadInstaller(_dirConfig?.SuiteInstallerDirectory ?? "");
|
var (installerName, stream) = await _azaionApi.DownloadInstaller(_dirConfig?.SuiteInstallerDirectory ?? "");
|
||||||
@@ -65,6 +162,7 @@ public partial class Login
|
|||||||
|
|
||||||
var process = Process.Start(processInfo);
|
var process = Process.Start(processInfo);
|
||||||
await process!.WaitForExitAsync();
|
await process!.WaitForExitAsync();
|
||||||
|
File.Delete(installerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Version> GetInstallerVer()
|
private async Task<Version> GetInstallerVer()
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
using MessagePack;
|
||||||
|
|
||||||
|
namespace Azaion.LoaderUI;
|
||||||
|
|
||||||
|
[MessagePackObject]
|
||||||
|
public class RemoteCommand(CommandType commandType, byte[]? data = null, string? message = null)
|
||||||
|
{
|
||||||
|
[Key("CommandType")]
|
||||||
|
public CommandType CommandType { get; set; } = commandType;
|
||||||
|
|
||||||
|
[Key("Data")]
|
||||||
|
public byte[]? Data { get; set; } = data;
|
||||||
|
|
||||||
|
[Key("Message")]
|
||||||
|
public string? Message { get; set; } = message;
|
||||||
|
|
||||||
|
public static RemoteCommand Create(CommandType commandType) =>
|
||||||
|
new(commandType);
|
||||||
|
|
||||||
|
public static RemoteCommand Create<T>(CommandType commandType, T data, string? message = null) where T : class =>
|
||||||
|
new(commandType, MessagePackSerializer.Serialize(data), message);
|
||||||
|
|
||||||
|
public override string ToString() => $"({CommandType.ToString().ToUpper()}: Data: {Data?.Length ?? 0} bytes. Message: {Message})";
|
||||||
|
}
|
||||||
|
|
||||||
|
[MessagePackObject]
|
||||||
|
public class LoadFileData(string filename, string? folder = null )
|
||||||
|
{
|
||||||
|
[Key(nameof(Folder))]
|
||||||
|
public string? Folder { get; set; } = folder;
|
||||||
|
|
||||||
|
[Key(nameof(Filename))]
|
||||||
|
public string Filename { get; set; } = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public enum CommandType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Ok = 3,
|
||||||
|
Login = 10,
|
||||||
|
CheckResource = 12,
|
||||||
|
ListRequest = 15,
|
||||||
|
ListFiles = 18,
|
||||||
|
Load = 20,
|
||||||
|
LoadBigSmall = 22,
|
||||||
|
UploadBigSmall = 24,
|
||||||
|
DataBytes = 25,
|
||||||
|
Inference = 30,
|
||||||
|
InferenceData = 35,
|
||||||
|
StopInference = 40,
|
||||||
|
AIAvailabilityCheck = 80,
|
||||||
|
AIAvailabilityResult = 85,
|
||||||
|
Error = 90,
|
||||||
|
Exit = 100,
|
||||||
|
}
|
||||||
@@ -111,7 +111,7 @@ public partial class App
|
|||||||
_loaderClient = new LoaderClient(initConfig.LoaderClientConfig, Log.Logger, _mainCTokenSource.Token);
|
_loaderClient = new LoaderClient(initConfig.LoaderClientConfig, Log.Logger, _mainCTokenSource.Token);
|
||||||
|
|
||||||
_loaderClient.StartClient();
|
_loaderClient.StartClient();
|
||||||
_loaderClient.Connect(); //Client app should be already started by LoaderUI
|
_loaderClient.Connect();
|
||||||
_loaderClient.Login(credentials);
|
_loaderClient.Login(credentials);
|
||||||
|
|
||||||
var azaionApi = new AzaionApi(Log.Logger, new HttpClient { BaseAddress = new Uri(initConfig.InferenceClientConfig.ApiUrl) }, _cache, credentials);
|
var azaionApi = new AzaionApi(Log.Logger, new HttpClient { BaseAddress = new Uri(initConfig.InferenceClientConfig.ApiUrl) }, _cache, credentials);
|
||||||
|
|||||||
Reference in New Issue
Block a user