# -*- coding: utf-8 -*-
'''
    :codeauthor: :email:`Agnes Tevesz (agnes.tevesz@morganstanley.com)`

    salt.config.schemas.esxvm
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~

    ESX Virtual Machine configuration schemas
'''

# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals

from salt.utils.schema import (DefinitionsSchema,
                               ComplexSchemaItem,
                               ArrayItem,
                               IntegerItem,
                               NumberItem,
                               BooleanItem,
                               StringItem,
                               IPv4Item,
                               AnyOfItem,
                               NullItem)


class ESXVirtualMachineSerialBackingItem(ComplexSchemaItem):
    '''
    Configuration Schema Item for ESX Virtual Machine Serial Port Backing
    '''
    title = 'ESX Virtual Machine Serial Port Backing'
    description = 'ESX virtual machine serial port backing'
    required = True

    uri = StringItem()
    direction = StringItem(enum=('client', 'server'))
    filename = StringItem()


class ESXVirtualMachineDeviceConnectionItem(ComplexSchemaItem):
    '''
    Configuration Schema Item for ESX Virtual Machine Serial Port Connection
    '''
    title = 'ESX Virtual Machine Serial Port Connection'
    description = 'ESX virtual machine serial port connection'
    required = True

    allow_guest_control = BooleanItem(default=True)
    start_connected = BooleanItem(default=True)


class ESXVirtualMachinePlacementSchemaItem(ComplexSchemaItem):
    '''
    Configuration Schema Item for ESX Virtual Machine Placement
    '''
    title = 'ESX Virtual Machine Placement Information'
    description = 'ESX virtual machine placement property'
    required = True

    cluster = StringItem(title='Virtual Machine Cluster',
                         description='Cluster of the virtual machine if it is placed to a cluster')
    host = StringItem(title='Virtual Machine Host',
                      description='Host of the virtual machine if it is placed to a standalone host')
    resourcepool = StringItem(title='Virtual Machine Resource Pool',
                              description='Resource pool of the virtual machine if it is placed to a resource pool')
    folder = StringItem(title='Virtual Machine Folder',
                        description='Folder of the virtual machine where it should be deployed, default is the datacenter vmFolder')


class ESXVirtualMachineCdDriveClientSchemaItem(ComplexSchemaItem):
    '''
    Configuration Schema Item for ESX Virtual Machine CD Drive Client
    '''
    title = 'ESX Virtual Machine Serial CD Client'
    description = 'ESX virtual machine CD/DVD drive client properties'

    mode = StringItem(required=True, enum=('passthrough', 'atapi'))


class ESXVirtualMachineCdDriveIsoSchemaItem(ComplexSchemaItem):
    '''
    Configuration Schema Item for ESX Virtual Machine CD Drive ISO
    '''
    title = 'ESX Virtual Machine Serial CD ISO'
    description = 'ESX virtual machine CD/DVD drive ISO properties'

    path = StringItem(required=True)


class ESXVirtualMachineCdDriveSchemaItem(ComplexSchemaItem):
    '''
    Configuration Schema Item for ESX Virtual Machine CD Drives
    '''
    title = 'ESX Virtual Machine Serial CD'
    description = 'ESX virtual machine CD/DVD drive properties'

    adapter = StringItem(title='Virtual Machine CD/DVD Adapter',
                         description='Unique adapter name for virtual machine cd/dvd drive',
                         required=True)
    controller = StringItem(required=True)
    device_type = StringItem(title='Virtual Machine Device Type',
                             description='CD/DVD drive of the virtual machine if it is placed to a cluster',
                             required=True,
                             default='client_device',
                             enum=('datastore_iso_file', 'client_device'))
    client_device = ESXVirtualMachineCdDriveClientSchemaItem()
    datastore_iso_file = ESXVirtualMachineCdDriveIsoSchemaItem()
    connectable = ESXVirtualMachineDeviceConnectionItem()


class ESXVirtualMachineSerialSchemaItem(ComplexSchemaItem):
    '''
    Configuration Schema Item for ESX Virtual Machine Serial Port
    '''
    title = 'ESX Virtual Machine Serial Port Configuration'
    description = 'ESX virtual machine serial port properties'

    type = StringItem(title='Virtual Machine Serial Port Type',
                      required=True,
                      enum=('network', 'pipe', 'file', 'device'))
    adapter = StringItem(title='Virtual Machine Serial Port Name',
                         description='Unique adapter name for virtual machine serial port'
                                     'for creation an arbitrary value should be specified',
                         required=True)
    backing = ESXVirtualMachineSerialBackingItem()
    connectable = ESXVirtualMachineDeviceConnectionItem()
    yield_port = BooleanItem(title='Serial Port Yield',
                             description='Serial port yield',
                             default=False)


