VCF 4.0 on VxRail 7.0.000 – initial cluster configuration and deployment with Ansible

A few weeks ago VxRail 7.0.10 was released and one of the many new features is that provides enhanced workflows and an API to support automation of initial cluster configuration and deployment. There is a great Dell EMC VxRail RESTful API Cookbook and it provides sample VxRail RESTful API workflows. You can find there even ready to use ansible playbooks. Good job VxRail team!!!.

But as you can see, it’s for VxRail 7.0.010 only. And what about 7.0.000? Let’s try to find a way to automate VxRail 7.0.000 cluster deployment by our own;)

NOTE!!! Please remember that i used private API.

Let’s start from vars:

vxmUrl: https://vxmFQDN 
getUnconfiguredNodesUiApiUrl: vxRailHost?configurationState=UNCONFIGURED 
validateVxrailInitialConfigApiUrl: v2/data/validate/initial
saveVxrailInitialConfigApiUrl: data/configuration/save
checkInitialProgressApiUrl: v2/data/validate/initial/progress
checkBuildProgressApiUrl: v2/data/configuration/progress
checkRequestStatusApiUrl: v1/requests
applyVxrailNetworkConfigApiUrl: network/static/apply
applyVxrailDataConfigApiUrl: data/configuration/apply

Ok, so first we need to discover all unconfigured hosts. Discovering can take around 1 min and that’s why i used ‘until’.

- name: Get all unconfigured nodes
  uri:
   url: "{{ vxmUrl }}/{{ getUnconfiguredNodesUiApiUrl }}"
   method: GET
   validate_certs: no
   return_content: yes
   body_format: json
  register: getUnconfiguredNodes
  until: getUnconfiguredNodes.json[0].nodeVersionInfo is defined
  retries: 100
  delay: 10

Extract unconfigured hosts:

- name: "Extract Unconfigured hosts"
  set_fact:
    unconfiguredHosts: "{{ getUnconfiguredNodes.json |  selectattr('configurationState','equalto',('unconfigured')) | map(attribute='assetTag') | list }}"
    
- name: "Debug -Extract Unconfigured hosts"
  debug:
    msg: "{{ unconfiguredHosts }}"

Next step is to extract VxRail version and build and Appliance ID. It’s needed to next request body.

- name: "Extract VxRail version"
  set_fact:
     vxrailVersion: "{{ getUnconfiguredNodes.json[0].nodeVersionInfo.version }}"
     
- name: "Extract VxRail build"
  set_fact:
     vxrailBuild: "{{ getUnconfiguredNodes.json[0].nodeVersionInfo.build }}"
   
- name: "Extract Appliance ID"
  set_fact:
     applianceId: "{{ getUnconfiguredNodes.json[0].marvinId.applianceId }}"
        
- name: Show VxRail Appliance ID
  debug:
    msg: "{{ applianceId }}"

- name: Show VxRail version-build
  debug:
    msg: "{{ vxrailVersion }}-{{ vxrailBuild }}"

And now we can validate our cluster config. Please remember that you have to provide ‘type’ of validation, ‘portgroupBinding and nicProfile.

Possible values for type’: ‘thorough’ or ‘cursory’. It’s a first validation so we need to use ‘thorough’.

‘portgroupBinding’: you can choose ‘EARLY_BINDING’ or ‘EPHEMERAL’.

‘nicProfile’: ‘TWO_HIGH_SPEED’ (2x10GbE or 2x25GbE), ‘FOUR_HIGH_SPEED’ (4x10GbE) or ‘FOUR_LOW_SPEED’ (4x1GbE)

