---

#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# These Ansible tasks only run on the client machine where Muchos runs
# At a high level, the various sections in this file do the following:
# 1. Create (if not already existing): an Azure resource group, virtual network / subnet
# 2. Optionally (if the user specified) create a VM and related resources to use as a proxy host
# 3. Create the Azure VMSS to support the nodes for use with Muchos
# 4. Automatically populate the hosts file and associated [nodes] section in muchos.props

# Moved SECTION1 to create_common_resources.yml
# Moved SECTION2 to create_optional_proxy.yml

# SECTION 3: Create the Azure VMSS for the nodes used by Muchos

- name: Create luns dictionary
  set_fact:
    luns_dict: "{{ luns_dict | default ([]) + [{ 'lun': item, 'disk_size_gb': disk_size_gb, 'managed_disk_type': data_disk_sku, 'caching': data_disk_caching } ] }}"
  with_sequence: start=0 end={{ data_disk_count-1 if data_disk_count > 0 else 0 }}

- name: Set single placement group to correct value
  set_fact:
    single_placement_group: False
  when: numnodes > 100

- name: Create Scale Set
  community.azure.azure_rm_virtualmachinescaleset:
    resource_group: "{{ resource_group }}"
    location: "{{ location }}"
    name: "{{ vmss_name }}"
    vm_size: "{{ vm_sku }}"
    priority: "{{ vmss_priority | default('Regular') }}"
    admin_username: "{{ cluster_user }}"
    ssh_password_enabled: false
    ssh_public_keys:
      - path: /home/{{ cluster_user }}/.ssh/authorized_keys
        key_data: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
    capacity: "{{ numnodes }}"
    virtual_network_name: "{{ vnet }}"
    subnet_name: "{{ subnet }}"
    upgrade_policy: Manual
    tier: Standard
    managed_disk_type: "{{ osdisk_sku }}"
    os_disk_caching: ReadWrite
    enable_accelerated_networking: "{{ accnet_capable }}"
    single_placement_group: "{{ single_placement_group | default(omit) }}"
    image:
      offer: "{{ image_offer if image_offer else omit }}"
      publisher: "{{ image_publisher if image_publisher else omit }}"
      sku: "{{ image_sku if image_sku else omit }}"
      version: "{{ image_version if image_version else omit }}"
    data_disks: "{{ luns_dict if data_disk_count > 0 else omit }}"
    custom_data: "{{ lookup('file', 'cloud-init.yml') }}"
  vars:
  - image_offer: "{{ azure_image_reference.split('|')[0] }}"
  - image_publisher: "{{ azure_image_reference.split('|')[1] }}"
  - image_sku: "{{ azure_image_reference.split('|')[2] }}"
  - image_version: "{{ azure_image_reference.split('|')[3] }}"
  - accnet_capable: "{{ True if vm_sku in accnet_capable_skus else False }}"
  - osdisk_sku: "{{ 'Premium_LRS' if vm_sku in premiumio_capable_skus else 'Standard_LRS' }}"
  tags: create_vmss

# SECTION 4: Automatically populate entries in the hosts file and in the muchos.props file, based on the VMSS node details
# Refactored below tasks to use Azure modules
- name: get instance ids
  azure_rm_virtualmachinescalesetinstance_info:
    resource_group: "{{ resource_group }}"
    vmss_name: "{{ vmss_name }}"
  register: vmss_instances

- name: replace underscores in instance names with dashes
  set_fact:
    hostnames: "{{ vmss_instances.instances | map(attribute='name') | map('replace', '_', '-') | list }}"

- name: Ensures host_vars sub-dir exists
  file:
     path: "{{ deploy_path }}/ansible/host_vars/"
     state: directory
     recurse: yes

- name: Get VMSS nic list
  azure_rm_virtualmachinescaleset_nic_list_facts:
    resource_group: "{{ resource_group }}"
    vmss_name: "{{ vmss_name }}"
  register: vmss_nic_list

