VMware Cloud Community
AlfredCrackhamm
Contributor
Contributor

Trouble adding more "CIVM" to a "CIVApp" in vCloud via PowerCLI 5.5

Hi All,

I am having trouble performing some tasks in PowerCLI that I can do easily in the GUI.

Firstly, in the vCloud Director GUI, I can create a new vApp from a template that has one machine in it. I can also do that task from PowerCLI with something like the following code:

  Connect-CIServer -server x.x.x.x -user ***** -org org-development -Password *****
  $myVappName = 'TestApp03'
  $myTemplate = Get-CIVAppTemplate -Name 'vWin2012-Template'
  $myOrgVdc = Get-OrgVdc -Name 'vOrgDevelopment'
  New-CIVApp -Name $myVappName -Description "Testonly." -OrgVdc $myOrgVdc -VAppTemplate $myTemplate
 
If I want to add some more VM's to this newly create vApp 'TestApp03', I can do it easily in the vCloud Director web GUI by browsing to the Virtual machines for the vApp, then on the actions click "add VM".  I can then add several more copies of the VM from the template.


My problem is how do I perform this same action in PowerCLI ?  How to add more machines from an existing template into an existing vApp ?

I want to only use "CI" type cmdlets and avoid having to "Connect-VIServer".
The version of PowerCLI that I have installed is "VMware-PowerCLI-5.5.0-1295336.exe"

Any insights or assistance is greatly appreciated.

Reply
0 Kudos
5 Replies
CSIEnvironments
Enthusiast
Enthusiast

Hi,

We are looking to do the same thing. I tried to use the re-compose option but got an error with the following code:

$vmstoaddnames = "Machine1,Machine2"

$vmstoaddnames = $vmstoaddnames -split(",")

$civapp = get-civapp "Dean Test"

$cat = Get-CIVAppTemplate "Build 29.08"

$vmstoadd =  $cat.ExtensionData.Children.Vm |? { $vmstoaddnames -contains $_.name }

$refstovmstoadd = $vmstoadd | % {

     $ref = new-object vmware.vimautomation.cloud.views.reference

     $ref.href = $_.href

     $ref

}

$recomposeparams = new-object vmware.vimautomation.cloud.views.recomposevappparams

$recomposeparams.CreateItem = $refstovmstoadd

$recompose = $civapp.extensiondata.recomposevapp_task($recomposeparams)

}

Exception setting "CreateItem": "Cannot convert the "VMware.VimAutomation.Cloud.Views.Reference" value of type

"VMware.VimAutomation.Cloud.Views.Reference" to type "VMware.VimAutomation.Cloud.Views.Vm"."

At line:8 char:1

+ $recomposeparams.CreateItem = $refstovmstoadd

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException

    + FullyQualifiedErrorId : ExceptionWhenSetting

Any help would be appreciated....

Reply
0 Kudos
AtanasAtanasov
VMware Employee
VMware Employee

Here is a script that I used to add a VM to a vApp. You would like to trim the parts that you probably don't need (networking, computer name) and probably refine it. Reading it backwards might be easier.

####################

# Creates a VM in a specified vApp. The VM is cloned from a VM template.

# The VM is attached to an Org/VApp Network and its IP is configured.

# Author: Atanas Dimitrov Atanasov (adatanasov@vmware.com)

####################

