diff --git a/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/compute-capacity/compute-capacity.component.ts b/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/compute-capacity/compute-capacity.component.ts index fa2d67e82..6da74225b 100644 --- a/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/compute-capacity/compute-capacity.component.ts +++ b/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/compute-capacity/compute-capacity.component.ts @@ -51,7 +51,7 @@ export class ComputeCapacityComponent implements OnInit { cpu: { maxUsage: null, minUsage: null, unreservedForPool: null }, memory: { maxUsage: null, minUsage: null, unreservedForPool: null } }; - public selectedObjectName: string; + public selectedObject: ComputeResource; public selectedResourceObjRef: string; private _selectedComputeResource: string; public serversInfo: ServerInfo[]; @@ -164,7 +164,7 @@ export class ComputeCapacityComponent implements OnInit { `${computeResource}/${payload.obj.realName}`; } this.selectedResourceObjRef = resourceObj; - this.selectedObjectName = payload.obj.realName; + this.selectedObject = payload.obj; this._selectedComputeResource = computeResource; // set active class on the treenodecomponent whose datacenter object reference is diff --git a/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/create-vch-wizard.component.html b/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/create-vch-wizard.component.html index 05bace349..fa275d19b 100644 --- a/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/create-vch-wizard.component.html +++ b/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/create-vch-wizard.component.html @@ -112,7 +112,7 @@ + [resourceObj]="computeCapacityStep.selectedObject"> diff --git a/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/create-vch-wizard.service.spec.ts b/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/create-vch-wizard.service.spec.ts index 7be8d687c..531174c4c 100644 --- a/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/create-vch-wizard.service.spec.ts +++ b/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/create-vch-wizard.service.spec.ts @@ -31,12 +31,15 @@ import { JASMINE_TIMEOUT } from '../testing/jasmine.constants'; import { CreateVchWizardService } from './create-vch-wizard.service'; import { Globals, GlobalsService } from '../shared'; import { + clusterHostsChilds, computeResourcesRealName, dcClustersAndStandAloneHosts, dcDSwitchPorGroupsList, dcMockData, dvsHostsEntries, folderDSwitchList, folderDSwitchPorGroupsList, netWorkingResources } from './mocks/create-vch-wizard-mocked-data'; +import {ComputeResource} from '../interfaces/compute.resource'; +import {COMPUTE_RESOURCE_NODE_TYPES} from '../shared/constants'; describe('CreateVchWizardService', () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = JASMINE_TIMEOUT; @@ -127,17 +130,33 @@ describe('CreateVchWizardService', () => { spyOn(service, 'getDvsFromNetworkFolders').and.returnValue(Observable.of(folderDSwitchList)); spyOn(service, 'getDvsPortGroups').and.returnValue([...folderDSwitchPorGroupsList, ...dcDSwitchPorGroupsList]); spyOn(service, 'getDvsHostsEntries').and.returnValue(dvsHostsEntries); - - service.getDistributedPortGroups(null, '10.192.109.234') + spyOn(service, 'getHostsFromComputeResource').and.returnValue(clusterHostsChilds); + + const selectedHostResource: ComputeResource = { + text: '10.192.109.234', + nodeTypeId: COMPUTE_RESOURCE_NODE_TYPES.host.dc_stand_alone, + objRef: 'urn:vmomi:ClusterComputeResource:host-276:d7c361cc-0a46-441e-8e21-ac22debf7003', + aliases: ['alias-id1'], + isEmpty: true + }; + + const selectedClusterResource: ComputeResource = { + text: 'New Cluster', + nodeTypeId: COMPUTE_RESOURCE_NODE_TYPES.cluster.dc_cluster, + objRef: 'urn:vmomi:ClusterComputeResource:domain-c270:d7c361cc-0a46-441e-8e21-ac22debf7003', + aliases: ['alias-id1'], + isEmpty: true + }; + + service.getDistributedPortGroups(null, selectedHostResource) .subscribe(data => { - expect(data.length).toBe(8); - }); + expect(data.length).toBe(3); + }); - service.getDistributedPortGroups(null, 'New Cluster') + service.getDistributedPortGroups(null, selectedClusterResource) .subscribe(data => { expect(data.length).toBe(3); - }); - + }); }); it('should return a list of Compute Resources with a property called realName', async() => { diff --git a/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/create-vch-wizard.service.ts b/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/create-vch-wizard.service.ts index 3f39a877a..8d7117ded 100644 --- a/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/create-vch-wizard.service.ts +++ b/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/create-vch-wizard.service.ts @@ -25,7 +25,6 @@ import { GET_CLONE_TICKET_URL, MEMORY_MIN_LIMIT_MB, VIC_APPLIANCES_LOOKUP_URL, - VIC_APPLIANCE_PORT } from '../shared/constants'; import { Http, URLSearchParams } from '@angular/http'; @@ -35,7 +34,9 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { byteToLegibleUnit } from '../shared/utils/filesize'; import { flattenArray } from '../shared/utils/array-utils'; -import { getServerServiceGuidFromObj } from '../shared/utils/object-reference'; +import { getMorIdFromObjRef, getServerServiceGuidFromObj, resourceIsCluster } from '../shared/utils/object-reference'; +import { HostTypeInfo } from '../interfaces/api-responses'; +import { globalProperties } from '../../environments/global-properties'; @Injectable() export class CreateVchWizardService { @@ -328,24 +329,33 @@ export class CreateVchWizardService { }); } - /** - * create an array of observables for DVS host entries - * @param {ComputeResource[]} dvsList - * @returns {Observable[]} - */ - private getDvsHostsEntries(dvsList: ComputeResource[]): Observable[] { - return dvsList.map(dv => { - return this.http.get(`/ui/data/properties/${dv['objRef']}?properties=dvs:dvsHostsData`) - .map(response => response.json()); - }); + /** + * Creates an array of observables for DVS host entries + * @param {ComputeResource[]} dvsList + * @returns {Observable[]} + */ + private getDvsHostsEntries(dvsList: ComputeResource[]): Observable[] { + return dvsList.map(dv => this.getHostsFromComputeResource(dv)); + } + + /** + * Returns all the host contained in a ComputeResource Object (eg: Cluster) + * @param {ComputeResource} obj + * @returns {Observable} + */ + getHostsFromComputeResource(obj: ComputeResource): Observable { + return this.http.get(`${globalProperties.vicService.paths.properties}${obj.objRef}?properties=host`) + .map(response => response.json()) + .map(data => data['host'] ? data['host'] : []); } /** * Get all available portgroups for the selected compute resource * @param dcObj selected datacenter object - * @param resourceObjName name of the selected compute resource + * @param resourceObj the selected compute resource */ - getDistributedPortGroups(dcObj: ComputeResource, resourceObjName?: string): Observable { + getDistributedPortGroups(dcObj: ComputeResource, resourceObj: ComputeResource): Observable { + const resourceObjIsCluster = resourceIsCluster(resourceObj.nodeTypeId); return this.getNetworkingTree(dcObj) .switchMap((networkingResources: ComputeResource[]) => { // gets the list of Dvs from the dc and or any existing network folder @@ -359,31 +369,37 @@ export class CreateVchWizardService { const dvsObs: Observable[] = this.getDvsPortGroups(dvsList); // create an array of observables for DVS host entries - const dvsHostsObs: Observable[] = this.getDvsHostsEntries(dvsList); + const dvsHostsObs: Observable[] = this.getDvsHostsEntries(dvsList); // zip all observables const allDvs = Observable.zip.apply(null, dvsObs); - const allDvsHosts = Observable.zip.apply(null, dvsHostsObs).map(arr => { - return arr.map(dvsHostsData => { - return dvsHostsData['dvs:dvsHostsData']['dvsHosts']; - }); - }); + const allDvsHosts = Observable.zip.apply(null, dvsHostsObs); + + // if the selected resource is a Cluster we need to fetch it hosts in order to validate if some of them is connected to the vds. + const allClusterChilds: Observable = resourceObjIsCluster ? + this.getHostsFromComputeResource(resourceObj) : Observable.of([]); // process the results from the zipped observables wherein only DV port group entries // whose parent distributed virtual switch can be accessed by the specified compute resource should be taken - return Observable.combineLatest(allDvs, allDvsHosts).map(([dvs, dvsHosts]) => { - let results = []; - for (let index = 0; index < dvsHosts.length; index++) { - // if any of the array item's clusterName or hostName property matches resourceObjName, - // it means all portgroups under that switch can be accessed by this compute resource - if (dvsHosts[index].some(computeResource => { - return computeResource['clusterName'] === resourceObjName || computeResource['hostName'] === resourceObjName; - })) { - results = results.concat(dvs[index]); + return Observable.combineLatest(allClusterChilds, allDvs, allDvsHosts) + .map(([clusterChilds, dvs, dvsHosts]) => { + let results = []; + for (let index = 0; index < dvsHosts.length; index++) { + if (resourceObjIsCluster) { + // if the selected resource is a Cluster we need to validate if any of it hosts is connected to the vds. + const clusterChildsHosts = clusterChilds.map(host => host['value']); + if (dvsHosts[index].some(host => clusterChildsHosts.indexOf(host['value']) !== -1 )) { + results = results.concat(dvs[index]); + } + } else { + // if the selected resource is a not Cluster we validate if the selected host is connected to the vds. + if (dvsHosts[index].some(host => host['value'] === getMorIdFromObjRef(resourceObj.objRef))) { + results = results.concat(dvs[index]); + } + } } - } - return flattenArray(results); - }); + return flattenArray(results); + }); }); } diff --git a/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/mocks/create-vch-wizard-mocked-data.ts b/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/mocks/create-vch-wizard-mocked-data.ts index b0b7a56dc..fa956c2e7 100644 --- a/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/mocks/create-vch-wizard-mocked-data.ts +++ b/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/mocks/create-vch-wizard-mocked-data.ts @@ -157,87 +157,49 @@ export const dcDSwitchPorGroupsList = [ ]; export const dvsHostsEntries = [ - Observable.of({ - id: 'urn:vmomi:VmwareDistributedVirtualSwitch:dvs-29:d7c361cc-0a46-441e-8e21-ac22debf7003', - 'dvs:dvsHostsData': { - dvsHosts: [ - { - hostName: '10.192.109.234', - clusterName: null, - connectionState: 'connected', - connectionStateLabel: 'Connected', - hostIconId: 'vsphere-icon-host-warning', - vdsState: 'Up', - vdsStateIcon: 'statusGreen', - hostRef: {value: 'host-94', type: 'HostSystem', serverGuid: 'd7c361cc-0a46-441e-8e21-ac22debf7003'}, - compatibilityErrors: [] - } - ]} - }), - Observable.of({ - id: 'urn:vmomi:VmwareDistributedVirtualSwitch:dvs-25:d7c361cc-0a46-441e-8e21-ac22debf7003', - 'dvs:dvsHostsData': { - dvsHosts: [ - { - hostName: '10.161.251.202', - clusterName: 'New Cluster', - connectionState: 'connected', - connectionStateLabel: 'Connected', - hostIconId: 'vsphere-icon-host-warning', - vdsState: 'Up', - vdsStateIcon: 'statusGreen', - hostRef: {value: 'host-20', type: 'HostSystem', serverGuid: 'd7c361cc-0a46-441e-8e21-ac22debf7003'}, - compatibilityErrors: [] - }, - { - hostName: '10.162.17.176', - clusterName: 'New Cluster', - connectionState: 'connected', - connectionStateLabel: 'Connected', - hostIconId: 'vsphere-icon-host-warning', - vdsState: 'Up', - vdsStateIcon: 'statusGreen', - hostRef: {value: 'host-9', type: 'HostSystem', serverGuid: 'd7c361cc-0a46-441e-8e21-ac22debf7003'}, - compatibilityErrors: [] - } - ]} - }), - Observable.of({ - id: 'urn:vmomi:VmwareDistributedVirtualSwitch:dvs-82:d7c361cc-0a46-441e-8e21-ac22debf7003', - 'dvs:dvsHostsData': { - dvsHosts: [ - { - hostName: '10.192.109.234', - clusterName: null, - connectionState: 'connected', - connectionStateLabel: 'Connected', - hostIconId: 'vsphere-icon-host-warning', - vdsState: 'Up', - vdsStateIcon: 'statusGreen', - hostRef: {value: 'host-94', type: 'HostSystem', serverGuid: 'd7c361cc-0a46-441e-8e21-ac22debf7003'}, - compatibilityErrors: [] - } - ]} - }), - Observable.of({ - id: 'urn:vmomi:VmwareDistributedVirtualSwitch:dvs-86:d7c361cc-0a46-441e-8e21-ac22debf7003', - 'dvs:dvsHostsData': { - dvsHosts: [ - { - hostName: '10.192.109.234', - clusterName: null, - connectionState: 'connected', - connectionStateLabel: 'Connected', - hostIconId: 'vsphere-icon-host-warning', - vdsState: 'Up', - vdsStateIcon: 'statusGreen', - hostRef: {value: 'host-94', type: 'HostSystem', serverGuid: 'd7c361cc-0a46-441e-8e21-ac22debf7003'}, - compatibilityErrors: [] - } - ]} - }) + Observable.of([ + { + serverGuid: 'd7c361cc-0a46-441e-8e21-ac22debf7003', + type: 'HostSystem', + value: 'host-276' + } + ]), + Observable.of([ + { + serverGuid: 'd7c361cc-0a46-441e-8e21-ac22debf7003', + type: 'HostSystem', + value: 'host-277' + }, + { + serverGuid: 'd7c361cc-0a46-441e-8e21-ac22debf7003', + type: 'HostSystem', + value: 'host-278' + } + ]), + Observable.of([ + { + serverGuid: 'd7c361cc-0a46-441e-8e21-ac22debf7003', + type: 'HostSystem', + value: 'host-279' + } + ]), + Observable.of([ + { + serverGuid: 'd7c361cc-0a46-441e-8e21-ac22debf7003', + type: 'HostSystem', + value: 'host-280' + } + ]) ]; +export const clusterHostsChilds = Observable.of([ + { + serverGuid: 'd7c361cc-0a46-441e-8e21-ac22debf7003', + type: 'HostSystem', + value: 'host-276' + } +]); + export const dcMockData = [ { text: 'ha-datacenter', diff --git a/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/networks/networks.component.ts b/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/networks/networks.component.ts index 68534036f..244afe0bf 100644 --- a/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/networks/networks.component.ts +++ b/h5c/vic/src/vic-webapp/src/app/create-vch-wizard/networks/networks.component.ts @@ -37,7 +37,7 @@ export class NetworksComponent implements OnInit { public portgroupsLoading = true; public portgroups: any[] = []; - @Input() resourceObjName: any; + @Input() resourceObj: ComputeResource; @Input() datacenter: ComputeResource; constructor( @@ -138,9 +138,9 @@ export class NetworksComponent implements OnInit { }); } - loadPortgroups(computeResourceObjName: string) { + loadPortgroups(computeResourceObj: ComputeResource) { this.portgroupsLoading = true; - this.createWzService.getDistributedPortGroups(this.datacenter, computeResourceObjName) + this.createWzService.getDistributedPortGroups(this.datacenter, computeResourceObj) .subscribe(v => { this.portgroups = v; this.form.get('bridgeNetwork').setValue(''); @@ -150,9 +150,10 @@ export class NetworksComponent implements OnInit { this.portgroupsLoading = false; }, err => console.error(err)); } + onPageLoad() { if (this.portgroups.length) { - this.loadPortgroups(this.resourceObjName); + this.loadPortgroups(this.resourceObj); return; } @@ -278,7 +279,7 @@ export class NetworksComponent implements OnInit { }); // load portgroups - this.loadPortgroups(this.resourceObjName); + this.loadPortgroups(this.resourceObj); } /** diff --git a/h5c/vic/src/vic-webapp/src/app/interfaces/api-responses.ts b/h5c/vic/src/vic-webapp/src/app/interfaces/api-responses.ts new file mode 100644 index 000000000..f2bc75ef2 --- /dev/null +++ b/h5c/vic/src/vic-webapp/src/app/interfaces/api-responses.ts @@ -0,0 +1,5 @@ +export interface HostTypeInfo { + serverGuid: string; + type: string; + value: string; +} diff --git a/h5c/vic/src/vic-webapp/src/app/shared/constants/nodetype.ts b/h5c/vic/src/vic-webapp/src/app/shared/constants/nodetype.ts index 85a10c687..d91183616 100644 --- a/h5c/vic/src/vic-webapp/src/app/shared/constants/nodetype.ts +++ b/h5c/vic/src/vic-webapp/src/app/shared/constants/nodetype.ts @@ -16,3 +16,29 @@ export const DC_CLUSTER = 'DcCluster'; export const DC_STANDALONE_HOST = 'DcStandaloneHost'; + +export const COMPUTE_RESOURCE_NODE_TYPES = { + dc: { + dc: 'Datacenter' + }, + folder: { + dc_folder: 'DcCompResFolder', + comp_res_folder: 'CompResFolderCompResFolder' + }, + host: { + dc_stand_alone: 'DcStandaloneHost', + cluster_host: 'ClusterHostSystem' + }, + cluster: { + dc_cluster: 'DcCluster', + folder_cluster: 'CompResFolderCluster' + }, + resource_pool: { + resource_pool: 'ResourcePool', + host_resource_pool: 'StandaloneHostResPool', + cluster_resource_pool: 'ClusterResPool', + resource_pool_resource_pool: 'ResPoolResPool', + vic_vch_resource_pool: 'VicVchResourcePool' + } +}; + diff --git a/h5c/vic/src/vic-webapp/src/app/shared/utils/object-reference.ts b/h5c/vic/src/vic-webapp/src/app/shared/utils/object-reference.ts index 9634b6546..514619ef1 100644 --- a/h5c/vic/src/vic-webapp/src/app/shared/utils/object-reference.ts +++ b/h5c/vic/src/vic-webapp/src/app/shared/utils/object-reference.ts @@ -17,6 +17,7 @@ import { VirtualContainerHost } from './../../vch-view/vch.model'; import { ComputeResource } from './../../interfaces/compute.resource'; import { ServerInfo } from '../vSphereClientSdkTypes'; +import {COMPUTE_RESOURCE_NODE_TYPES} from '../constants'; export function getServerServiceGuidFromObj (obj: ComputeResource): string { return obj.objRef.split(':')[4]; @@ -55,3 +56,14 @@ export function getServerInfoByVchObjRef (serversInfo: ServerInfo[], vch: Virtua }); return filtered[0] || null; } + +export function isDesiredType(type: string, types: string[]): boolean { + return types.indexOf(type) !== -1; +} + +export function resourceIsCluster(type: string): boolean { + return isDesiredType(type, [ + COMPUTE_RESOURCE_NODE_TYPES.cluster.dc_cluster, + COMPUTE_RESOURCE_NODE_TYPES.cluster.folder_cluster + ]); +} diff --git a/h5c/vic/src/vic-webapp/src/environments/global-properties.ts b/h5c/vic/src/vic-webapp/src/environments/global-properties.ts new file mode 100644 index 000000000..9ca16da52 --- /dev/null +++ b/h5c/vic/src/vic-webapp/src/environments/global-properties.ts @@ -0,0 +1,11 @@ +export const globalProperties = { + // vic service + vicService: { + paths: { + base: '/ui/vic/rest/data/', + get properties () {return `${this.base}properties/`}, + get list () {return `${this.base}list/`}, + get propertiesByRelation () {return `${this.base}propertiesByRelation/`}, + } + } +};