Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #70: Added Host datasources #116

Merged
merged 7 commits into from
Apr 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions client/v3/v3_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ type Service interface {
ListAllImage() (*ImageListIntentResponse, error)
ListAllCluster() (*ClusterListIntentResponse, error)
GetTask(taskUUID string) (*TasksResponse, error)
GetHost(taskUUID string) (*HostResponse, error)
ListHost(getEntitiesRequest *DSMetadata) (*HostListResponse, error)
ListAllHost() (*HostListResponse, error)
}

/*CreateVM Creates a VM
Expand Down Expand Up @@ -1067,3 +1070,73 @@ func (op Operations) GetTask(taskUUID string) (*TasksResponse, error) {

return tasksTesponse, op.client.Do(ctx, req, tasksTesponse)
}

//GetHost ...
func (op Operations) GetHost(hostUUID string) (*HostResponse, error) {
ctx := context.TODO()

path := fmt.Sprintf("/hosts/%s", hostUUID)
host := new(HostResponse)

req, err := op.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, err
}

return host, op.client.Do(ctx, req, host)
}

//ListHost ...
func (op Operations) ListHost(getEntitiesRequest *DSMetadata) (*HostListResponse, error) {
ctx := context.TODO()
path := "/hosts/list"

hostList := new(HostListResponse)

req, err := op.client.NewRequest(ctx, http.MethodPost, path, getEntitiesRequest)
if err != nil {
return nil, err
}

return hostList, op.client.Do(ctx, req, hostList)
}

// ListAllHost ...
func (op Operations) ListAllHost() (*HostListResponse, error) {
entities := make([]*HostResponse, 0)

resp, err := op.ListHost(&DSMetadata{
Kind: utils.StringPtr("host"),
Length: utils.Int64Ptr(itemsPerPage),
})
if err != nil {
return nil, err
}

totalEntities := utils.Int64Value(resp.Metadata.TotalMatches)
remaining := totalEntities
offset := utils.Int64Value(resp.Metadata.Offset)

if totalEntities > itemsPerPage {
for hasNext(&remaining) {
resp, err = op.ListHost(&DSMetadata{
Kind: utils.StringPtr("cluster"),
Length: utils.Int64Ptr(itemsPerPage),
Offset: utils.Int64Ptr(offset),
})

if err != nil {
return nil, err
}

entities = append(entities, resp.Entities...)

offset += itemsPerPage
log.Printf("[Debug] total=%d, remaining=%d, offset=%d len(entities)=%d\n", totalEntities, remaining, offset, len(entities))
}

resp.Entities = entities
}

return resp, nil
}
122 changes: 122 additions & 0 deletions client/v3/v3_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2797,3 +2797,125 @@ func testHTTPMethod(t *testing.T, r *http.Request, expected string) {
t.Errorf("Request method = %v, expected %v", r.Method, expected)
}
}

func TestOperations_GetHost(t *testing.T) {
mux, c, server := setup()

defer server.Close()

mux.HandleFunc("/api/nutanix/v3/hosts/cfde831a-4e87-4a75-960f-89b0148aa2cc", func(w http.ResponseWriter, r *http.Request) {
testHTTPMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{"metadata": {"kind":"host","uuid":"cfde831a-4e87-4a75-960f-89b0148aa2cc"}}`)
})

hostResponse := &HostResponse{}
hostResponse.Metadata = &Metadata{
UUID: utils.StringPtr("cfde831a-4e87-4a75-960f-89b0148aa2cc"),
Kind: utils.StringPtr("host"),
}

type fields struct {
client *client.Client
}

type args struct {
UUID string
}

tests := []struct {
name string
fields fields
args args
want *HostResponse
wantErr bool
}{
{
"Test GetHost OK",
fields{c},
args{"cfde831a-4e87-4a75-960f-89b0148aa2cc"},
hostResponse,
false,
},
}

for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
op := Operations{
client: tt.fields.client,
}
got, err := op.GetHost(tt.args.UUID)
if (err != nil) != tt.wantErr {
t.Errorf("Operations.GetHost() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Operations.GetHost() = %v, want %v", got, tt.want)
}
})
}
}

func TestOperations_ListHost(t *testing.T) {
mux, c, server := setup()

defer server.Close()

mux.HandleFunc("/api/nutanix/v3/hosts/list", func(w http.ResponseWriter, r *http.Request) {
testHTTPMethod(t, r, http.MethodPost)
fmt.Fprint(w, `{"entities":[{"metadata": {"kind":"host","uuid":"cfde831a-4e87-4a75-960f-89b0148aa2cc"}}]}`)
})

hostList := &HostListResponse{}
hostList.Entities = make([]*HostResponse, 1)
hostList.Entities[0] = &HostResponse{}
hostList.Entities[0].Metadata = &Metadata{
UUID: utils.StringPtr("cfde831a-4e87-4a75-960f-89b0148aa2cc"),
Kind: utils.StringPtr("host"),
}

input := &DSMetadata{
Length: utils.Int64Ptr(1.0),
}

type fields struct {
client *client.Client
}

type args struct {
getEntitiesRequest *DSMetadata
}

tests := []struct {
name string
fields fields
args args
want *HostListResponse
wantErr bool
}{
{
"Test ListSubnet OK",
fields{c},
args{input},
hostList,
false,
},
}

for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
op := Operations{
client: tt.fields.client,
}
got, err := op.ListHost(tt.args.getEntitiesRequest)
if (err != nil) != tt.wantErr {
t.Errorf("Operations.ListHost() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Operations.ListHost() = %v, want %v", got, tt.want)
}
})
}
}
139 changes: 139 additions & 0 deletions client/v3/v3_structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1795,3 +1795,142 @@ type DeleteStatus struct {
State string `json:"state"`
ExecutionContext *ExecutionContext `json:"execution_context"`
}

/* Host Resource */

