GenerateNodeVNCURL creates a noVNC shell URL for the given node.
(nodeName string)
| 343 | |
| 344 | // GenerateNodeVNCURL creates a noVNC shell URL for the given node. |
| 345 | func (c *Client) GenerateNodeVNCURL(nodeName string) (string, error) { |
| 346 | c.logger.Info("Generating VNC shell URL for node: %s", nodeName) |
| 347 | |
| 348 | // Get VNC shell proxy details |
| 349 | c.logger.Debug("Requesting VNC shell proxy for URL generation for node %s", nodeName) |
| 350 | |
| 351 | proxy, err := c.GetNodeVNCShell(nodeName) |
| 352 | if err != nil { |
| 353 | c.logger.Error("Failed to get VNC shell proxy for URL generation for node %s: %v", nodeName, err) |
| 354 | |
| 355 | return "", err |
| 356 | } |
| 357 | |
| 358 | // Extract server details from base URL |
| 359 | serverURL := strings.TrimSuffix(c.baseURL, "/api2/json") |
| 360 | c.logger.Debug("Base server URL for node %s: %s", nodeName, serverURL) |
| 361 | |
| 362 | // URL encode the VNC ticket (critical for avoiding 401 errors) |
| 363 | encodedTicket := url.QueryEscape(proxy.Ticket) |
| 364 | c.logger.Debug("VNC shell ticket encoded for node %s (original length: %d, encoded length: %d)", |
| 365 | nodeName, len(proxy.Ticket), len(encodedTicket)) |
| 366 | |
| 367 | // Build the noVNC shell URL using the working format from the forum post |
| 368 | // Format: https://server:8006/?console=shell&novnc=1&node=nodename&resize=off&cmd=&vncticket=encoded_ticket |
| 369 | vncURL := fmt.Sprintf("%s/?console=shell&novnc=1&node=%s&resize=off&cmd=&vncticket=%s", |
| 370 | serverURL, nodeName, encodedTicket) |
| 371 | |
| 372 | c.logger.Info("VNC shell URL generated successfully for node %s", nodeName) |
| 373 | c.logger.Debug("VNC shell URL for node %s: %s", nodeName, vncURL) |
| 374 | |
| 375 | return vncURL, nil |
| 376 | } |
| 377 | |
| 378 | // GetNodeStorages retrieves all storages available on a specific node. |
| 379 | func (c *Client) GetNodeStorages(nodeName string) ([]*Storage, error) { |
no test coverage detected