- name: Validate Initial VxRail Cluster Config
  uri:
   url: "{{ vxmUrl }}/{{ validateVxrailInitialConfigApiUrl }}"
   method: POST
   validate_certs: no
   return_content: yes
   body_format: json
   register: validateConfig
   timeout: 300
   body: 
     type: thorough
     parameters:
       version: "{{ vxrailVersion }}-{{ vxrailBuild }}"
       network:
         dhcp: false
         hosts:
           management:
             pools:
             - minIp: ''
               maxIp: ''
             netmask: 255.255.255.0
             gateway: 172.22.16.1
             vlanId: '80'
             customizeIps:
             - ip: 172.22.16.101
             - ip: 172.22.16.102
             - ip: 172.22.16.103
             - ip: 172.22.16.104
           vsan:
             pools:
             - minIp: 172.22.19.101
               maxIp: 172.22.19.104
             netmask: 255.255.255.0
             vlanId: '83'
           vmotion:
             pools:
             - minIp: 172.22.18.101
               maxIp: 172.22.18.104
             netmask: 255.255.255.0
             vlanId: '82'
           vm:
           - name: VM Network
             vlanId: '81'
           witness:
             pools:
             - minIp: ''
               maxIp: ''
             netmask: ''
             gateway: ''
             vlanId: ''
         vcenter:
           ip: 172.22.16.20
         psc:
           ip: ''
         evorail:
           ip: 172.22.16.6
         portgroupBinding: EPHEMERAL 
       hostnames:
         customizeHostnames:
         - hostname: "{{ hostname1 }}"
         - hostname: "{{ hostname2 }}"
         - hostname: "{{ hostname3 }}"
         - hostname: "{{ hostname4 }}"
         hosts:
           prefix: gre02mgt
           separator: ''
           iterator: NUMERIC_NNN
           offset: ''
           postfix: ''
         vcenter: gre02vcs001
         evorail: gre02vxm001
         psc: ''
         pscSite: Default-First-Site
         tld: "{{ activeDirectory.domainName }}"
       usernames:
         vcUsername: ''
       accounts:
         nonHostAccounts:
           isShared: true
           sharedAccount:
             username: vxmadministrator
             password: "{{ vCenterPassword }}"
             passwordConfirm: "{{ vCenterPassword }}"
           vcRootAccount:
             username: root
             password: ''
             passwordConfirm: ''
           vcAdministratorAccount:
             username: "{{ vCenterUsername }}"
             password: ''
             passwordConfirm: ''
           vcManagementAccount:
             username: ''
             password: ''
             passwordConfirm: ''
           pscRootAccount:
             username: ''
             password: ''
             passwordConfirm: ''
           vxRailManagerRootAccount:
             username: root
             password: ''
             passwordConfirm: ''
           vxRailManagerServiceAccount:
             username: mystic
             password: "{{ vCenterPassword }}{{ vCenterPassword }}"
             passwordConfirm: "{{ vCenterPassword }}{{ vCenterPassword }}"
           logInsightRootAccount:
             username: root
             password: ''
             passwordConfirm: ''
           logInsightAdminAccount:
             username: admin
             password: ''
             passwordConfirm: ''
         hostAccounts:
           isShared: true
           sharedAccount:
             rootAccount:
               username: root
               password: "{{ vCenterPassword }}"
               passwordConfirm: "{{ vCenterPassword }}"
             managementAccount:
               username: administrator
               password: "{{ vCenterPassword }}"
               passwordConfirm: "{{ vCenterPassword }}"
           separatedAccounts:
           - hostname: "{{ hostname1 }}.{{ activeDirectory.domainName }}"
             rootAccount:
               username: root
               password: ''
               passwordConfirm: ''
             managementAccount:
               username: ''
               password: ''
               passwordConfirm: ''
           - hostname: "{{ hostname2 }}.{{ activeDirectory.domainName }}"
             rootAccount:
               username: root
               password: ''
               passwordConfirm: ''
             managementAccount:
               username: ''
               password: ''
               passwordConfirm: ''
           - hostname: "{{ hostname3 }}.{{ activeDirectory.domainName }}"
             rootAccount:
               username: root
               password: ''
               passwordConfirm: ''
             managementAccount:
               username: ''
               password: ''
               passwordConfirm: ''
           - hostname: "{{ hostname4 }}.{{ activeDirectory.domainName }}"
             rootAccount:
               username: root
               password: ''
               passwordConfirm: ''
             managementAccount:
               username: ''
               password: ''
               passwordConfirm: ''
       global:
         ntpServerCSV: 172.22.16.24
         syslogServerCSV: ''
         dnsServerCSV: 172.22.16.24
         proxyServer: ''
         proxyUsername: ''
         proxyPassword: ''
         loginsightHostname: ''
         loginsightServer: ''
         proxyPort: ''
         logging: NONE
         joinVC: false
         joinSSO: false
         roboCluster: false
         customizeNetwork: true
         nicProfile: "{{ nicProfile }}"
       externalVC:
         nonEmbeddedMode: false
         psc: ''
         vcenter: ''
         vcUsername: ''
         vcPassword: ''
         managementUsername: ''
         managementPassword: ''
         datacenterName: ''
         clusterName: ''
       existingSSODomain:
         server: ''
         port: 443
         username: "{{ vCenterUsername }}"
         password: ''
       witnessNode:
         managementIp: ''
         witnessIp: ''
         gateway: ''
         netmask: ''
         username: root
         password: ''
       vendor:
         ovfs: []
       vmwSolution:
         ovfs: []
       expectedMarvinIds:
         marvinIds:
         - applianceId: "{{ applianceId }}"
           totalSupportedNodes: 4
           position: 1
           primaryNode: true
         - applianceId: "{{ applianceId }}"
           totalSupportedNodes: 4
           position: 2
           primaryNode: false
         - applianceId: "{{ applianceId }}"
           totalSupportedNodes: 4
           position: 3
           primaryNode: false
         - applianceId: "{{ applianceId }}"
           totalSupportedNodes: 4
           position: 4
           primaryNode: false

