VMware {code} Community
Carmageddon
Contributor
Contributor

Trying to write a script which would change MAC address of a VM by vm_name

Hello!

First wanted to say thanks for all the stuff I've found so far by the community (especially William Lam, in my case).

Currently I am in a dire need to figure out, how to change the MAC of a machine.

After reading the vSphere SDK for Perl documentation, and successfully writing (or at least understanding hehe) scripts to retrieve information as well as do simple actions such as reboot/poweron etc, I've moved on to changing properties of virtual machines.

My current task (small part of a bigger project actually), is to be able to get as parameter, a MAC address and VM name, then find the VM, and modify the MAC address (it will only have one...)

I have tried following the Documentation, in the section about "Modifying Property Values"

As you can see in my attached Perl code, line 74 is: $newMAC = $_->macAddress($parsedMAC);

Which is like the Documentation example, and actually gives no errors when ran - except MAC doesn't change!

I've tried everything I could think of, but in other variations or scopes, there are errors about not found methods/objects etc, so pretty sure I am on the right track at least.

Finally I managed to find William's vmNICManagement.pl - which is exactly for changing MAC! (mind you, it was NOT easy to find heh).

I looked at the code first, trying to understand how is that different from what I tried, and I still cant understand why does he have so many more parameters such as $vnic_device,$vnic_name and then doing a lot of checks about properties that don't exist as far as I am aware - I work according to: http://pubs.vmware.com/vi30/sdk/ReferenceGuide/vim.vm.device.VirtualEthernetCard.html

There should only be 3 properties....

Anyhow, I gave it a try, but Lam's script gives this error to me:

Can't locate object method "network" via package "VirtualEthernetCardDistributedVirtualPortBackingInfo" at /usr/lib/vmware-vcli/apps/vm/vmNICManagement.pl line 123.

Which is not surprising, cause this property doesn't exist according to API documentation.

If I am wrong or don't understand, please correct me... Been trying to get it fixed the whole working day Smiley Sad

I also tried to understand the values of the variables in his updatemac function, added a print line which prints:

vnic_device is: VirtualPCNet32=HASH(0xa9ee57c), vnic_name is: Network adapter 1

I know the machine was created with an E1000 adaptor, so this is what I specify when I try running his script.

I hope someone can give me some help with this.. I am getting the feel my code is pretty close to being right and (as usual in programming..) missing something small Smiley Happy

Thanks!

14 Replies
Carmageddon
Contributor
Contributor

Since I cant edit above post, I also tried adding this to my script:

$newMAC = $_->macAddress($parsedMAC);

$task_ref = $vm_view->ReconfigVM_Task(spec => $newMAC);

But I get: Can't call method "ReconfigVM_Task" on unblessed reference at /usr/lib/vmware-vcli/apps/vm/ChangeMAC.pl line 75.

So, how do I make it a blessed reference?

Reply
0 Kudos
lamw
Community Manager
Community Manager

Take a look at this script which does exactly what you want -

=========================================================================

William Lam

VMware vExpert 2009,2010

VMware scripts and resources at:

Twitter: @lamw

Getting Started with the vMA (tips/tricks)

Getting Started with the vSphere SDK for Perl

VMware Code Central - Scripts/Sample code for Developers and Administrators

VMware Developer Community

If you find this information useful, please award points for "correct" or "helpful".

Carmageddon
Contributor
Contributor

William please note I did try running your script but got the error: Can't locate object method "network" via package "VirtualEthernetCardDistributedVirtualPortBackingInfo" at /usr/lib/vmware-vcli/apps/vm/vmNICManagement.pl line 123.

Which makes sense because there is no such attribute in the VirtualEthernetCard data type - I explained it all in the original post, perhaps it is a bit too lengthy though.

I am also looking for an explanation why mine doesn't work, and how yours is supposed to work - I wrote everything as per the documentation, I think, so what did I do wrong?

William is there any way to contact you? I cant seem to find email or anything beside tweeter but that's not a two way communication tool Smiley Wink

