ngine-io / ansible-collection-cloudstack

CloudStack Ansible Collections
https://galaxy.ansible.com/ngine_io/cloudstack
GNU General Public License v3.0
20 stars 26 forks source link

Parameter to specify region when creating a VM instance #128

Closed rakesh-p closed 1 month ago

rakesh-p commented 1 month ago

Hi,

Is it possible to specify the region when using ngine_io.cloudstack.cs_instance module please? I am using a cloud provider but service offering names Iis NOT unique across regions. This means I am not able to create a VM instance using the service offering name. I need to use the service offering ID to make it work. See below.

After setting the ENV variables CLOUDSTACK_KEY, CLOUDSTACK_SECRET and CLOUDSTACK_ENDPOINT, I ran the following playbook

Ansible playbook:

---
- name: Create a CloudStack VM instance
  hosts: localhost
  gather_facts: no
  collections:
    - ngine_io.cloudstack
  tasks:
    - name: Create a VM instance from an existing template
      ngine_io.cloudstack.cs_instance:
        name: ansible-vm-1
        template: ec-rocky-9.4-base
        zone: New York (ESX)
        # service_offering: 2927c1c1-7889-47f9-b987-644cba37618c
        service_offering: 2048-1
        networks:
          - Network Local ECMWF 3

Setting service_offering to 2927c1c1-7889-47f9-b987-644cba37618c works well and the VM ius created. But if I change the service_offering value to 2048-1 (which is name of the service offering as per the list serviceoffering output), i get the error that the service offering not found (which is correct because the service offering ID in the error message belongs to another region which does not contain NewYork zone)

Error: HTTP 431 error 'errortext': 'Unable to execute API command deployvirtualmachine due to invalid value. Invalid parameter serviceofferingid'

Should this be considered as a feature request to add a region parameter or is there another solution please?

Thanks

rvalle commented 1 month ago

@rakesh-p I think you have to create the offerings per region. I can see that I use the same offering across zones without problems, but I don't think that works across regions.

luckily you can automate offering creation with cs_service_offering ...

resmo commented 1 month ago

