VMware Cloud Community
Schorschi
Expert
Expert

you have modified the global:DefaultVIServer and global:DefaultVIServers system variables?

I have a rather complex PowerShell/PowerCLI script that watches the vCenter task queue for specific tasks (AddHost_Task and AssociateProfile_Task) and takes action depending on the task found, the parent script spawns another script when appropriate based on the work to be done.  The 'parent' script works, when I run it directly, or within Powershell ISE, spawn of the 'child' script is done via a PowerShell workspace object, and the 'child' script runs as expected as well.  I load the snap-ins and modules needed explicitly, in either script, 'parent' or 'child', so I am not executing in the default PowerCLI profile or shell.  When I run my 'parent' script as a scheduled task, everything runs for a while, apparently fine, until I get the following exception:


You have modified the global:DefaultVIServer and global:DefaultVIServers system variables. This is not allowed. Please reset them to $null and reconnect to the vSphere server.


I am very careful to explicitly open and close my connections, when connecting to a vCenter instance, I open the vCenter connection and keep it open, since the script may run 24/7, I don't close the vCenter connection except when I tell the script to exit. The PowerCLI call that seems to trigger the issue when it happens is a simple Get-VMHost call, I pass in the connection object I got from Connect-VIServer when the script first fired up, so I am not (or so I believe) ever using the 'default' connection information, and to my knowledge i am not changing anything, since I am using the -NotDefault feature of Connect-VIServer cmdlet.


If I explicitly kill the scheduled task and restart it, the issue goes away for a while, but sooner or later, it appears again.  I could not find any information on a Connect-VIServer session timing out, but could that be a factor?  Can someone tell me how this exception happens, what triggers it, and how to avoid it?  I have written a lot of PowerCLI over the years, but have yet to see this issue before.  I have not staged many PowerCLI scripts via Task Scheduler, so want to believe element is a factor, but not entirely sure.


All assistance greatly appreciated, I hit a brick wall with this one.

Reply
0 Kudos
4 Replies
LucD
Leadership
Leadership

When you pass a connection object, obtained by Connect-VIServer, to background job, in a parallel workflow or to a runspace, you shouldn't pass the complete VIServer object.

Instead pass the SessionId property of the VIServer object, and use that value on the Connect-VIServer cmdlet with the Session parameter (see Example 3).


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Schorschi
Expert
Expert

LucD,

Why am I not surprised you chimed in?  Smiley Happy

Does the '-NotDefault' option for Connect-VIServer not provide for isolation of connections?  Well at the very least it will expose PowerCLI calls that maybe using default connections when you don't want that to happen, when I set the '-NotDefault' option, I found a few places in my scripting that were leveraging the default connections, where I had not intended that to happen.  Since I fixed those issues, and still use the '-NotDefault' option, I seem to have eliminated the "you have modified..." issue.  However, I have another issue, I am not sure how to solve now.

Scenario I...

     Scheduled Task:

     Script A (Parent Script)

     User 1 Context (Service Account), not an interactive session

User 1, Script A connects to vCenter

User 1, Script B is invoked by Script A, via a queued, separate (powershell) run-space, connects to vCenter

User 1, Script B does work

User 1, Script B closes vCenter connection

Scenario I Result...

User 1, Script A connection to vCenter lost!

Scenario II...

User 1, Script B runs ad-hoc from interactive environment

User 1, Script B closes vCenter connection

Scenario II Result...

User 1, Script A connection to vCenter lost!

Required Result For Scenario I and II...

User 1, Script B can open and close connections to vCenter at any time, User 1, Script A, never loses its connection to vCenter, regardless of what Script B does, in reference vCenter connections.  Expectation was that separate (powershell) run-space provided session isolation, which it does for powershell but not for PowerCLI apparently. I never want to pass a connection to Script B, I want Script B to have a completely separate connection to vCenter from Script A.

Will what you outlined address my need?  That Script B explicit open/close of connections to vCenter cannot impact Script A?  I think understand what you noted, but not how to implement it, and not entirely sure it will do what I need?  I can't seem to find the Session id value?  How can I get the session id in the first place?  Moreover, I don't think that is what I want to have implemented, what you suggest is that Script A hands off its connection to Script B as a separate session, not a completely separate connection?  Could I may the session id idea work, I think sure, if I have to... But I prefer isolated connections as outlined above if possible.

A temporary fix is to never have Script B close its vCenter connection if Script B is invoked by Script A, but that seems sloppy.  Since Script B can be run at anytime... by User 1 interactively... even while Script A is alive as a scheduled task.

Thoughts?

Reply
0 Kudos
LucD
Leadership
Leadership

Your understanding of the NotDefault switch is correct, it will not store that vSphere server in the $global:defaultviservers variable.

But when you start a Runspace, the $global:defaultviservers variable should normally not be passed to the new runspace (i'll have to check that to be 100% sure).


In scenario I, is that a real .Net runspace, in other words created via [runspacefactory]::CreateRunspacePool ?
Because if it is, I don't see how that would work.
Unless it is because the session is a shared entry on the vCenter, not as much as in the $global:defaultviservers variable.

Did you check the open sessions in vCenter before, during and after the scenarios?


The SessionId is a property in the VIServer object, that is returned by Connect-VIServer


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Schorschi
Expert
Expert

Yup, the core issue I proved out as well with some testing of my own.  For example, I wrote a script that opens 10 connections via Connect-VIServer (no default option used) under the same credentials, into an array.  Then the script closes the 10 connections, however, only the first call to disconnect-VIServer actually works, since the credentials are shared, it appears PowerCLI can't qualify that each connection should be a unique session.

Then modified the script to output the session list, and only one session for the given credentials is listed.  This makes sense under a connection polling strategy.  Each of the 10 connections being in an array can be used as needed, and appear to be separate connections but in reality that is not case at some level.  The session list does not expose the 10 connections, this was something I was hoping for, because then I could try to close connections by explicit match of the session list key, so each script only closes the connect that makes its specific session, i.e. key.  This is what I need, the ability to selectively close any of the 10 connections when I want without impacting the remaining connections... but it appears disconnect-VIServer lacks this flexibility

To get around the issue, I wrote a wrapper around disconnect-VIserver, that only closes a connection when the credentials are unique, if the credentials are shared across connections, only the last script to use any connection with shared credentials actually invokes disconnect-VIserver.  This is not elegant, but since I can control when the various scripts run, and the parent script is always to first script to run, and the last script to stop (short of an exception or such), this does work... just not thrilled with it.  Having come from a straight C programming background, the idea what I leave a connection 'floating' is not something desired.

I really want the connections to be unique, specific, scope/context based.  PowerCLI seems to allow this, as long as 1) each connect is to a separate vCenter instance, or 2) each connection uses separate credentials.  As you noted a PowerShell run space is unique only in the context of PowerShell its-self, PowerCLI shares context at some level (right or wrong?), clearly as the above proves, even if using the -notdefault option, such that the global variables are not used.

If I could figure out how to force connect-VIserver use a unique session key, even if credentials are the same, and each such is listed as unique in the session list, every time it is called, that might work, but since disconnect-VIserver has no option to accept a unique session key, this fails to solve the issue.

As always LucD, thanks for the insight and assistance.  Live and learn!  Smiley Happy

Reply
0 Kudos