Validation will take few minutes. In case of any failures, all failed tasks will be showed on screen and task will fail:

- name: Check progress
  uri:
   url: "{{ vxmUrl }}/{{ checkProgressApiUrl }}"
   method: GET
   validate_certs: no
   return_content: yes
  register: checkProgress

- name: "Extract Failed tasks"
  set_fact:
    failedTask: "{{ checkProgress.json.validatorProgresses |  selectattr('status','equalto',('FAILED')) | map(attribute='description') | list }}"

- name: "Failure notice"
  fail:
    msg: "Validation error: {{ checkProgress.json.validatorProgresses | selectattr('status','equalto',('FAILED')) | map(attribute='description') | list }}"
  when: "checkProgress.json.validationErrorsCount != 0"

If validation task is completed with no errors, play will continue.

- name: "Validation succeded"
  debug:
    msg: "Validation succeded. No erors found."
  when: "checkProgress.json.validationErrorsCount == 0"

Moving forward, when validation is done we need to save VxRail cluster configuration. The request body is almost the same as in aboce request for validation.

- name: Save config
  uri:
    url: "{{ vxmUrl }}/{{ saveVxrailInitialConfigApiUrl }}"
    method: POST
    validate_certs: no
    return_content: yes
    body_format: json
    body: 
      version: "{{ vxrailVersion }}-{{ vxrailBuild }}"
      network:
        dhcp: false
        hosts:
          management:
            pools:
            - minIp: ''
              maxIp: ''
            netmask: 255.255.255.0
            gateway: 172.22.16.1
            vlanId: '80'
            customizeIps:
            - ip: 172.22.16.101
            - ip: 172.22.16.102
            - ip: 172.22.16.103
            - ip: 172.22.16.104
          vsan:
            pools:
            - minIp: 172.22.19.101
              maxIp: 172.22.19.104
            netmask: 255.255.255.0
            vlanId: '83'
          vmotion:
            pools:
            - minIp: 172.22.18.101
              maxIp: 172.22.18.104
            netmask: 255.255.255.0
            vlanId: '82'
          vm:
          - name: VM Network
            vlanId: '81'
          witness:
            pools:
            - minIp: ''
              maxIp: ''
            netmask: ''
            gateway: ''
            vlanId: ''
        vcenter:
          ip: 172.22.16.20
        psc:
          ip: ''
        evorail:
          ip: 172.22.16.6
        portgroupBinding: EPHEMERAL
      hostnames:
        customizeHostnames:
        - hostname: "{{ hostname1 }}"
        - hostname: "{{ hostname2 }}"
        - hostname: "{{ hostname3 }}"
        - hostname: "{{ hostname4 }}"
        hosts:
          prefix: gre02mgt
          separator: ''
          iterator: NUMERIC_NNN
          offset: ''
          postfix: ''
        vcenter: gre02vcs001
        evorail: gre02vxm001
        psc: ''
        pscSite: Default-First-Site
        tld: "{{ activeDirectory.domainName }}"
      usernames:
        vcUsername: ''
      accounts:
        nonHostAccounts:
          isShared: true
          sharedAccount:
            username: vxmadministrator
            password: "{{ vCenterPassword }}"
            passwordConfirm: "{{ vCenterPassword }}"
          vcRootAccount:
            username: root
            password: ''
            passwordConfirm: ''
          vcAdministratorAccount:
            username: "{{ vCenterUsername }}"
            password: ''
            passwordConfirm: ''
          vcManagementAccount:
            username: ''
            password: ''
            passwordConfirm: ''
          pscRootAccount:
            username: ''
            password: ''
            passwordConfirm: ''
          vxRailManagerRootAccount:
            username: root
            password: ''
            passwordConfirm: ''
          vxRailManagerServiceAccount:
            username: mystic
            password: "{{ vCenterPassword }}{{ vCenterPassword }}"
            passwordConfirm: "{{ vCenterPassword }}{{ vCenterPassword }}"
          logInsightRootAccount:
            username: root
            password: ''
            passwordConfirm: ''
          logInsightAdminAccount:
            username: admin
            password: ''
            passwordConfirm: ''
        hostAccounts:
          isShared: true
          sharedAccount:
            rootAccount:
              username: root
              password: "{{ vCenterPassword }}"
              passwordConfirm: "{{ vCenterPassword }}"
            managementAccount:
              username: administrator
              password: "{{ vCenterPassword }}"
              passwordConfirm: "{{ vCenterPassword }}"
          separatedAccounts:
          - hostname: "{{ hostname1 }}.{{ activeDirectory.domainName }}"
            rootAccount:
              username: root
              password: ''
              passwordConfirm: ''
            managementAccount:
              username: ''
              password: ''
              passwordConfirm: ''
          - hostname: "{{ hostname2 }}.{{ activeDirectory.domainName }}"
            rootAccount:
              username: root
              password: ''
              passwordConfirm: ''
            managementAccount:
              username: ''
              password: ''
              passwordConfirm: ''
          - hostname: "{{ hostname3 }}.{{ activeDirectory.domainName }}"
            rootAccount:
              username: root
              password: ''
              passwordConfirm: ''
            managementAccount:
              username: ''
              password: ''
              passwordConfirm: ''
          - hostname: "{{ hostname4 }}.{{ activeDirectory.domainName }}"
            rootAccount:
              username: root
              password: ''
              passwordConfirm: ''
            managementAccount:
              username: ''
              password: ''
              passwordConfirm: ''
      global:
        ntpServerCSV: 172.22.16.24
        syslogServerCSV: ''
        dnsServerCSV: 172.22.16.24
        proxyServer: ''
        proxyUsername: ''
        proxyPassword: ''
        loginsightHostname: ''
        loginsightServer: ''
        proxyPort: ''
        logging: NONE
        joinVC: false
        joinSSO: false
        roboCluster: false
        customizeNetwork: true
        nicProfile: "{{ nicProfile }}"
      externalVC:
        nonEmbeddedMode: false
        psc: ''
        vcenter: ''
        vcUsername: ''
        vcPassword: ''
        managementUsername: ''
        managementPassword: ''
        datacenterName: ''
        clusterName: ''
      existingSSODomain:
        server: ''
        port: 443
        username: "{{ vCenterUsername }}"
        password: ''
      witnessNode:
        managementIp: ''
        witnessIp: ''
        gateway: ''
        netmask: ''
        username: root
        password: ''
      vendor:
        ovfs: []
      vmwSolution:
        ovfs: []
      expectedMarvinIds:
        marvinIds:
        - applianceId: "{{ applianceId }}"
          totalSupportedNodes: 4
          position: 1
          primaryNode: true
        - applianceId: "{{ applianceId }}"
          totalSupportedNodes: 4
          position: 2
          primaryNode: false
        - applianceId: "{{ applianceId }}"
          totalSupportedNodes: 4
          position: 3
          primaryNode: false
        - applianceId: "{{ applianceId }}"
          totalSupportedNodes: 4
          position: 4
          primaryNode: false
  register: saveConfig
         