Sorry for dump question, I am a bit confused but if I remember correctly, a region has its own api endpoint and keys right? (there aren't any federation yet, right?)

so wouldn't switching endpoints solve this issue?

---
- name: Create a CloudStack VM instance
  hosts: localhost
  gather_facts: no
  collections:
    - ngine_io.cloudstack
  tasks:
    - name: Create a VM instance from an existing template
      ngine_io.cloudstack.cs_instance:
        name: ansible-vm-1
        template: ec-rocky-9.4-base
        zone: New York (ESX)
        # service_offering: 2927c1c1-7889-47f9-b987-644cba37618c
        service_offering: 2048-1
        api_url: "{{ cloudstack_api_url }}"
        api_key: "{{ cloudstack_api_key }}"
        api_secret: "{{ cloudstack_api_secret }}"
        networks:
          - Network Local ECMWF 3

usually you organize these vars in group_vars/region-xyz and put these instances in the corresponding ansible inventory group in your inventory.

resmo commented 1 month ago

Probably helpful for inspiration is this role I created for exoscale cloud. (they used to use cloudstack underneath, but that had changed, so it's outdated). Please have a look at the readme, especially the last parts.

As a result, I wouldn't recommend to have hosts: localhost but use a group of hosts and let ansible loop over it, e.g. hosts: cloud_instances and use delegate_to: localhost to prevent ansible trying to ssh into the VM you want to create. I would organize different regions using different ansible inventories and create a region group_var on top tree of each inventory.

https://github.com/ngine-io/ansible-role-exoscale

rakesh-p commented 1 month ago

@rakesh-p I think you have to create the offerings per region. I can see that I use the same offering across zones without problems, but I don't think that works across regions.

luckily you can automate offering creation with cs_service_offering ...

thanks for your reply. i was using the service offerings that were listed and never thought about creating one myself. i will try this and reply here.

rakesh-p commented 1 month ago

Sorry for dump question, I am a bit confused but if I remember correctly, a region has its own api endpoint and keys right? (there aren't any federation yet, right?)

so wouldn't switching endpoints solve this issue?

---
- name: Create a CloudStack VM instance
  hosts: localhost
  gather_facts: no
  collections:
    - ngine_io.cloudstack
  tasks:
    - name: Create a VM instance from an existing template
      ngine_io.cloudstack.cs_instance:
        name: ansible-vm-1
        template: ec-rocky-9.4-base
        zone: New York (ESX)
        # service_offering: 2927c1c1-7889-47f9-b987-644cba37618c
        service_offering: 2048-1
        api_url: "{{ cloudstack_api_url }}"
        api_key: "{{ cloudstack_api_key }}"
        api_secret: "{{ cloudstack_api_secret }}"
        networks:
          - Network Local ECMWF 3

usually you organize these vars in group_vars/region-xyz and put these instances in the corresponding ansible inventory group in your inventory.

The cloud provider has only one API endpoint. customer support confirmed this via chat.

This means i am going to create an ansible task to fetch the ID for a service_offering name in the given region and use it to create VM. Thanks for your input.

rakesh-p commented 1 month ago

Probably helpful for inspiration is this role I created for exoscale cloud. (they used to use cloudstack underneath, but that had changed, so it's outdated). Please have a look at the readme, especially the last parts.

As a result, I wouldn't recommend to have hosts: localhost but use a group of hosts and let ansible loop over it, e.g. hosts: cloud_instances and use delegate_to: localhost to prevent ansible trying to ssh into the VM you want to create. I would organize different regions using different ansible inventories and create a region group_var on top tree of each inventory.

https://github.com/ngine-io/ansible-role-exoscale

@resmo thanks for the ansible role. looks like i can reuse most of it.

resmo commented 1 month ago

The cloud provider has only one API endpoint. customer support confirmed this via chat.

May you share the cloud provider's name (in case it's a public one)?

  • "We have just one single API endpoint that sends requests to all three regions"

This info is a bit weird. so they might have a one api for all regions (could it be they are just zones?) but they somehow have to find out which region this request belongs to or they map the zone to a region internally. So maybe it is all about the zoneid missing in the query for listing the serviceofferings:

https://github.com/ngine-io/ansible-collection-cloudstack/blob/58075b9831c5cc879c8c5cf3fa357a06dd4d2d6b/plugins/modules/cs_instance.py#L463

  • "You can use the service offering ID in ansible I believe instead of the name. Each offering has a unique ID"

This means i am going to create an ansible task to fetch the ID for a service_offering name in the given region and use it to create VM. Thanks for your input.

This would be a workaround, but it should be an easy fix nevertheless.

rakesh-p commented 1 month ago

The cloud provider has only one API endpoint. customer support confirmed this via chat.

May you share the cloud provider's name (in case it's a public one)?

  • "We have just one single API endpoint that sends requests to all three regions"

This info is a bit weird. so they might have a one api for all regions (could it be they are just zones?) but they somehow have to find out which region this request belongs to or they map the zone to a region internally. So maybe it is all about the zoneid missing in the query for listing the serviceofferings:

https://github.com/ngine-io/ansible-collection-cloudstack/blob/58075b9831c5cc879c8c5cf3fa357a06dd4d2d6b/plugins/modules/cs_instance.py#L463

  • "You can use the service offering ID in ansible I believe instead of the name. Each offering has a unique ID"

This means i am going to create an ansible task to fetch the ID for a service_offering name in the given region and use it to create VM. Thanks for your input.

This would be a workaround, but it should be an easy fix nevertheless.

the provider is GTT https://vdc.gtt.net/doc/vdc-api/introduction-api/vdc-regions this link takes to section where it says they support a special parameter called region.

with the cloudmonkey CLI, if i run list serviceofferings region=usa I get response that includes all regions but if i run list zones region=usa the response includes only zones for the USA region

resmo commented 1 month ago

hmm... I see.

So this is a custom API indeed, and a bit unfortunate. I will break many cloudstack integrations (including this ansible one).

To avoid it, they would have to change the endpoints to distinguish between regions, e.g use either one of:

And parse the region as they do with the region param. I don't know how successful it is but I would talk to them again about this issue and this suggestion.

(this solution wouldn't be a difficult,nor risky nor huge change and straight forward to implement imho)

rakesh-p commented 1 month ago

@resmo thanks again. I will close this issue and will discuss with the provider..