VCF 4.0 on VxRail – externalize vCenter with Ansible
In the previous post I showed how to automate initial VxRail cluster configuration and deployment with Ansible. In this post, which is the next of a number of posts on VCF 4 on VxRail I will show you how to externalize embedded vCenter.
As you know, by default, VMware vCenter server is internal to the VxRail cluster. But as per the VVD guidelines, it needs to be external for VCF 4.0.0 on VxRail (starting with Cloud Foundation 4.0.1, externalization of VMware vCenter server is automated during the bring-up process).

So let’s automate this step. We will use ‘rest/vxm/v1/vc/mode’ and /v1/requests’ APIs.
Vars used in the role task:
externalizeVcenterApiUrl: rest/vxm/v1/vc/mode
checkRequestStatusApiUrl: /v1/requests
vCenterUsername: administrator@vsphere.local
vCenterPassword: SoM3Pa$$w0Rd
As a first step, let’s check what is the current vCenter mode:
- name: Get current vCenter mode
uri:
url: "{{ vxmUrl }}/{{ externalizeVcenterApiUrl }}"
method: GET
headers:
Content-Type: application/json
# Authorization: Basic {{ auth }}
force_basic_auth: yes
user: "{{ vCenterUsername }}"
password: "{{ vCenterPassword }}"
validate_certs: no
return_content: yes
register: getVcenterMode
- name : Debug - Get current vCenter mode
debug:
msg: "{{ getVcenterMode.json.vc_mode }}"

As you can see above, it’s EMBEDDED. So let’s use this as a condition for next step- externalize vCenter. As a response we will get a request ID.
- name: Externalize vCenter
uri:
url: "{{ vxmUrl }}/{{ externalizeVcenterApiUrl }}"
method: PATCH
headers:
Content-Type: application/json
force_basic_auth: yes
user: "{{ vCenterUsername }}"
password: "{{ vCenterPassword }}"
validate_certs: no
return_content: yes
body_format: json
status_code: 202
body:
psc_mode: EMBEDDED
vc_admin_user:
password: "{{ vCenterPassword }}"
username: "{{ vCenterUsername }}"
vc_mode: EXTERNAL
register: externalizeVcenter
when: "getVcenterMode.json.vc_mode == 'EMBEDDED'"
- name : Debug - Externalize vCenter
debug:
msg: "{{ externalizeVcenter.json.request_id }}"
If you switch to vSphere Client, you should see two completed tasks: ‘Run VC Conversion’ and Initiate guest OS reboot’.


And let’s use Request ID ‘externalizeVcenter.json.request_id’ (in my case it’s ‘SBI_2’) to check externalize vCenter task status. The task will finish when the status is COMPLETED. And as a last step we will check vCenter mode after convertion.
- name: Check request status
uri:
url: "{{ vxmUrl }}/{{ checkRequestStatusApiUrl }}/{{ externalizeVcenter.json.request_id }}"
method: GET
headers:
Content-Type: application/json
force_basic_auth: yes
user: "{{ vCenterUsername }}"
password: "{{ vCenterPassword }}"
timeout: 300
validate_certs: no
return_content: yes
register: checkRequestStatus
until: checkRequestStatus.json.state == "COMPLETED"
retries: 100
delay: 20
- name : Debug - Check request status
debug:
msg: "{{ checkRequestStatus.json.state }}"

Quick check in Postman as a proof that all is fine:

And once again, all in one file:
---
- name: Get current vCenter mode
uri:
url: "{{ vxmUrl }}/{{ externalizeVcenterApiUrl }}"
method: GET
headers:
Content-Type: application/json
force_basic_auth: yes
user: "{{ vCenterUsername }}"
password: "{{ vCenterPassword }}"
validate_certs: no
return_content: yes
register: getVcenterMode
- name : Debug - Get current vCenter mode
debug:
msg: "{{ getVcenterMode.json.vc_mode }}"
- name: Externalize vCenter
uri:
url: "{{ vxmUrl }}/{{ externalizeVcenterApiUrl }}"
method: PATCH
headers:
Content-Type: application/json
force_basic_auth: yes
user: "{{ vCenterUsername }}"
password: "{{ vCenterPassword }}"
validate_certs: no
return_content: yes
body_format: json
status_code: 202
body:
psc_mode: EMBEDDED
vc_admin_user:
password: "{{ vCenterPassword }}"
username: "{{ vCenterUsername }}"
vc_mode: EXTERNAL
register: externalizeVcenter
when: "getVcenterMode.json.vc_mode == 'EMBEDDED'"
- name : Debug - Externalize vCenter
debug:
msg: "{{ externalizeVcenter.json.request_id }}"
- name: Check request status
uri:
url: "{{ vxmUrl }}/{{ checkRequestStatusApiUrl }}/{{ externalizeVcenter.json.request_id }}"
method: GET
headers:
Content-Type: application/json
force_basic_auth: yes
user: "{{ vCenterUsername }}"
password: "{{ vCenterPassword }}"
timeout: 300
validate_certs: no
return_content: yes
register: checkRequestStatus
until: checkRequestStatus.json.state == "COMPLETED"
retries: 100
delay: 20
- name : Debug - Check request status
debug:
msg: "{{ checkRequestStatus.json.state }}"
- name: Get vCenter mode after conversion
uri:
url: "{{ vxmUrl }}/{{ externalizeVcenterApiUrl }}"
method: GET
headers:
Content-Type: application/json
# Authorization: Basic {{ auth }}
force_basic_auth: yes
user: "{{ vCenterUsername }}"
password: "{{ vCenterPassword }}"
validate_certs: no
return_content: yes
register: getNewVcenterMode
- name : Debug - Get current vCenter mode
debug:
msg: "Current vCenter mode is:{{ getNewVcenterMode.json.vc_mode }}"
- name: "vCenter externalize task completed"
debug:
msg: "vCenter externalize task completed."
when: "checkRequestStatus.json.state == 'COMPLETED'"
And pretty much that’s it. In next post i will show you how to automate changing vCenter components names: DC, cluster, vDS and vSAN datastore before VCF bring-up.