XCP-ng
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    XEN Orchestra JSON-RPC automation questions

    Scheduled Pinned Locked Moved Unsolved Infrastructure as Code
    json-rpspowershell 5websocketautomationdeployclone
    2 Posts 2 Posters 26 Views 2 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • I Offline
      IvanK
      last edited by IvanK

      Hello.

      We already have VM deploy tool written in powershell 5. And now we need to add there support for XCP-NG.
      REST API does not provide neither clone nor methods for change VM properties (but name and description, so I had to use websockets.

      But I face several issues:

      1. When I call vm.clone method I can see in corresponding task that it fails with “SR_BACKEND_FAILURE_1200(, Invalid argument, )” error, never mind that sr is not needed for clone. here is reference from our XCP about this method:
      "vm.clone": {
        "params": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "full_copy": {
            "type": "boolean"
          }
        }
      },
      

      I tried to use parameters with SR or without - does not matter - it didn't work, same as I tried to use parameters like

      VM = vm_id
          name_label = "NEW_VM_BY_API"
          name_description = "NEW_VM_BY_API"
          snapshot = "false"
          full_copy = "true"
          sr = sr_id
      

      it also did not help.

      What correct parameters should be to run vm.clone method via websocket json_rpc?

      1. I was able sucecssfully call method vm.copy with parameters
      $vm_copy = @{
          vm = vm_id
          name = "NEW_VM_BY_API"
          sr = 'sr_id'
      }
      

      and it worked, but how can I track process programmaticaly and how it finished?

      there're no methods for tasks, but task.cancel or task.destroy. I can query xo.getAllObjects with filter "task", but it returns only pending tasks and just failed ones (and for single copy task there're two tasks in output. very similar) As soon as task completes succesfully - it disappears from getAllObjects. And even if it fails - it also disappeares from there but after some time. Why there're no info about successfully completed tasks? Where can I found those logs?

      I can see more failed tasks in REST output in /rest/v0/tasks (no sign of successfull ones either), but I cannot find correspondence between task GUID in json_rpc and task id that some type of base_encode in REST so it is very hard to determine that deploy completed successfully
      I can query each failed task in /rest/v0/tasks/GUID in cycles to find mine, but it sounds awful. And if one task failed for the first time and I will do restart - it will find in REST old failed tasks with the same info, so I need to rely on something else. Timestamps?

      Not very convenient for sure.

      I feel that I am missing something and hope that you can help me automating my deploys on XCP-NG platform using powershell 5.

      all methods I have I received using ws call method 'system.getMethodsInfo'

      Here powershell code for websocket queries if you like:

      function Call-XOJsonRpc
      {
          param(
              [string]$uri,
              [string]$username,
              [string]$password,
              [string]$method,
              [hashtable]$parameters = @{}
          )
          $ct = [System.Threading.CancellationToken]::None
          $client = [System.Net.WebSockets.ClientWebSocket]::new()
      
          try {
              # Connect to WebSocket
              $client.ConnectAsync([System.Uri]$uri, $ct).Wait()
              Write-Host "Connected to XO WebSocket"
      
              function Send-JsonRpc {
                  param (
                      [string]$method,
                      [hashtable]$params = @{},
                      [int]$id
                  )
      
                  $json = @{
                      jsonrpc = "2.0"
                      method  = $method
                      params  = $params
                      id      = $id
                  } | ConvertTo-Json -Depth 5 -Compress
      
                  $bytes = [System.Text.Encoding]::UTF8.GetBytes($json)
                  $segment = [System.ArraySegment[byte]]::new($bytes)
                  $client.SendAsync($segment, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $ct).wait()
              }
      
              function Receive-JsonRpc {
                  $buffer = New-Object byte[] 8192
                  $segment = [System.ArraySegment[byte]]::new($buffer)
                  $textBuilder = New-Object System.Text.StringBuilder
      
                  do {
                      $result = $client.ReceiveAsync($segment, $ct).Result
                      $chunk = [System.Text.Encoding]::UTF8.GetString($buffer, 0, $result.Count)
                      $null = $textBuilder.Append($chunk)
                  } while (-not $result.EndOfMessage)
      
                  return $textBuilder.ToString()
              }
      
              # 2. session.signIn
              Send-JsonRpc -method "session.signIn" -params @{ username = $username; password = $password } -id 1
              $loginResponse = Receive-JsonRpc | ConvertFrom-Json
              if ($loginResponse.error) {
                  throw "Login failed: $($loginResponse.error.message)"
              }
      
              Write-Host "Logged in to XO WebSocket successfully"
      
              Send-JsonRpc -method $method -id 2 -params $parameters 
              $objResponse = (Receive-JsonRpc).tolower()| ConvertFrom-Json
      
              return $objResponse
      
          } catch {
              Write-Error "Error: $_"
          } finally {
              if ($client.State -eq [System.Net.WebSockets.WebSocketState]::Open) {
                  
                  $result = $client.CloseAsync([System.Net.WebSockets.WebSocketCloseStatus]::Empty, "", $ct)
                  Start-Sleep -Seconds 5
                  if ($client.State -eq [System.Net.WebSockets.WebSocketState]::Open)
                  {
                      throw "Cannot close websocket connection"
                  }
              }
              $client.Dispose()
          }
      
      }
      

      example

      $username = "yourusername"
      $password = 'yourpassword'
      
      $task_info = @{
          filter = @{
              type = "task"
          }
      }
      
      $result_tasks = Call-XOJsonRpc -uri 'ws://URL/api/' -username $username  -password $password -method "xo.getAllObjects" -parameters $task_info
      
      output like:
      
      ($result_tasks.result.PSObject.Properties.Value |ForEach-Object { $_ | ConvertTo-Json -Depth 5 })|ConvertFrom-Json
      
      1 Reply Last reply Reply Quote 0
      • olivierlambertO Offline
        olivierlambert Vates 🪐 Co-Founder CEO
        last edited by

        Ping @Team-DevOps

        1 Reply Last reply Reply Quote 0
        • First post
          Last post