param(

    $vappName, # The name of the vApp where the workers are added

    $templateVAppName, # The name of the vApp template where the worker template is stored

    $templateVmName, # The name of the worker VM template

    $orgNetName, # The name of the Org network that the worker VM should be connected to.

    $newVMName, # The name of the newly created worker VM

    $compName, # The computer name of the newly created worker VM

    $ipAddress, # The IP address of the newly created worker VM

    $powerOn = $false) # Set to true if you wish to have the newly created worker VM be powered on

    if(!$vappName) { throw "VApp name is required" }

    if(!$templateVAppName) { throw "Template VApp Name is required" }

    if(!$templateVmName) { throw "Template VM name is required" }

    if(!$orgNetName) { throw "Org Network name is required" }

    if(!$compName) { throw "Computer name is required" }

    if(!$newVMName) { throw "The new VM name is required" }

    if(!$ipAddress) { throw "IP address is required is required" }

    # Get API views to the target vApp, the template VM

    $vapp = Get-CIVApp $vappName

    $vappView = $vapp.ExtensionData

    $vmTemplateRecord = Search-Cloud -QueryType "vm" -Name $templateVmName -Filter "IsVAppTemplate==True;ContainerName==$templateVAppName"

    $vmTemplateView = Get-CIView -Id $vmTemplateRecord.Id

    # Get the network name in the template VM and the target vApp

    $netConfigSection = $vappView.Section | where { $_ -is [VMware.VimAutomation.Cloud.Views.NetworkConfigSection] }

    if(!$netConfigSection) { throw "NetworkConfig section not found for the target vApp. Check that the vApp has a vApp/Org network defined." }

    $netConfig = $netConfigSection.NetworkConfig | where { $_.Configuration.ParentNetwork.Name -eq $orgNetName }

    if(!$netConfig) { throw "A network with name '$orgNetName' was not found in the target vApp. Check that the vApp has a vApp/Org network named '$orgNetName'." }

    $netConnectionSection = $vmTemplateView.Section | where { $_ -is [VMware.VimAutomation.Cloud.Views.NetworkConnectionSection] }

    # Assuming 1 network in VM template!!!

    $netConnection = $netConnectionSection.NetworkConnection[0]

    # Define the network settings of the newly created VM by coping the

    # configuration of the template VM and changing the configuration to Static IP.

    [VMware.VimAutomation.Cloud.Views.NetworkConnection] $newNetConnection = New-Object VMware.VimAutomation.Cloud.Views.NetworkConnection

    $newNetConnection.Network = $netConnection.Network

    $newNetConnection.NeedsCustomization = $netConnection.NeedsCustomization

    $newNetConnection.NetworkConnectionIndex = $netConnection.NetworkConnectionIndex

    $newNetConnection.IpAddress = $ipAddress

    $newNetConnection.IsConnected = $netConnection.IsConnected

    #$newNetConnection.MACAddress = $netConnection.MACAddress

    $newNetConnection.IpAddressAllocationMode = "MANUAL"

    [VMware.VimAutomation.Cloud.Views.NetworkConnectionSection] $newNetConnectionSection = New-Object VMware.VimAutomation.Cloud.Views.NetworkConnectionSection

    $newNetConnectionSection.NetworkConnection = ,$newNetConnection

    $newNetConnectionSection.Info = $netConnectionSection.Info

    # Define the mapping between the template VM's network and the vApp network in the target vApp

    $instantiationSection = New-Object VMware.VimAutomation.Cloud.Views.NetworkAssignment

    $instantiationSection.InnerNetwork = $netConnection.Name

    $instantiationSection.ContainerNetwork = $netConfig.Name

    # Define the guest OS settings of the newly created VM by configuring the new Computer Name (hostname).

    $templateGuestSection = $vmTemplateView.Section | where { $_ -is [VMware.VimAutomation.Cloud.Views.GuestCustomizationSection] }

    [VMware.VimAutomation.Cloud.Views.GuestCustomizationSection] $guestSection = `

        New-Object VMware.VimAutomation.Cloud.Views.GuestCustomizationSection

    $guestSection.Enabled = $templateGuestSection.Enabled

    $guestSection.ComputerName = $compName

    $guestSection.Info = $templateGuestSection.Info

    # Define the recomposition specification

    [VMware.VimAutomation.Cloud.Views.SourcedCompositionItemParam] $importedVmItem = `

        New-Object VMware.VimAutomation.Cloud.Views.SourcedCompositionItemParam

    $importedVmItem.Source = New-Object VMware.VimAutomation.Cloud.Views.Reference

    $importedVmItem.Source.Href = $vmTemplateView.Href # Specify the template VM to be used

    $importedVmItem.Source.Name = $newVMName # Specify the name of the newly create VM

    $importedVmItem.InstantiationParams = New-Object VMware.VimAutomation.Cloud.Views.InstantiationParams

    $importedVmItem.InstantiationParams.Section = $newNetConnectionSection, $guestSection # Define the IP and computer name of the new VM

    $importedVmItem.NetworkAssignment = , $instantiationSection # Define the Network mapping of the new VM

    [VMware.VimAutomation.Cloud.Views.SourcedCompositionItemParam[]] $sourcedItem = , $importedVmItem

    Write-Host "Cloning VM '$templateVmName' into vApp '$vappName' under the name '$newVMName' with Computer Name '$compName' attaching its only NIC to network '$orgNetName' with the IP '$ipAddress'"

    $vappView.RecomposeVApp($null, $null , $null, $null, $sourcedItem, $null, $null, $null, $null, $vappView.Name, $vappView.Description)

   

    $newVM = Get-CIVApp -Id $vappView.Id | Get-CIVM -Name $newVmName

   

    if($powerOn)

    {

        $newVM.ExtensionData.PowerOn()

    }

   

    return Get-CIVApp -Id $vappView.Id | Get-CIVM -Name $newVmName

Reply
0 Kudos
AtanasAtanasov
VMware Employee
VMware Employee

Some remarks on your script and the error:

You are trying to assign references to CreateItem. CreateItem is used when you want to create a VM from scratch in the vApp. To use a template VM, set the SourcedItem property instead of CreateItem and set its source to the references that you try to currently assign to CreateItem.

Reply
0 Kudos
CSIEnvironments
Enthusiast
Enthusiast

Thanks Atanas, with some slight modifications I was able to get your script working as expected! I guess I was way off the mark Smiley Happy  Great work!

-Dean

Reply
0 Kudos
Mythili_Krishna
Contributor
Contributor

I am getting the below error on running the RecomposeVApp command :


Exception calling "RecomposeVApp" with "11" argument(s): "The operation failed because no suitable resource was found.

Hub "Resources" doesn't have access to network "ONET_ADMIN_nPROD"."

At line:16 char:5

+     $vappView.RecomposeVApp($null, $null , $null, $null, $sourcedItem, $null, $n ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : CloudException

Could you suggest which access is missing here ? !

Reply
0 Kudos