- name: Show save config task status
  debug:
    msg: "Config save: {{ saveConfig.json.success }}" 

And now it’s time to apply config.

- name: Apply network config
  uri:
   url: "{{ vxmUrl }}/{{ applyVxrailNetworkConfigApiUrl }}"
   method: POST
   validate_certs: no
   return_content: yes
   body_format: json
   register: applyNetworkConfig
   status_code: 200
   timeout: 300
   body: 
     dhcp: false
     hosts:
       management:
         pools:
         - minIp: ''
           maxIp: ''
         netmask: 255.255.255.0
         gateway: 172.22.16.1
         vlanId: '80'
         customizeIps:
         - ip: 172.22.16.101
         - ip: 172.22.16.102
         - ip: 172.22.16.103
         - ip: 172.22.16.104
       vsan:
         pools:
         - minIp: 172.22.19.101
           maxIp: 172.22.19.104
         netmask: 255.255.255.0
         vlanId: '83'
       vmotion:
         pools:
         - minIp: 172.22.18.101
           maxIp: 172.22.18.104
         netmask: 255.255.255.0
         vlanId: '82'
       vm:
       - name: VM Network
         vlanId: '81'
       witness:
         pools:
         - minIp: ''
           maxIp: ''
         netmask: ''
         gateway: ''
         vlanId: ''
     vcenter:
       ip: 172.22.16.20
     psc:
       ip: ''
     evorail:
       ip: 172.22.16.6
     portgroupBinding: EPHEMERAL

