def _find_dvswitch(server, vlan, datacenter): """Try to find a dvSwitch named as a network.""" netfolder = datacenter.networkFolder._obj dvswitch_resources = server._retrieve_properties_traversal( property_names=['uuid', 'portgroup'], from_node=netfolder, obj_type='DistributedVirtualSwitch') if not dvswitch_resources: return None # Count number of uplinks we can use to make sure that we're not trying to # use an un-initialized DVS for dvswitch in dvswitch_resources: if pysphere.VIProperty(server, dvswitch._obj).summary.numPorts > 0: break else: return None # Find the dvPortgroup that contains a portgroup with the correct VLAN portgroup_key, portgroup_name = _vlan_to_dvs_portgroup_key( server, vlan, datacenter) # Now get the associated dvswitch dvswitch = _portgroup_to_dvswitch(server, dvswitch_resources, portgroup_key) dvswitch_uuid = next(p.Val for p in dvswitch.PropSet if p.Name == 'uuid') dvswitch_name = pysphere.VIProperty(server, dvswitch._obj).summary.name print 'Using VLAN %s on PG %s on DVS %s' % (vlan, portgroup_name, dvswitch_name) return DistributedSwitchPort(dvswitch_uuid, portgroup_key)
def create_dvswitch(vcenter, datacenter, name, uplinks=2): """Create a new DVS.""" switch_folder = pysphere.VIProperty(vcenter, datacenter).networkFolder._obj request = VI.CreateDVS_TaskRequestMsg() _this = request.new__this(switch_folder) _this.set_attribute_type(switch_folder.get_attribute_type()) request.set_element__this(_this) spec = request.new_spec() config = spec.new_configSpec() config.Name = name uplink_policy = ( VI.ns0.DVSNameArrayUplinkPortPolicy_Def('uplink_policy').pyclass()) uplink_policy.UplinkPortName = [ 'Uplink%d' % x for x in range(1, uplinks + 1) ] config.set_element_uplinkPortPolicy(uplink_policy) spec.set_element_configSpec(config) request.set_element_spec(spec) task = vcenter._proxy.CreateDVS_Task(request)._returnval vi_task = pysphere.VITask(task, vcenter) status = vi_task.wait_for_state( [vi_task.STATE_SUCCESS, vi_task.STATE_ERROR]) if status == vi_task.STATE_ERROR: raise CreateDvSwitchError(vi_task.get_error_message())
def provision_vm(server, vm, vlan, datacenter): # Set VMs first NIC to the correct label hardware = pysphere.VIProperty(server, vm).config.hardware nic = next( (x._obj for x in hardware.device if x._type in NET_DEVICE_TYPES), None) if not nic: raise NicNotFoundError('No NIC found') # Only vCenter has the correct notion of a datacenter, so if talking to # an ESXi assume it is called ha-datacenter instead. dc = datacenter if 'vCenter' in server.get_server_type( ) else 'ha-datacenter' datacenter_props = _get_datacenter_props(server, dc) nic.set_element_backing(create_nic_backing(server, vlan, datacenter_props)) # Submit reconfig request # Copy/paste from pysphere mailinglist request = VI.ReconfigVM_TaskRequestMsg() _this = request.new__this(vm) _this.set_attribute_type(vm.get_attribute_type()) request.set_element__this(_this) spec = request.new_spec() dev_change = spec.new_deviceChange() dev_change.set_element_device(nic) dev_change.set_element_operation('edit') spec.set_element_deviceChange([dev_change]) request.set_element_spec(spec) ret = server._proxy.ReconfigVM_Task(request)._returnval task = pysphere.VITask(ret, server) status = task.wait_for_state([task.STATE_SUCCESS, task.STATE_ERROR]) if task.get_state() == task.STATE_ERROR: raise ProvisionVmError(task.get_error_message())
def _vlan_to_network(server, vlan, datacenter): """Given a numeric VLAN, resolve to network name.""" # Fetch VLAN -> network label map hosts = server._retrieve_properties_traversal( property_names=('name', ), obj_type='HostSystem', from_node=datacenter.hostFolder._obj) if not hosts: raise NoHostsInClusterError('Datacenter %s has no hosts' % datacenter.name) prop = pysphere.VIProperty(server, hosts[0].Obj) network_info = prop.configManager.networkSystem.networkInfo # This doesn't work if we have the same VLAN in multiple switches vlan_map = { pg.spec.vlanId: pg.spec.name for pg in network_info.portgroup if pg.spec.name != 'Management Network' } if vlan not in vlan_map: raise UnknownVlanError('VLAN %d not found in any networks' % vlan) return vlan_map[vlan]
def get_server_fqdn(server): """Extract server's configured fqdn.""" host = next(server.get_hosts().iterkeys()) prop = pysphere.VIProperty(server, host) # Prop is a "HostSystem" # http://pubs.vmware.com/vsphere-60/index.jsp#com.vmware.wssdk.apiref.doc/vim.HostSystem.html dnsconfig = prop.config.network.dnsConfig return dnsconfig.hostName + '.' + dnsconfig.domainName
def _get_datacenter_props(server, datacenter): if datacenter is None: datacenter = server.get_datacenters().values()[0] for k, v in server.get_datacenters().iteritems(): if v == datacenter: return pysphere.VIProperty(server, k) raise DatacenterNotFoundError('Found no datacenter named "%s"' % datacenter)
def get_server_ip(server): """Extract server's configured IP.""" host = next(server.get_hosts().iterkeys()) prop = pysphere.VIProperty(server, host) # Prop is a "HostSystem" # http://pubs.vmware.com/vsphere-60/index.jsp#com.vmware.wssdk.apiref.doc/vim.HostSystem.html # TODO soundgoof quick and dirty fix for edgecase for esxi00 mgmt if prop.config.network.vnic[0].spec.ip.ipAddress.startswith('169'): return prop.config.network.vnic[1].spec.ip.ipAddress return prop.config.network.vnic[0].spec.ip.ipAddress
def _get_first_active_cluster(server, datacenter): """Given a server, return the first active cluster.""" compute_resources = server._retrieve_properties_traversal( property_names=('name', 'host'), obj_type='ComputeResource', from_node=datacenter.hostFolder._obj) for compute_resource in compute_resources: compute_resource_props = pysphere.VIProperty(server, compute_resource.Obj) if compute_resource_props.summary.numEffectiveHosts > 0: break else: raise NoHostsInClusterError( 'Tried to create VM, but no available clusters could be found') return compute_resource_props
def add_host_to_dvs(server, host, datacenter, switch, interface): """Add given interface on a host to a dvSwitch.""" host_mor = next(m for m, h in server.get_hosts().iteritems() if h == host) netfolder = pysphere.VIProperty(server, datacenter).networkFolder._obj dvswitch_resources = server._retrieve_properties_traversal( property_names=['config', 'name'], from_node=netfolder, obj_type='DistributedVirtualSwitch') version = None for dvswitch in dvswitch_resources: name = next(p.Val for p in dvswitch.PropSet if p.Name == 'name') config = next(p.Val for p in dvswitch.PropSet if p.Name == 'config') if name == switch: version = config.get_element_configVersion() break else: raise CreateDvSwitchError('Switch %s not found' % switch) request = VI.ReconfigureDvs_TaskRequestMsg() _this = request.new__this(dvswitch._obj) _this.set_attribute_type(dvswitch._obj.get_attribute_type()) request.set_element__this(_this) spec = VI.ns0.VMwareDVSConfigSpec_Def('spec').pyclass() spec.ConfigVersion = version host_spec = spec.new_host() backing = VI.ns0.DistributedVirtualSwitchHostMemberPnicBacking_Def( 'backing').pyclass() pnic_spec = backing.new_pnicSpec() pnic_spec.PnicDevice = interface backing.set_element_pnicSpec([pnic_spec]) host_spec.Backing = backing host_spec.Host = host_mor host_spec.Operation = 'add' spec.set_element_host([host_spec]) request.set_element_spec(spec) task = server._proxy.ReconfigureDvs_Task(request)._returnval vi_task = pysphere.VITask(task, server) status = vi_task.wait_for_state( [vi_task.STATE_SUCCESS, vi_task.STATE_ERROR]) if status == vi_task.STATE_ERROR: raise CreateDvSwitchError(vi_task.get_error_message())
def get_or_create_cluster(vcenter, datacenter, cluster): """Retrieve (or create) a given cluster.""" for folder, name in vcenter.get_clusters().iteritems(): if name == cluster: return folder cluster_folder = pysphere.VIProperty(vcenter, datacenter).hostFolder._obj request = VI.CreateClusterRequestMsg() _this = request.new__this(cluster_folder) _this.set_attribute_type(cluster_folder.get_attribute_type()) request.set_element__this(_this) request.set_element_name(cluster) spec = request.new_spec() drsConfig = spec.new_drsConfig() drsConfig.Enabled = True drsConfig.DefaultVmBehavior = 'fullyAutomated' spec.set_element_drsConfig(drsConfig) request.set_element_spec(spec) return vcenter._proxy.CreateCluster(request)._returnval
def get_ssl_thumbprint(server): """Calculate the SSL thumbprint for a given server.""" # Source: https://groups.google.com/forum/#!topic/pysphere/rio7h8nWDcw host = next(server.get_hosts().iterkeys()) prop = pysphere.VIProperty(server, host) # Prop is a "HostSystem" # http://pubs.vmware.com/vsphere-60/index.jsp#com.vmware.wssdk.apiref.doc/vim.HostSystem.html cert = ''.join(chr(x) for x in prop.config.certificate) # Remove --BEGIN CERTIFICATE-- and --END CERTIFICATE-- cert = ''.join(x for x in cert.split('\n') if not x.startswith('--')).strip() cert_decode = base64.decodestring(cert) cert_digest = hashlib.sha1(cert_decode).hexdigest() # SSL Thumbprint MUST be uppercase for VMware use ssl_thumbprint = ':'.join(cert_digest[i:i + 2] for i in range(0, len(cert_digest), 2)) return ssl_thumbprint.upper()
def create_dvs_portgroup(server, datacenter, switch, name_vlan_map): """Create a new DVS.""" netfolder = pysphere.VIProperty(server, datacenter).networkFolder._obj dvswitch_resources = server._retrieve_properties_traversal( property_names=['name'], from_node=netfolder, obj_type='DistributedVirtualSwitch') for dvswitch in dvswitch_resources: name = next(p.Val for p in dvswitch.PropSet if p.Name == 'name') if name == switch: break else: raise CreateDvSwitchError('Switch %s not found' % switch) request = VI.AddDVPortgroup_TaskRequestMsg() _this = request.new__this(dvswitch._obj) _this.set_attribute_type(dvswitch._obj.get_attribute_type()) request.set_element__this(_this) specs = [] for name, vlan_id in name_vlan_map.iteritems(): if vlan_id is None: continue spec = request.new_spec() spec.Name = name spec.Type = 'earlyBinding' spec.NumPorts = 0 vlan = VI.ns0.VmwareDistributedVirtualSwitchVlanIdSpec_Def( 'vlan').pyclass() vlan.Inherited = False vlan.VlanId = vlan_id port_config = VI.ns0.VMwareDVSPortSetting_Def('port_config').pyclass() port_config.Vlan = vlan spec.DefaultPortConfig = port_config specs.append(spec) request.set_element_spec(specs) task = server._proxy.AddDVPortgroup_Task(request)._returnval vi_task = pysphere.VITask(task, server) status = vi_task.wait_for_state( [vi_task.STATE_SUCCESS, vi_task.STATE_ERROR]) if status == vi_task.STATE_ERROR: raise CreateDvPortgroupError(vi_task.get_error_message())