Reply
0 Kudos
lamw
Community Manager
Community Manager

First off, I don't do any personal email or PM support, post any questions or comments you have on the VMTN forums, that's what it is for.

Second, you're lacking quite a bit in your script to properly update a device. Take a look at the script I reference on a vNIC with standard portgroup and understand how to obtain the correct device and proper config spec to update the MAC. One you understand how that works, then you should be able to apply that to update a vNIC that is connected to a distributed portgroup.

=========================================================================

William Lam

VMware vExpert 2009,2010

VMware scripts and resources at:

Twitter: @lamw

Getting Started with the vMA (tips/tricks)

Getting Started with the vSphere SDK for Perl

VMware Code Central - Scripts/Sample code for Developers and Administrators

VMware Developer Community

If you find this information useful, please award points for "correct" or "helpful".

Carmageddon
Contributor
Contributor

William, my issue with analyzing how your script works, it two-folded:

1) Due to the error I get on line 123, I cant reach the actual creation and watch it via debugger like I want

2) I found no documentation for a lot of things you use in your script, such as mo_ref => $vnic_device->backing->network

There is no documentation on mo_ref for vSphere 4 anywhere, also the whole section of: if($nictype eq 'VirtualE1000') {.....}

Uses things I am not sure where are they documented. If you look at page 29 of the SDK for Perl Programming Guide documentation, it's instructions on how to modify a property, are very different from how you do it. - thats why I am having troubles understanding that.

I will also point out, that your other script (which finds a machine name by its MAC), actually works exactly as per the documentation, eg it goes to $vm->config->hardware->device->VirtualEthernetCard and then accesses the macAddress property - simple, identical to what the API says about that object.

Now from here when I get back to 1 and 2, I cant understand why suddenly everything changes, the moment I want to modify the value of the field?

Reply
0 Kudos
lamw
Community Manager
Community Manager

When you refer to documentation, the vSphere SDK for Perl programming guide only deal with the syntax using the Perl SDK. The actual vSphere API documentation in terms of the object names and properties, is what you'll need to use - http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/index.html

If you're new to vSphere API/SDK, I would recommend first off checking out -

If I understand you correctly, you're trying to update a MAC Address on a VMs vNIC? The script that I have provided does exactly that but only supports a VM that is connected to a standard portgroup and not a distributed portgroup. To better understand the script and the logic, I would recommend you start off with a simple example of updating a MAC Address on a VM with regular portgroup, if you feel that you fully understand that, then you should tackle the distributed portgroup task which is what you're trying to do.

Hopefully this makes more sense

=========================================================================

William Lam

VMware vExpert 2009,2010

VMware scripts and resources at:

Twitter: @lamw

Getting Started with the vMA (tips/tricks)

Getting Started with the vSphere SDK for Perl

VMware Code Central - Scripts/Sample code for Developers and Administrators

VMware Developer Community

If you find this information useful, please award points for "correct" or "helpful".

Reply
0 Kudos
Carmageddon
Contributor
Contributor

Thank you.

I've followed your links and started digging deeper, although a lot of the PDF documents seem very outdated using very old (2006-2007) versions of the Perl API.

About the ReferenceGuide - is there any way to present it in a UML like way, or some way I could comfortably print it out? I find it hard to link all the bits and pieces in my head, and it helps seeing who inherits what etc, when its printed and easy to follow from one page to the next. Or better yet, a nice printout of the entire VM object, the way debugger shows - I think this would help.

I have another idea for approaching this problem: Will creating a VM with custom MAC pre-defined, be easier than modifying? (I will need to do it anyway on the next step of the project..)

Yes you understood correctly I think - I will put it in my words: I need to change the VM's ethernet adapter's MAC, because this is how DHCP server handles out IPs etc. (Or alternatively and even better, create the VM with the right MAC from the start).

I am not sure what is standard portgroup, and distributed portgroup - is this part of the API? if not where do I check, which kind of ethernet adapter our VMs use?