- name: Apply data config
  uri:
   url: "{{ vxmUrl }}/{{ applyVxrailDataConfigApiUrl }}"
   method: POST
   validate_certs: no
   return_content: yes
   body_format: json
  register: applyDataConfig

- name: "Check deployment status"
  debug:
    msg: "Deployment status: {{ applyDataConfig.json.success }}"

Of course we should monitor deployment progress.

- name: Check VxRail cluster deployment progress
  uri:
   url: "{{ vxmUrl }}/{{ checkBuildProgressApiUrl }}"
   method: GET
   validate_certs: no
   return_content: yes
  register: checkBuildProgress
  until: checkBuildProgress.json.status == "COMPLETED"
  retries: 60
  delay: 60
  
- name: "Check deployment status"
  debug:
    msg: "VxRail cluster build status:{{ checkBuildProgress.json.status }}"

And…Hooray!

And once again, all tasks in one file:

---
- name: Get all unconfigured nodes
  uri:
   url: "{{ vxmUrl }}/{{ getUnconfiguredNodesUiApiUrl }}"
   method: GET
   validate_certs: no
   return_content: yes
   body_format: json
  register: getUnconfiguredNodes
  until: getUnconfiguredNodes.json[0].nodeVersionInfo is defined
  retries: 100
  delay: 10
  
- name : Debug list
  debug:
    msg: "{{ getUnconfiguredNodes.json }}"
    verbosity: 1
  
- name: "Extract Unconfigured hosts"
  set_fact:
    unconfiguredHosts: "{{ getUnconfiguredNodes.json |  selectattr('configurationState','equalto',('unconfigured')) | map(attribute='assetTag') | list }}"
    
- name: "Debug- Extract Unconfigured hosts"
  debug:
    msg: "{{ unconfiguredHosts }}"

- name: "Extract VxRail version"
  set_fact:
     vxrailVersion: "{{ getUnconfiguredNodes.json[0].nodeVersionInfo.version }}"
     
- name: "Extract VxRail build"
  set_fact:
     vxrailBuild: "{{ getUnconfiguredNodes.json[0].nodeVersionInfo.build }}"
   
- name: "Extract Appliance ID"
  set_fact:
     applianceId: "{{ getUnconfiguredNodes.json[0].marvinId.applianceId }}"
        
- name: Show VxRail Appliance ID
  debug:
    msg: "{{ applianceId }}"

- name: Show VxRail version-build
  debug:
    msg: "{{ vxrailVersion }}-{{ vxrailBuild }}"