- name: Get VM hostname to IP mapping
  set_fact:
    hostname_ip_pairs: |
      {%- set vmname_ips = [] -%}
      {%- if azure_proxy_host is defined and azure_proxy_host -%}
      {%- set _ = vmname_ips.append({'name': azure_proxy_host, 'ip': azure_proxy_public_ip.state.ip_address }) -%}
      {%- endif -%}
      {%- set vmid_names = {} -%}
      {%- for instance in vmss_instances.instances -%}
      {%- set _ = vmid_names.__setitem__(instance.id, instance.name.replace('_','-')) -%}
      {%- endfor -%}
      {%- set vmid_ips = {} -%}
      {%- for interface in vmss_nic_list.networkinterfaces -%}
      {%- if interface.virtualMachine is defined -%}
      {%- set _ = vmid_ips.__setitem__(interface.virtualMachine.id, interface.ipConfigurations[0].privateIPAddress) -%}
      {%- endif -%}
      {%- endfor -%}
      {%- for vmid in vmid_names -%}
      {%- set _ = vmname_ips.append({'name': vmid_names[vmid], 'ip': vmid_ips[vmid]}) -%}
      {%- endfor -%}
      {{ vmname_ips }}

- name: Ensures hosts sub-dir exists
  file:
     path: "{{ deploy_path }}/conf/hosts/"
     state: directory
     recurse: yes

- name: Write hosts file
  template:
    src: hostname_ip_mappings.j2
    dest: "{{ deploy_path }}/conf/hosts/{{ vmss_name }}"
    mode: 0644

- name: Clear section
  community.general.ini_file:
    path: "{{ deploy_path }}/conf/muchos.props"
    section: "nodes"
    state: absent

- name: Recreate section
  community.general.ini_file:
    path: "{{ deploy_path }}/conf/muchos.props"
    section: "nodes"
    option: "#host0"
    value: "service"
    state: present

- name: add azure proxy host
  lineinfile:
    path: "{{ deploy_path }}/conf/muchos.props"
    line: "{{ azure_proxy_host }} = client"
  when: azure_proxy_host is defined and azure_proxy_host and azure_proxy_host != None

- block:
  - name: Assign Accumulo master, HDFS components to the first node of the cluster
    lineinfile:
      path: "{{ deploy_path }}/conf/muchos.props"
      line: "{{ hostnames[0] }} = namenode,resourcemanager,accumulomaster,zookeeper"
  - name: Assign metrics to the second node of the cluster
    lineinfile:
      path: "{{ deploy_path }}/conf/muchos.props"
      line: "{{ hostnames[1] }} = metrics"
  - name: Add worker nodes to muchos.props
    lineinfile:
      path: "{{ deploy_path }}/conf/muchos.props"
      line: "{{ item }} = worker"
    with_items: "{{ hostnames | json_query('[2:]') }}"
  when: not hdfs_ha

- block:
  - name: Assign Accumulo master, HDFS HA components cluster roles to the first node of the cluster
    lineinfile:
      path: "{{ deploy_path }}/conf/muchos.props"
      line: "{{ hostnames[0] }} = namenode,resourcemanager,accumulomaster,zookeeper,journalnode,zkfc"
  - name: Assign Accumulo master, HDFS HA components cluster roles to the second node of the cluster
    lineinfile:
      path: "{{ deploy_path }}/conf/muchos.props"
      line: "{{ hostnames[1] }} = zookeeper,metrics,journalnode,namenode,zkfc,accumulomaster,resourcemanager"
  - name: Assign HDFS HA components cluster roles to the third node of the cluster
    lineinfile:
      path: "{{ deploy_path }}/conf/muchos.props"
      line: "{{ hostnames[2] }} = journalnode,zookeeper"
  - name: Add worker nodes to muchos.props
    lineinfile:
      path: "{{ deploy_path }}/conf/muchos.props"
      line: "{{ item }} = worker"
    with_items: "{{ hostnames | json_query('[3:]') }}"
  when: hdfs_ha

- name: Change proxy hostname to azure proxy host in muchos.props
  lineinfile:
    path: "{{ deploy_path }}/conf/muchos.props"
    regexp: '^proxy_hostname\s*=\s*'
    line: "proxy_hostname = {{ azure_proxy_host }}"
  when: azure_proxy_host is defined and azure_proxy_host and azure_proxy_host != None

- name: Change proxy hostname to first node in vmss in muchos.props
  lineinfile:
    path: "{{ deploy_path }}/conf/muchos.props"
    regexp: '^proxy_hostname\s*=\s*'
    line: "proxy_hostname = {{ hostnames[0] }}"
  when: not (azure_proxy_host is defined and azure_proxy_host and azure_proxy_host != None)