I will try your suggestion and create a VM with standard default NIC tomorrow at work, and see if the change MAc works then, and take it from there.

Although I am beginning to think creating VM with the right mac from the start, should be easier?

If I specify it in the config XML file I pass to create_VM method, how would I define this? can I simply take the elements names from a sample VMX file, add it to the XML file and it will understand what to do with the special elements? beside the trivial ones such as Disksize etc?

Reply
0 Kudos
lamw
Community Manager
Community Manager

Before getting in too deep, I would recommend you spend some time looking at this documentation first -

You'll want to get a good understanding of the vSphere API object model before attempting to writing your own scripts, else it can potentially be confusing.

=========================================================================

William Lam

VMware vExpert 2009,2010

VMware scripts and resources at:

Twitter: @lamw

Getting Started with the vMA (tips/tricks)

Getting Started with the vSphere SDK for Perl

VMware Code Central - Scripts/Sample code for Developers and Administrators

VMware Developer Community

If you find this information useful, please award points for "correct" or "helpful".

Reply
0 Kudos
Carmageddon
Contributor
Contributor

Ok.. after thinking, perhaps it would be much easier to customize the MAC address, when I create the machine instead?

using vmware-vsphere-cli-distrib/apps/vm/vmclone.pl , I can ask it to clone the machine while customizing the VM using an XMLll file.

They give some examples in the documentation for things such as:

However, I cant find the corresponding settings in the VMX file.

What I want to do, is esentially clone from template (which works) BUT, I want to do it with customizing the VM using the XML file, which would contain configspecs equal to these from the VMX file:

ethernet0.present = "TRUE"

ethernet0.virtualDev = "e1000"

ethernet0.dvs.switchId = "long HEX address"

ethernet0.dvs.portId = "510"

ethernet0.dvs.portgroupId = "dvportgroup-712"

ethernet0.dvs.connectionId = "1946534217"

ethernet0.addressType = "static"

ethernet0.address = "00:50:56:30:00:13"

Now, how do I find the equivalents of these for XML file? From all my searches and readings, the documentation is spread all over and in my cases not complete, I would love if you could point me to specifics - maybe I missed something?

Anyhow, of the above VMX settings, I think I only need to do ethernet0.present, ethernet0.virtualDev, ethernet0.dvs.switchId = "some HEX address", ethernet0.addressType and ethernet0.address, and everything else would be adjusted by VMware (as the port is unique per each VM).

Am I right? if not, how would you suggest I do it? and by the way, you were right William, we do indeed use Distributed Ports, but since I cant find such setting in the VMX file, I must assume it comes from the switch?

I not, how would you suggest I clone the template, using a custom MAC? (I can specify the template - it could be without a NIC, or with it, but seems much more difficult to change it).

Reply
0 Kudos
Carmageddon
Contributor
Contributor

William I got it working, took a while but I changed your script a bit. I dont know why did you do stuff such as:

my $network = Vim::get_view(mo_ref => $vnic_device->backing->network, properties => );

Its not needed I disabled ALL of that stuff, and changed all 4 devices in the following fashion (your old setting commented out):