// DomainCredencial represents the way to login server
type DomainCredencial struct {
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
}

// WindowsDomain means Hyper-V node domain
type WindowsDomain struct {
Name string `json:"name,omitempty"`
NameServerIP string `json:"name_server_ip,omitempty"`
OrganizationUnitPath string `json:"organization_unit_path,omitempty"`
NamePrefix string `json:"name_prefix,omitempty"`
DomainName string `json:"domain_name,omitempty"`
DomainCredencial *DomainCredencial `json:"domain_credencial,omitempty"`
}

// OplogUsage represents oplog disk usage
type OplogUsage struct {
OplogDiskPct *float64 `json:"oplog_disk_pct,omitempty"`
OplogDiskSize *int64 `json:"oplog_disk_size,omitempty"`
}

// ControllerVM means Hyper-V node domain
type ControllerVM struct {
IP string `json:"ip,omitempty"`
NatIP string `json:"nat_ip,omitempty"`
NatPort *int64 `json:"nat_port,omitempty"`
OplogUsage *OplogUsage `json:"oplog_usage,omitempty"`
}

// FailoverCluster means Hiper-V failover cluster
type FailoverCluster struct {
IP string `json:"ip,omitempty"`
Name string `json:"name,omitempty"`
DomainCredencial *DomainCredencial `json:"domain_credencial,omitempty"`
}

// IPMI means Host IPMI Information
type IPMI struct {
IP string `json:"ip,omitempty"`
}

// ReferenceValues references to a kind
type ReferenceValues struct {
Kind string `json:"kind,omitempty"`
UUID string `json:"uuid,omitempty"`
Name string `json:"name,omitempty"`
}