class ESXVirtualMachineScsiSchemaItem(ComplexSchemaItem):
    '''
    Configuration Schema Item for ESX Virtual Machine SCSI Controller
    '''
    title = 'ESX Virtual Machine SCSI Controller Configuration'
    description = 'ESX virtual machine scsi controller properties'
    required = True

    adapter = StringItem(title='Virtual Machine SCSI Controller Name',
                         description='Unique SCSI controller name'
                                     'for creation an arbitrary value should be specified',
                         required=True)
    type = StringItem(title='Virtual Machine SCSI type',
                      description='Type of the SCSI controller',
                      required=True,
                      enum=('lsilogic', 'lsilogic_sas', 'paravirtual', 'buslogic'))
    bus_sharing = StringItem(title='Virtual Machine SCSI bus sharing',
                             description='Sharing type of the SCSI bus',
                             required=True,
                             enum=('virtual_sharing', 'physical_sharing', 'no_sharing'))
    bus_number = NumberItem(title='Virtual Machine SCSI bus number',
                            description='Unique bus number of the SCSI device',
                            required=True)


class ESXVirtualMachineSataSchemaItem(ComplexSchemaItem):
    '''
    Configuration Schema Item for ESX Virtual Machine SATA Controller
    '''
    title = 'ESX Virtual Machine SATA Controller Configuration'
    description = 'ESX virtual machine SATA controller properties'
    required = False
    adapter = StringItem(title='Virtual Machine SATA Controller Name',
                         description='Unique SATA controller name'
                                     'for creation an arbitrary value should be specified',
                         required=True)
    bus_number = NumberItem(title='Virtual Machine SATA bus number',
                            description='Unique bus number of the SATA device',
                            required=True)


class ESXVirtualMachineDiskSchemaItem(ComplexSchemaItem):
    '''
    Configuration Schema Item for ESX Virtual Machine Disk
    '''
    title = 'ESX Virtual Machine Disk Configuration'
    description = 'ESX virtual machine disk properties'
    required = True

    size = NumberItem(title='Disk size',
                      description='Size of the disk in GB',
                      required=True)
    unit = StringItem(title='Disk size unit',
                      description='Unit of the disk size, to VMware a '
                                  'GB is the same as GiB = 1024MiB',
                      required=False,
                      default='GB',
                      enum=('KB', 'MB', 'GB'))
    adapter = StringItem(title='Virtual Machine Adapter Name',
                         description='Unique adapter name for virtual machine'
                                     'for creation an arbitrary value should be specified',
                         required=True)
    filename = StringItem(title='Virtual Machine Disk File',
                          description='File name of the virtual machine vmdk')
    datastore = StringItem(title='Virtual Machine Disk Datastore',
                           description='Disk datastore where the virtual machine files will be placed',
                           required=True)
    address = StringItem(title='Virtual Machine SCSI Address',
                         description='Address of the SCSI adapter for the virtual machine',
                         pattern=r'\d:\d')
    thin_provision = BooleanItem(title='Virtual Machine Disk Provision Type',
                                 description='Provision type of the disk',
                                 default=True,
                                 required=False)
    eagerly_scrub = AnyOfItem(required=False,
                              items=[BooleanItem(), NullItem()])
    controller = StringItem(title='Virtual Machine SCSI Adapter',
                            description='Name of the SCSI adapter where the disk will be connected',
                            required=True)


class ESXVirtualMachineNicMapSchemaItem(ComplexSchemaItem):
    '''
    Configuration Schema Item for ESX Virtual Machine Nic Map
    '''
    title = 'ESX Virtual Machine Nic Configuration'
    description = 'ESX Virtual Machine nic properties'
    required = False

    domain = StringItem()
    gateway = IPv4Item()
    ip_addr = IPv4Item()
    subnet_mask = IPv4Item()


class ESXVirtualMachineInterfaceSchemaItem(ComplexSchemaItem):
    '''
    Configuration Schema Item for ESX Virtual Machine Network Interface
    '''
    title = 'ESX Virtual Machine Network Interface Configuration'
    description = 'ESX Virtual Machine network adapter properties'
    required = True

    name = StringItem(title='Virtual Machine Port Group',
                      description='Specifies the port group name for the virtual machine connection',
                      required=True)
    adapter = StringItem(title='Virtual Machine Network Adapter',
                         description='Unique name of the network adapter, '
                                     'for creation an arbitrary value should be specified',
                         required=True)
    adapter_type = StringItem(title='Virtual Machine Adapter Type',
                              description='Network adapter type of the virtual machine',
                              required=True,
                              enum=('vmxnet', 'vmxnet2', 'vmxnet3', 'e1000', 'e1000e'),
                              default='vmxnet3')
    switch_type = StringItem(title='Virtual Machine Switch Type',
                             description='Specifies the type of the virtual switch for the virtual machine connection',
                             required=True,
                             default='standard',
                             enum=('standard', 'distributed'))
    mac = StringItem(title='Virtual Machine MAC Address',
                     description='Mac address of the virtual machine',
                     required=False,
                     pattern='^([0-9a-f]{1,2}[:]){5}([0-9a-f]{1,2})$')
    mapping = ESXVirtualMachineNicMapSchemaItem()
    connectable = ESXVirtualMachineDeviceConnectionItem()


