/*
// Copyright (c) 2016 Intel Corporation
//
// Licensed 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.
*/

package payloads

// Persistence represents the persistency of an instance, i.e., whether that
// instance should be restarted after certain events have occurred, e.g., the
// node on which the instance runs is rebooted. It's not currently implemented
// in ciao-launcher.
type Persistence string

// Firmware represents the type of firmware used to boot a VM
type Firmware string

// Resource represents the name of a resource in a StartCmd structure
type Resource string

// Hypervisor indicates the type of hypervisor used to run a given instance
type Hypervisor string

const (
	// All used to indicate all persistent scenario, in this case it
	// indicates to act in all instances.
	All Persistence = "all"

	// VM used to indicate in a instance persistent scenario, in this case it
	// indicates to act in only one instance.
	VM = "vm"

	// Host used to indicate in a Host persistent scenario, in this case it
	// indicates to act in only in the instances of a host.
	Host = "host"
)

const (
	// EFI indicates that EFI firmware, e.g., OVMF.fd, should be used to
	// boot a VM
	EFI Firmware = "efi"

	// Legacy indicates that legacy firmware, e.g., BIOS should be used
	// to boot a VM
	Legacy = "legacy"
)

const (
	// VCPUs indicates that a particular resource struct contains a count
	// of VCPUs
	VCPUs Resource = "vcpus"

	// MemMB indicates that a resource struct specifies a quantity of memory
	// in MBs
	MemMB = "mem_mb"

	// NetworkNode indicates that a resource struct specifies whether the
	// command in which it is embedded applies to a network node.
	NetworkNode = "network_node"

	// ComputeNode indicates that a resource struct specifies whether the
	// command in which it is embedded applies to a compute node.
	ComputeNode = "compute_node"

	// Instance is used to indicate that this requested resource is an instance.
	Instance = "instance"

	// Volume is used to indicate that the requested resource is a volume.
	Volume = "volume"

	// Image is used to indicate that the requested resource is an image.
	Image = "image"

	// ExternalIP is used to indicate the the requested resource is an
	// externally accessible IP address.
	ExternalIP = "external_ip"

	// SharedDiskGiB is used for shared storage across the cluster used for
	// storing volume and images. (Measured in GiB)
	SharedDiskGiB = "shared_disk_gib"
)

const (
	// QEMU specifies that an instance is to be booted on QEMU KVM VM.
	QEMU Hypervisor = "qemu"

	// Docker specifies that an instance is to be launched inside a Docker
	// container.
	Docker = "docker"
)

// StorageResource represents a requested storage resource for a workload.
type StorageResource struct {
	// ID is passed to the Block Driver to operate on the resource
	ID string `yaml:"id,omitempty"`

	// Bootable indicates that this is a bootable storage device.
	Bootable bool `yaml:"boot,omitempty"`

	// BootIndex hints to the hypervisor a bootable disk order among
	// multple storage resources
	BootIndex int `yaml:"boot_index,omitempty"`

	// Ephemeral indicates whether this storage should only last as long as
	// the instance
	Ephemeral bool `yaml:"ephemeral,omitempty"`

	// Local indicates if the storage resource is local (ephemeral,
	// auto-created by launcher implied) or backed by the volume service
	Local bool `yaml:"local,omitempty"`

	// Swap optionally indicates the storage resource is intended for
	// use as a linux swap device (attempt swapon via cloud-init
	Swap bool `yaml:"swap,omitempty"`

	// Tag is an arbitrary text identifier
	Tag string `yaml:"tag,omitempty"`

	// Size is the requested size for an auto-created storage resource
	Size int `yaml:"size,omitempty"`
}

// RequestedResource is used to specify an individual resource contained within
// a Start or Restart command.  Example of resources include number of VCPUs or
// MBs of RAM to assign to an instance
type RequestedResource struct {
	// Type specifies the type of the resource, e.g., VCPUs.
	Type Resource `yaml:"type"`

	// Value specifies the integer value associated with that resource.
	Value int `yaml:"value"`

	// ValueString is an optional string format value instead of integer
	ValueString string `yaml:"value_string,omitempty"`

	// Mandatory indicates whether a resource is mandatory or not.
	Mandatory bool `yaml:"mandatory"`
}