// GPU represnts list of GPUs on the host
type GPU struct {
Status string `json:"status,omitempty"`
Vendor string `json:"vendor,omitempty"`
NumVirtualDisplayHeads *int64 `json:"num_virtual_display_heads,omitempty"`
Assignable bool `json:"assignable,omitempty"`
LicenseList []*string `json:"license_list,omitempty"`
NumVgpusAllocated *int64 `json:"num_vgpus_allocated,omitempty"`
PciAddress string `json:"pci_address,omitempty"`
Name string `json:"name,omitempty"`
FrameBufferSizeMib *int64 `json:"frame_buffer_size_mib,omitempty"`
Index *int64 `json:"index,omitempty"`
UUID string `json:"uuid,omitempty"`
NumaNode *int64 `json:"numa_node,omitempty"`
MaxResoution string `json:"max_resolution,omitempty"`
ConsumerReference *ReferenceValues `json:"consumer_reference,omitempty"`
Mode string `json:"mode,omitempty"`
Fraction *int64 `json:"fraction,omitempty"`
GuestDriverVersion string `json:"guest_driver_version,omitempty"`
DeviceID *int64 `json:"device_id,omitempty"`
}

// Hypervisor Full name of hypervisor running on Host
type Hypervisor struct {
NumVms *int64 `json:"num_vms,omitempty"`
IP string `json:"ip,omitempty"`
HypervisorFullName string `json:"hypervisor_full_name,omitempty"`
}

// Block represents Host block config info.
type Block struct {
BlockSerialNumber string `json:"block_serial_number,omitempty"`
BlockModel string `json:"block_model,omitempty"`
}

// HostResources represents the host resources
type HostResources struct {
GPUDriverVersion string `json:"gpu_driver_version,omitempty"`
FailoverCluster *FailoverCluster `json:"failover_cluster,omitempty"`
IPMI *IPMI `json:"ipmi,omitempty"`
CPUModel string `json:"cpu_model,omitempty"`
HostNicsIDList []*string `json:"host_nics_id_list,omitempty"`
NumCPUSockets *int64 `json:"num_cpu_sockets,omitempty"`
WindowsDomain *WindowsDomain `json:"windows_domain,omitempty"`
GPUList []*GPU `json:"gpu_list,omitempty"`
SerialNumber string `json:"serial_number,omitempty"`
CPUCapacityHZ *int64 `json:"cpu_capacity_hz,omitempty"`
MemoryVapacityMib *int64 `json:"memory_capacity_mib,omitempty"`
HostDisksReferenceList []*ReferenceValues `json:"host_disks_reference_list,omitempty"`
MonitoringState string `json:"monitoring_state,omitempty"`
Hypervisor *Hypervisor `json:"hypervisor,omitempty"`
HostType string `json:"host_type,omitempty"`
NumCPUCores *int64 `json:"num_cpu_cores,omitempty"`
RackableUnitReference *ReferenceValues `json:"rackable_unit_reference,omitempty"`
ControllerVM *ControllerVM `json:"controller_vm,omitempty"`
Block *Block `json:"block,omitempty"`
}

// HostSpec Represents volume group input spec.
type HostSpec struct {
Name string `json:"name,omitempty"`
Resources *HostResources `json:"resources,omitempty"`
}

// HostStatus Volume group configuration.
type HostStatus struct {
State string `json:"state,omitempty"`
MessageList []*MessageResource `json:"message_list,omitempty"`
Name string `json:"name,omitempty"`
Resources *HostResources `json:"resources,omitempty"`
ClusterReference *ReferenceValues `json:"cluster_reference,omitempty"`
}

// HostResponse Response object for intentful operations on a Host
type HostResponse struct {
APIVersion string `json:"api_version,omitempty"`
Metadata *Metadata `json:"metadata,omitempty"`
Spec *HostSpec `json:"spec,omitempty"`
Status *HostStatus `json:"status,omitempty"`
}

// HostListResponse Response object for intentful operation of Host
type HostListResponse struct {
APIVersion string `json:"api_version,omitempty"`
Entities []*HostResponse `json:"entities,omitempty"`
Metadata *ListMetadataOutput `json:"metadata,omitempty"`
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/hashicorp/terraform v0.12.3
github.com/mitchellh/gox v1.0.1
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/cast v1.3.1
)

go 1.13
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,8 @@ github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
Expand Down
Loading