""" Server Management Tool - Auto-incrementing IDs Properly checks existing server IDs and increments from the highest """ import asyncio import sys sys.path.insert(0, r'C:\DEV\COPILOT\geutebruck-api\src\api\protos') import grpc import configuration_pb2 import configuration_pb2_grpc async def get_existing_servers(): """Read current configuration and list all servers""" channel = grpc.aio.insecure_channel('localhost:50051') stub = configuration_pb2_grpc.ConfigurationServiceStub(channel) try: request = configuration_pb2.ReadConfigurationTreeRequest() response = await stub.ReadConfigurationTree(request, timeout=10.0) # Find GeViGCoreServer node servers = [] for child in response.root.children: if child.name == "GeViGCoreServer": for server in child.children: if server.type == "folder": servers.append({ 'id': server.name, 'alias': next((c.string_value for c in server.children if c.name == "Alias"), ""), 'host': next((c.string_value for c in server.children if c.name == "Host"), "") }) break await channel.close() return servers except grpc.RpcError as e: print(f"Error reading configuration: {e.code()} - {e.details()}") await channel.close() return [] def get_next_server_id(servers): """Find the highest numeric server ID and return next ID""" numeric_ids = [] for server in servers: try: numeric_ids.append(int(server['id'])) except ValueError: # Skip non-numeric IDs pass if not numeric_ids: return "1" return str(max(numeric_ids) + 1) async def delete_server(server_id): """Delete a server by ID""" channel = grpc.aio.insecure_channel('localhost:50051') stub = configuration_pb2_grpc.ConfigurationServiceStub(channel) try: request = configuration_pb2.DeleteServerRequest(server_id=server_id) response = await stub.DeleteServer(request, timeout=10.0) print(f" [OK] Deleted server '{server_id}'") await channel.close() return True except grpc.RpcError as e: print(f" [ERROR] Failed to delete server '{server_id}': {e.details()}") await channel.close() return False async def create_server(alias, host, user="admin", password="", enabled=True): """Create a server with auto-incremented ID""" # Get existing servers and determine next ID servers = await get_existing_servers() next_id = get_next_server_id(servers) print(f"\nCreating server with ID={next_id} (auto-incremented)") channel = grpc.aio.insecure_channel('localhost:50051') stub = configuration_pb2_grpc.ConfigurationServiceStub(channel) request = configuration_pb2.CreateServerRequest( server=configuration_pb2.ServerData( id=next_id, alias=alias, host=host, user=user, password=password, enabled=enabled, deactivate_echo=False, deactivate_live_check=False ) ) try: response = await stub.CreateServer(request, timeout=10.0) print(f" [OK] Server created") print(f" ID: {response.server.id}") print(f" Alias: {response.server.alias}") print(f" Host: {response.server.host}") print(f" Enabled: {response.server.enabled} (bool type)") await channel.close() return response.server.id except grpc.RpcError as e: print(f" [ERROR] Failed to create server: {e.details()}") await channel.close() return None async def delete_action_mapping(mapping_id): """Delete an action mapping by ID (1-based)""" channel = grpc.aio.insecure_channel('localhost:50051') stub = configuration_pb2_grpc.ConfigurationServiceStub(channel) try: request = configuration_pb2.DeleteActionMappingRequest(mapping_id=mapping_id) response = await stub.DeleteActionMapping(request, timeout=10.0) print(f" [OK] Deleted action mapping #{mapping_id}") await channel.close() return True except grpc.RpcError as e: print(f" [ERROR] Failed to delete mapping #{mapping_id}: {e.details()}") await channel.close() return False async def list_action_mappings(): """List all action mappings""" channel = grpc.aio.insecure_channel('localhost:50051') stub = configuration_pb2_grpc.ConfigurationServiceStub(channel) try: request = configuration_pb2.ReadActionMappingsRequest() response = await stub.ReadActionMappings(request, timeout=10.0) mappings = [] for i, mapping in enumerate(response.mappings, 1): mappings.append({ 'id': i, 'name': mapping.name, 'input_count': len(mapping.input_actions), 'output_count': len(mapping.output_actions) }) await channel.close() return mappings except grpc.RpcError as e: print(f"Error reading mappings: {e.details()}") await channel.close() return [] async def main(): print("=" * 70) print("SERVER MANAGEMENT TOOL - Auto-incrementing IDs") print("=" * 70) # 1. List existing servers print("\n1. CURRENT SERVERS:") print("-" * 70) servers = await get_existing_servers() if servers: for server in servers: print(f" ID: {server['id']:10s} | Alias: {server['alias']:30s} | Host: {server['host']}") else: print(" No servers found") # 2. List existing action mappings print("\n2. CURRENT ACTION MAPPINGS:") print("-" * 70) mappings = await list_action_mappings() if mappings: for mapping in mappings: print(f" #{mapping['id']}: {mapping['name']} (In:{mapping['input_count']}, Out:{mapping['output_count']})") else: print(" No action mappings found") # 3. Clean up test data print("\n3. CLEANING UP TEST DATA:") print("-" * 70) # Delete test servers (18, 19) for server_id in ["18", "19"]: if any(s['id'] == server_id for s in servers): await delete_server(server_id) # Delete test mapping (should be last one based on the order) test_mapping_ids = [m['id'] for m in mappings if "Test Mapping" in m['name']] for mapping_id in test_mapping_ids: await delete_action_mapping(mapping_id) # 4. Demonstrate proper server creation print("\n4. CREATING NEW SERVERS WITH AUTO-INCREMENT:") print("-" * 70) await create_server( alias="Production Server 1", host="192.168.1.100", user="admin", password="secure123" ) await create_server( alias="Production Server 2", host="192.168.1.101", user="admin", password="secure123" ) # 5. List final state print("\n5. FINAL SERVER LIST:") print("-" * 70) servers = await get_existing_servers() for server in servers: print(f" ID: {server['id']:10s} | Alias: {server['alias']:30s} | Host: {server['host']}") print("\n" + "=" * 70) print("DONE - Check GeViSet to verify the changes") print("=" * 70) if __name__ == "__main__": asyncio.run(main())