// NetworkResources contains all the networking information for an instance.
type NetworkResources struct {

	// VnicMAC contains the MAC address of an instance's VNIC.
	VnicMAC string `yaml:"vnic_mac"`

	// VnicUUID is a cluster unique UUID assigned to an instance's VNIC.
	VnicUUID string `yaml:"vnic_uuid"`

	// ConcentratorUUID is the UUID of the CNCI instance.  Only specified
	// when creating CN instances.
	ConcentratorUUID string `yaml:"concentrator_uuid"`

	// ConcentratorIP is the IP address of the CNCI.  Only specified
	// when creating CN instances.
	ConcentratorIP string `yaml:"concentrator_ip"`

	// Subnet is the subnet to which the instance is assigned.  Only
	// specified when creating CN instances.
	Subnet string `yaml:"subnet"`

	// SubnetKey is the subnet identifier to which the instance
	// is assigned.
	SubnetKey string `yaml:"subnet_key"`

	// SubnetUUID is the subnet ID of the subnet to which the instance is
	//  assinged.
	SubnetUUID string `yaml:"subnet_uuid"`

	// PrivateIP represents the private IP address of an instance.  Only
	// specified when creating CN instances.
	PrivateIP string `yaml:"private_ip"`

	// PublicIP represents the current statu of the assignation of a Public
	// IP.
	PublicIP bool `yaml:"public_ip"`
}

// WorkloadRequirements contains the requirements to execute the workload
type WorkloadRequirements struct {
	// MemMB species the required memory for this workload in MiB
	MemMB int `yaml:"mem_mb"`

	// VCPUs specifies the required number of CPUs for the workload
	VCPUs int `yaml:"vcpus"`

	// NodeID specifies the node that the instance must be scheduled on
	NodeID string `yaml:"node_id,omitempty"`

	// Hostname specifies the node that the instance must be scheduled on
	Hostname string `yaml:"hostname,omitempty"`

	// NetworkNode specifies that this workload must be scheduled on a network node
	NetworkNode bool `yaml:"network_node,omitempty"`

	// Privileged indicates that this container workload should be run with increased
	// permissions
	Privileged bool `yaml:"privileged,omitempty"`
}

// StartCmd contains the information needed to start a new instance.
type StartCmd struct {
	// TenantUUID is the UUID of the tenant to which the new instance will
	// belong.
	TenantUUID string `yaml:"tenant_uuid"`

	// InstanceUUID is the UUID of the instance itself.
	InstanceUUID string `yaml:"instance_uuid"`

	// DockerImage is the name of the docker base image from which the
	// container will be created.  It should match the name of an
	// existing image in the docker registry.  Only used for docker
	// instances.
	DockerImage string `yaml:"docker_image"`

	// FWType indicates the type of firmware needed to boot the instance.
	// Only used for qemu instances.
	FWType Firmware `yaml:"fw_type"`

	// InstancePersistence is the persistence type for the instance.
	InstancePersistence Persistence `yaml:"persistence"`

	// VMType indicates whether we are creating a qemu or docker instance.
	VMType Hypervisor `yaml:"vm_type"`

	// Networking contains all the information required to set up networking
	// for the new instance.
	Networking NetworkResources `yaml:"networking"`

	// Storage contains all the information required to attach or boot
	// from storage for the new instance.
	Storage []StorageResource `yaml:"storage,omitempty"`

	// Requirements indicates what resources are needed for this workload
	Requirements WorkloadRequirements `yaml:"requirements"`

	// Restart is set to true if the payload represents a request to
	// restart an existing instance on a new node.
	Restart bool
}

// Start represents the unmarshalled version of the contents of a SSNTP START
// payload.  The structure contains enough information to create and launch a
// new CN or NN instance.
type Start struct {
	// Start contains information about the instance to create.
	Start StartCmd `yaml:"start"`
}