- name: Validate Initial VxRail Cluster Config
  uri:
   url: "{{ vxmUrl }}/{{ validateVxrailInitialConfigApiUrl }}"
   method: POST
   validate_certs: no
   return_content: yes
   body_format: json
   register: validateConfig
   timeout: 300
   body: 
     type: thorough
     parameters:
       version: "{{ vxrailVersion }}-{{ vxrailBuild }}"
       network:
         dhcp: false
         hosts:
           management:
             pools:
             - minIp: ''
               maxIp: ''
             netmask: 255.255.255.0
             gateway: 172.22.16.1
             vlanId: '80'
             customizeIps:
             - ip: 172.22.16.101
             - ip: 172.22.16.102
             - ip: 172.22.16.103
             - ip: 172.22.16.104
           vsan:
             pools:
             - minIp: 172.22.19.101
               maxIp: 172.22.19.104
             netmask: 255.255.255.0
             vlanId: '83'
           vmotion:
             pools:
             - minIp: 172.22.18.101
               maxIp: 172.22.18.104
             netmask: 255.255.255.0
             vlanId: '82'
           vm:
           - name: VM Network
             vlanId: '81'
           witness:
             pools:
             - minIp: ''
               maxIp: ''
             netmask: ''
             gateway: ''
             vlanId: ''
         vcenter:
           ip: 172.22.16.20
         psc:
           ip: ''
         evorail:
           ip: 172.22.16.6
         portgroupBinding: EPHEMERAL 
       hostnames:
         customizeHostnames:
         - hostname: "{{ hostname1 }}"
         - hostname: "{{ hostname2 }}"
         - hostname: "{{ hostname3 }}"
         - hostname: "{{ hostname4 }}"
         hosts:
           prefix: gre02mgt
           separator: ''
           iterator: NUMERIC_NNN
           offset: ''
           postfix: ''
         vcenter: gre02vcs001
         evorail: gre02vxm001
         psc: ''
         pscSite: Default-First-Site
         tld: "{{ activeDirectory.domainName }}"
       usernames:
         vcUsername: ''
       accounts:
         nonHostAccounts:
           isShared: true
           sharedAccount:
             username: vxmadministrator
             password: "{{ vCenterPassword }}"
             passwordConfirm: "{{ vCenterPassword }}"
           vcRootAccount:
             username: root
             password: ''
             passwordConfirm: ''
           vcAdministratorAccount:
             username: "{{ vCenterUsername }}"
             password: ''
             passwordConfirm: ''
           vcManagementAccount:
             username: ''
             password: ''
             passwordConfirm: ''
           pscRootAccount:
             username: ''
             password: ''
             passwordConfirm: ''
           vxRailManagerRootAccount:
             username: root
             password: ''
             passwordConfirm: ''
           vxRailManagerServiceAccount:
             username: mystic
             password: "{{ vCenterPassword }}{{ vCenterPassword }}"
             passwordConfirm: "{{ vCenterPassword }}{{ vCenterPassword }}"
           logInsightRootAccount:
             username: root
             password: ''
             passwordConfirm: ''
           logInsightAdminAccount:
             username: admin
             password: ''
             passwordConfirm: ''
         hostAccounts:
           isShared: true
           sharedAccount:
             rootAccount:
               username: root
               password: "{{ vCenterPassword }}"
               passwordConfirm: "{{ vCenterPassword }}"
             managementAccount:
               username: administrator
               password: "{{ vCenterPassword }}"
               passwordConfirm: "{{ vCenterPassword }}"
           separatedAccounts:
           - hostname: "{{ hostname1 }}.{{ activeDirectory.domainName }}"
             rootAccount:
               username: root
               password: ''
               passwordConfirm: ''
             managementAccount:
               username: ''
               password: ''
               passwordConfirm: ''
           - hostname: "{{ hostname2 }}.{{ activeDirectory.domainName }}"
             rootAccount:
               username: root
               password: ''
               passwordConfirm: ''
             managementAccount:
               username: ''
               password: ''
               passwordConfirm: ''
           - hostname: "{{ hostname3 }}.{{ activeDirectory.domainName }}"
             rootAccount:
               username: root
               password: ''
               passwordConfirm: ''
             managementAccount:
               username: ''
               password: ''
               passwordConfirm: ''
           - hostname: "{{ hostname4 }}.{{ activeDirectory.domainName }}"
             rootAccount:
               username: root
               password: ''
               passwordConfirm: ''
             managementAccount:
               username: ''
               password: ''
               passwordConfirm: ''
       global:
         ntpServerCSV: 172.22.16.24
         syslogServerCSV: ''
         dnsServerCSV: 172.22.16.24
         proxyServer: ''
         proxyUsername: ''
         proxyPassword: ''
         loginsightHostname: ''
         loginsightServer: ''
         proxyPort: ''
         logging: NONE
         joinVC: false
         joinSSO: false
         roboCluster: false
         customizeNetwork: true
         nicProfile: "{{ nicProfile }}"
       externalVC:
         nonEmbeddedMode: false
         psc: ''
         vcenter: ''
         vcUsername: ''
         vcPassword: ''
         managementUsername: ''
         managementPassword: ''
         datacenterName: ''
         clusterName: ''
       existingSSODomain:
         server: ''
         port: 443
         username: "{{ vCenterUsername }}"
         password: ''
       witnessNode:
         managementIp: ''
         witnessIp: ''
         gateway: ''
         netmask: ''
         username: root
         password: ''
       vendor:
         ovfs: []
       vmwSolution:
         ovfs: []
       expectedMarvinIds:
         marvinIds:
         - applianceId: "{{ applianceId }}"
           totalSupportedNodes: 4
           position: 1
           primaryNode: true
         - applianceId: "{{ applianceId }}"
           totalSupportedNodes: 4
           position: 2
           primaryNode: false
         - applianceId: "{{ applianceId }}"
           totalSupportedNodes: 4
           position: 3
           primaryNode: false
         - applianceId: "{{ applianceId }}"
           totalSupportedNodes: 4
           position: 4
           primaryNode: false
           

- name: Check progress
  uri:
   url: "{{ vxmUrl }}/{{ checkInitialProgressApiUrl }}"
   method: GET
   validate_certs: no
   return_content: yes
  register: checkProgress

- name: "Extract Failed tasks"
  set_fact:
    failedTask: "{{ checkProgress.json.validatorProgresses |  selectattr('status','equalto',('FAILED')) | map(attribute='description') | list }}"
  