class ESXVirtualMachineMemorySchemaItem(ComplexSchemaItem):
    '''
    Configurtation Schema Item for ESX Virtual Machine Memory
    '''
    title = 'ESX Virtual Machine Memory Configuration'
    description = 'ESX Virtual Machine memory property'
    required = True

    size = IntegerItem(title='Memory size',
                       description='Size of the memory',
                       required=True)

    unit = StringItem(title='Memory unit',
                      description='Unit of the memory, to VMware a '
                                  'GB is the same as GiB = 1024MiB',
                      required=False,
                      default='MB',
                      enum=('MB', 'GB'))
    hotadd = BooleanItem(required=False, default=False)
    reservation_max = BooleanItem(required=False, default=False)


class ESXVirtualMachineCpuSchemaItem(ComplexSchemaItem):
    '''
    Configurtation Schema Item for ESX Virtual Machine CPU
    '''
    title = 'ESX Virtual Machine Memory Configuration'
    description = 'ESX Virtual Machine memory property'
    required = True

    count = IntegerItem(title='CPU core count',
                        description='CPU core count',
                        required=True)
    cores_per_socket = IntegerItem(title='CPU cores per socket',
                                   description='CPU cores per socket count',
                                   required=False)
    nested = BooleanItem(title='Virtual Machine Nested Property',
                         description='Nested virtualization support',
                         default=False)
    hotadd = BooleanItem(title='Virtual Machine CPU hot add',
                         description='CPU hot add',
                         default=False)
    hotremove = BooleanItem(title='Virtual Machine CPU hot remove',
                            description='CPU hot remove',
                            default=False)


class ESXVirtualMachineConfigSchema(DefinitionsSchema):
    '''
    Configuration Schema for ESX Virtual Machines
    '''
    title = 'ESX Virtual Machine Configuration Schema'
    description = 'ESX Virtual Machine configuration schema'

    vm_name = StringItem(title='Virtual Machine name',
                         description='Name of the virtual machine',
                         required=True)
    cpu = ESXVirtualMachineCpuSchemaItem()
    memory = ESXVirtualMachineMemorySchemaItem()
    image = StringItem(title='Virtual Machine guest OS',
                       description='Guest OS type',
                       required=True)
    version = StringItem(title='Virtual Machine hardware version',
                         description='Container hardware version property',
                         required=True)
    interfaces = ArrayItem(items=ESXVirtualMachineInterfaceSchemaItem(),
                           min_items=1,
                           required=False,
                           unique_items=True)
    disks = ArrayItem(items=ESXVirtualMachineDiskSchemaItem(),
                      min_items=1,
                      required=False,
                      unique_items=True)
    scsi_devices = ArrayItem(items=ESXVirtualMachineScsiSchemaItem(),
                             min_items=1,
                             required=False,
                             unique_items=True)
    serial_ports = ArrayItem(items=ESXVirtualMachineSerialSchemaItem(),
                             min_items=0,
                             required=False,
                             unique_items=True)
    cd_dvd_drives = ArrayItem(items=ESXVirtualMachineCdDriveSchemaItem(),
                              min_items=0,
                              required=False,
                              unique_items=True)
    sata_controllers = ArrayItem(items=ESXVirtualMachineSataSchemaItem(),
                                 min_items=0,
                                 required=False,
                                 unique_items=True)
    datacenter = StringItem(title='Virtual Machine Datacenter',
                            description='Datacenter of the virtual machine',
                            required=True)
    datastore = StringItem(title='Virtual Machine Datastore',
                           description='Datastore of the virtual machine',
                           required=True)
    placement = ESXVirtualMachinePlacementSchemaItem()
    template = BooleanItem(title='Virtual Machine Template',
                           description='Template to create the virtual machine from',
                           default=False)
    tools = BooleanItem(title='Virtual Machine VMware Tools',
                        description='Install VMware tools on the guest machine',
                        default=False)
    power_on = BooleanItem(title='Virtual Machine Power',
                           description='Power on virtual machine afret creation',
                           default=False)
    deploy = BooleanItem(title='Virtual Machine Deploy Salt',
                         description='Deploy salt after successful installation',
                         default=False)


class ESXVirtualMachineRemoveSchema(DefinitionsSchema):
    '''
    Remove Schema for ESX Virtual Machines to delete or unregister virtual machines
    '''
    name = StringItem(title='Virtual Machine name',
                      description='Name of the virtual machine',
                      required=True)
    datacenter = StringItem(title='Virtual Machine Datacenter',
                            description='Datacenter of the virtual machine',
                            required=True)
    placement = AnyOfItem(required=False,
                          items=[ESXVirtualMachinePlacementSchemaItem(), NullItem()])
    power_off = BooleanItem(title='Power off vm',
                            description='Power off vm before delete operation',
                            required=False)


class ESXVirtualMachineDeleteSchema(ESXVirtualMachineRemoveSchema):
    '''
    Deletion Schema for ESX Virtual Machines
    '''


class ESXVirtualMachineUnregisterSchema(ESXVirtualMachineRemoveSchema):
    '''
    Unregister Schema for ESX Virtual Machines
    '''