if($nictype eq 'VirtualE1000') {

#$newNetworkDevice = VirtualE1000->new(key => $vnic_device->key, unitNumber => $vnic_device->unitNumber, controllerKey => $vnic_device->controllerKey, backing => $backing_info, addressType => 'Manual', macAddress => $mac);

$newNetworkDevice = VirtualE1000->new(key => $vnic_device->key, unitNumber => $vnic_device->unitNumber, controllerKey => $vnic_device->controllerKey, backing => $vnic_device->backing, addressType => 'Manual', macAddress => $mac, deviceInfo => $vnic_device->deviceInfo, wakeOnLanEnabled => $vnic_device->wakeOnLanEnabled, connectable => $vnic_device->connectable);

As you can see, your old objects contained too few sub-objects, and I have no idea why did you read them to separate variables earlier, just to give them again here - doing backing => $vnic_device->backing is UNIVERSAL, and should work for any nic - why did you go to backing->network? you didn't need anything there in order to complete the script's task.

In any case, thanks again! although not a direct help, you did send me time and time again to look at your script Smiley Happy

Hope you update your published one to be universal.

Reply
0 Kudos
lamw
Community Manager
Community Manager

Glad you got it working, but I seriously no clue what you're trying to say.

Hope you update your published one to be universal.I'm not sure I follow this as well, what do you mean "universal". It supports all 4 types of vNIC (e1000,pcnet32,vmxnet2 and vmxnet3)

In any case, the script is provide as an example and has been tested against all 4 types of vNIC. I encourage users to modify and tweak these scripts to fit their operating environment. Regarding the limited sub-properties, if you look at the API docs, not all of them are required ... this really depends on what you need configured and again, it may vary based on your requirements.

Thanks

=========================================================================

William Lam

VMware vExpert 2009,2010

VMware scripts and resources at:

Twitter: @lamw

Getting Started with the vMA (tips/tricks)

Getting Started with the vSphere SDK for Perl

VMware Code Central - Scripts/Sample code for Developers and Administrators

VMware Developer Community

If you find this information useful, please award points for "correct" or "helpful".

Reply
0 Kudos
Carmageddon
Contributor
Contributor

Glad you got it working, but I seriously no clue what you're trying to say.

Hope you update your published one to be universal.I'm not sure I follow this as well, what do you mean "universal". It supports all 4 types of vNIC (e1000,pcnet32,vmxnet2 and vmxnet3)

In any case, the script is provide as an example and has been tested against all 4 types of vNIC. I encourage users to modify and tweak these scripts to fit their operating environment. Regarding the limited sub-properties, if you look at the API docs, not all of them are required ... this really depends on what you need configured and again, it may vary based on your requirements.

Thanks

ok I will try explaining again:

What I meant is, your script currently tries to retrieve information from sub-objects in the VM tree such as "Backing" and then some sub-object in it etc (which doesnt always exist for everyone who uses the script), and is are not neccesary information for the changing MAC procedure - hence why your original script failed for me.

Instead, I just modified your call to the New constructor, and inside simply copied all the attributes inside my NIC.

What I am saying, perhaps we should simply write a script that would automatically check first if certain attribute exists, if it does, copy it to the new object as well (eventually ending up with perfect copy, and only changing macAddress and the "Static" thing.

And then issuing the Reconfigure task.

The point is, such script would work "universally" for all people, regardless if they have Distributed NIC, normal nic, 100 attributes to their NIC, or only 5.

Reply
0 Kudos
yiruzhang1
Contributor
Contributor

HI, I have the same issue to use the vmNICManagement.pl. I tried query option. But coplains about

Can't locate object

method "network" via package

"VirtualEthernetCardDistributedVirtualPortBackingInfo" at

/usr/lib/vmware-vcli/apps/vm/vmNICManagement.pl line 111.

(my $network = Vim::get_view(mo_ref => $vnic_device->backing->network, properties => );)

Is that because the"backing" doesn't have this object?

Can you post your midified script?

Thanks a lot.

Reply
0 Kudos
yiruzhang1
Contributor
Contributor

Hi, I read your post again. you changed William's script to

$newNetworkDevice = VirtualE1000->new(key => $vnic_device->key, unitNumber => $vnic_device->unitNumber,

controllerKey => $vnic_device->controllerKey, backing =>

$vnic_device->backing, addressType => 'Manual',

macAddress

=> $mac, deviceInfo => $vnic_device->deviceInfo,

wakeOnLanEnabled => $vnic_device->wakeOnLanEnabled, connectable

=> $vnic_device->connectable);

So you use $vnic_device->backing for the $newNetworkDevice's backing.

If I just want to add a vnic. (not change the existing mac), whabacking I should use?

Thanks.

Yiru

Reply
0 Kudos