- name: "Failure notice"
  fail:
    msg: "Validation error: {{ checkProgress.json.validatorProgresses | selectattr('status','equalto',('FAILED')) | map(attribute='description') | list }}"
  when: "checkProgress.json.validationErrorsCount != 0"
  
- name: "Validation succeded"
  debug:
    msg: "Validation succeded. No erors found."
  when: "checkProgress.json.validationErrorsCount == 0"

- name: Save config
  uri:
    url: "{{ vxmUrl }}/{{ saveVxrailInitialConfigApiUrl }}"
    method: POST
    validate_certs: no
    return_content: yes
    body_format: json
    body: 
      version: "{{ vxrailVersion }}-{{ vxrailBuild }}"
      network:
        dhcp: false
        hosts:
          management:
            pools:
            - minIp: ''
              maxIp: ''
            netmask: 255.255.255.0
            gateway: 172.22.16.1
            vlanId: '80'
            customizeIps:
            - ip: 172.22.16.101
            - ip: 172.22.16.102
            - ip: 172.22.16.103
            - ip: 172.22.16.104
          vsan:
            pools:
            - minIp: 172.22.19.101
              maxIp: 172.22.19.104
            netmask: 255.255.255.0
            vlanId: '83'
          vmotion:
            pools:
            - minIp: 172.22.18.101
              maxIp: 172.22.18.104
            netmask: 255.255.255.0
            vlanId: '82'
          vm:
          - name: VM Network
            vlanId: '81'
          witness:
            pools:
            - minIp: ''
              maxIp: ''
            netmask: ''
            gateway: ''
            vlanId: ''
        vcenter:
          ip: 172.22.16.20
        psc:
          ip: ''
        evorail:
          ip: 172.22.16.6
        portgroupBinding: EPHEMERAL
      hostnames:
        customizeHostnames:
        - hostname: "{{ hostname1 }}"
        - hostname: "{{ hostname2 }}"
        - hostname: "{{ hostname3 }}"
        - hostname: "{{ hostname4 }}"
        hosts:
          prefix: gre02mgt
          separator: ''
          iterator: NUMERIC_NNN
          offset: ''
          postfix: ''
        vcenter: gre02vcs001
        evorail: gre02vxm001
        psc: ''
        pscSite: Default-First-Site
        tld: "{{ activeDirectory.domainName }}"
      usernames:
        vcUsername: ''
      accounts:
        nonHostAccounts:
          isShared: true
          sharedAccount:
            username: vxmadministrator
            password: "{{ vCenterPassword }}"
            passwordConfirm: "{{ vCenterPassword }}"
          vcRootAccount:
            username: root
            password: ''
            passwordConfirm: ''
          vcAdministratorAccount:
            username: "{{ vCenterUsername }}"
            password: ''
            passwordConfirm: ''
          vcManagementAccount:
            username: ''
            password: ''
            passwordConfirm: ''
          pscRootAccount:
            username: ''
            password: ''
            passwordConfirm: ''
          vxRailManagerRootAccount:
            username: root
            password: ''
            passwordConfirm: ''
          vxRailManagerServiceAccount:
            username: mystic
            password: "{{ vCenterPassword }}{{ vCenterPassword }}"
            passwordConfirm: "{{ vCenterPassword }}{{ vCenterPassword }}"
          logInsightRootAccount:
            username: root
            password: ''
            passwordConfirm: ''
          logInsightAdminAccount:
            username: admin
            password: ''
            passwordConfirm: ''
        hostAccounts:
          isShared: true
          sharedAccount:
            rootAccount:
              username: root
              password: "{{ vCenterPassword }}"
              passwordConfirm: "{{ vCenterPassword }}"
            managementAccount:
              username: administrator
              password: "{{ vCenterPassword }}"
              passwordConfirm: "{{ vCenterPassword }}"
          separatedAccounts:
          - hostname: "{{ hostname1 }}.{{ activeDirectory.domainName }}"
            rootAccount:
              username: root
              password: ''
              passwordConfirm: ''
            managementAccount:
              username: ''
              password: ''
              passwordConfirm: ''
          - hostname: "{{ hostname2 }}.{{ activeDirectory.domainName }}"
            rootAccount:
              username: root
              password: ''
              passwordConfirm: ''
            managementAccount:
              username: ''
              password: ''
              passwordConfirm: ''
          - hostname: "{{ hostname3 }}.{{ activeDirectory.domainName }}"
            rootAccount:
              username: root
              password: ''
              passwordConfirm: ''
            managementAccount:
              username: ''
              password: ''
              passwordConfirm: ''
          - hostname: "{{ hostname4 }}.{{ activeDirectory.domainName }}"
            rootAccount:
              username: root
              password: ''
              passwordConfirm: ''
            managementAccount:
              username: ''
              password: ''
              passwordConfirm: ''
      global:
        ntpServerCSV: 172.22.16.24
        syslogServerCSV: ''
        dnsServerCSV: 172.22.16.24
        proxyServer: ''
        proxyUsername: ''
        proxyPassword: ''
        loginsightHostname: ''
        loginsightServer: ''
        proxyPort: ''
        logging: NONE
        joinVC: false
        joinSSO: false
        roboCluster: false
        customizeNetwork: true
        nicProfile: "{{ nicProfile }}"
      externalVC:
        nonEmbeddedMode: false
        psc: ''
        vcenter: ''
        vcUsername: ''
        vcPassword: ''
        managementUsername: ''
        managementPassword: ''
        datacenterName: ''
        clusterName: ''
      existingSSODomain:
        server: ''
        port: 443
        username: "{{ vCenterUsername }}"
        password: ''
      witnessNode:
        managementIp: ''
        witnessIp: ''
        gateway: ''
        netmask: ''
        username: root
        password: ''
      vendor:
        ovfs: []
      vmwSolution:
        ovfs: []
      expectedMarvinIds:
        marvinIds:
        - applianceId: "{{ applianceId }}"
          totalSupportedNodes: 4
          position: 1
          primaryNode: true
        - applianceId: "{{ applianceId }}"
          totalSupportedNodes: 4
          position: 2
          primaryNode: false
        - applianceId: "{{ applianceId }}"
          totalSupportedNodes: 4
          position: 3
          primaryNode: false
        - applianceId: "{{ applianceId }}"
          totalSupportedNodes: 4
          position: 4
          primaryNode: false
  register: saveConfig
         
  
- name: Show save config task status
  debug:
    msg: "Config save: {{ saveConfig.json.success }}"  

- name: Apply network config
  uri:
   url: "{{ vxmUrl }}/{{ applyVxrailNetworkConfigApiUrl }}"
   method: POST
   validate_certs: no
   return_content: yes
   body_format: json
   register: applyNetworkConfig
   status_code: 304,200
   timeout: 300
   body: 
     dhcp: false
     hosts:
       management:
         pools:
         - minIp: ''
           maxIp: ''
         netmask: 255.255.255.0
         gateway: 172.22.16.1
         vlanId: '80'
         customizeIps:
         - ip: 172.22.16.101
         - ip: 172.22.16.102
         - ip: 172.22.16.103
         - ip: 172.22.16.104
       vsan:
         pools:
         - minIp: 172.22.19.101
           maxIp: 172.22.19.104
         netmask: 255.255.255.0
         vlanId: '83'
       vmotion:
         pools:
         - minIp: 172.22.18.101
           maxIp: 172.22.18.104
         netmask: 255.255.255.0
         vlanId: '82'
       vm:
       - name: VM Network
         vlanId: '81'
       witness:
         pools:
         - minIp: ''
           maxIp: ''
         netmask: ''
         gateway: ''
         vlanId: ''
     vcenter:
       ip: 172.22.16.20
     psc:
       ip: ''
     evorail:
       ip: 172.22.16.6
     portgroupBinding: EPHEMERAL

- name: Apply data config
  uri:
   url: "{{ vxmUrl }}/{{ applyVxrailDataConfigApiUrl }}"
   method: POST
   validate_certs: no
   return_content: yes
   body_format: json
  register: applyDataConfig

- name: "Check deployment status"
  debug:
    msg: "Deployment status: {{ applyDataConfig.json.success }}"

- name: Check VxRail cluster deployment progress
  uri:
   url: "{{ vxmUrl }}/{{ checkBuildProgressApiUrl }}"
   method: GET
   validate_certs: no
   return_content: yes
  register: checkBuildProgress
  until: checkBuildProgress.json.status == "COMPLETED"
  retries: 60
  delay: 60
  
- name: "Check deployment status"
  debug:
    msg: "VxRail cluster build status:{{ checkBuildProgress.json.status }}"

In next posts i will show you how to automate (with Ansible and Powershell) vCenter externalizing and renaming of cluster components (DC, cluster, vDS and vSAN datastore before VCF bringup process).

That’s it. If you have any questions or suggestions, please ping me.