def associate_public_ip_addresses(self): """Associate public Ip Addresses to network. *Async command* :return: Cloudstack asynchronous job id :rtype: str :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'associateIpAddress', 'account': self._data['account'], 'domainid': self._data['domainid'], 'networkid': self.id } try: response = self.send_request(params) res = json.loads(response) clsk_job_id = res['associateipaddressresponse']['jobid'] self.logger.debug('Start job - associateIpAddress: %s' % res) return clsk_job_id except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def attach_iso(self, iso_id): """Attaches an ISO to a virtual machine. *Async command* :param str iso_id: the ID of the ISO file :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'attachIso', 'id': iso_id, 'virtualmachineid': self.id } try: response = self.send_request(params) res = json.loads(response) clsk_job_id = res['attachisoresponse']['jobid'] self.logger.debug('Start job over %s.%s - %s: %s' % (self._obj_type, self.name, 'attachIso', res)) return clsk_job_id except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def list_volumes(self): """List virtual machine volumes. """ # get virtual machine info params = { 'command': 'listVolumes', 'listall': 'true', 'virtualmachineid': self.id } try: response = self.send_request(params) res = json.loads(response)['listvolumesresponse'] if len(res) > 0: vols = res['volume'] volumes = [] for vol in vols: volumes.append(Volume(self._orchestrator, vol)) return volumes else: return [] except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def restore(self, templateid=None): """Restore a instance to original template/ISO or new template/ISO. *Async command* :param templateid: an optional template Id to restore instance from the new template. This can be an ISO id in case of restore instance deployed using ISO. :return: Cloudstack asynchronous job id :rtype: str :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'restoreVirtualMachine', 'virtualmachineid': self.id } if templateid: params['templateid'] = templateid try: response = self.send_request(params) res = json.loads(response) clsk_job_id = res['restorevirtualmachineresponse']['jobid'] self.logger.debug( 'Start job over %s.%s - %s: %s' % (self._obj_type, self.name, 'restoreVirtualMachine', res)) return clsk_job_id except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def assign(self, account, domainid, networkids): """Change ownership of a instance from one account to another. A root administrator can reassign a instance from any account to any other account in any domain. A domain administrator can reassign a instance to any account in the same domain. instance must be stopped. :param str account: account name of the new instance owner. :param str domainid: domain id of the new instance owner. :param str networkids: list of new network ids in which the moved instance will participate. :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'assignVirtualMachine', 'virtualmachineid': self.id, 'account': account, 'domainid': domainid, 'networkids': networkids } try: response = self.send_request(params) res = json.loads(response) self._data = res['assignvirtualmachineresponse']['virtualmachine'] except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def extract(self, mode='HTTP_DOWNLOAD'): """Extracts an iso. *Async command* :param mode: the mode of extraction - HTTP_DOWNLOAD [default] or FTP_UPLOAD :return: Cloudstack asynchronous job id :rtype: str :raises ClskError: raise :class:`.base.ClskError` """ params = {'command': 'extractIso', 'id': self.id, 'mode': mode} name = self._data['name'] try: response = self.send_request(params) res = json.loads(response) clsk_job_id = res['extractisoresponse']['jobid'] self.logger.debug( 'Start job over %s.%s - %s: %s' % (self._obj_type, self._data['name'], 'extractIso', res)) return clsk_job_id except KeyError as ex: self.logger.error('Error parsing json data: %s' % ex) raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: self.logger.error(ex) raise ClskError(ex)
def list_volumes(self): '''List storage pool volumes.''' params = { 'command': 'listVolumes', 'listall': 'true', 'zoneid': self._data['zoneid'], } try: response = self.send_request(params) res = json.loads(response)['listvolumesresponse'] if len(res) > 0: data = res['volume'] else: return [] except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex) volumes = [] for item in data: # create Volume instance volume = Volume(self._orchestrator, item) volumes.append(volume) return volumes
def list_virtual_machines(self): """List virtual machines. :return: Dictionary with all host configuration attributes. :rtype: dict :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'listVirtualMachines', 'listall': 'true', 'hostid': self.id } try: response = self.send_request(params) res = json.loads(response)['listvirtualmachinesresponse'] if len(res) > 0: data = res['virtualmachine'] else: return [] except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex) vms = [] for item in data: # create Account instance vm = VirtualMachine(self._orchestrator, item) vms.append(vm) self.logger.debug('List host %s virtual machine: %s' % (self.name, vms)) return vms
def update(self, allocationstate=None, hosttags=None, oscategoryid=None): """Update host. :param allocationstate: Change resource state of host, valid values are [Enable, Disable]. Operation may failed if host in states not allowing Enable/Disable :param hosttags: list of tags to be added to the host :param oscategoryid: the id of Os category to update the host with :return: Dictionary with all host configuration attributes. :rtype: dict :raises ClskError: raise :class:`.base.ClskError` """ params = {'command': 'updateHost', 'id': self.id} if allocationstate: params['allocationstate'] = allocationstate if hosttags: params['hosttags'] = hosttags if oscategoryid: params['oscategoryid'] = oscategoryid try: response = self.send_request(params) res = json.loads(response)['updatehostresponse']['host'][0] self._data = res self.logger.debug('Update host %s' % self.name) return self._data except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def delete_load_balancer_rule(self, load_balancer_rule_id): """Delete load balancer rule *Async command* :param load_balancer_rule_id: the ID of the load balancer rule :return: Cloudstack asynchronous job id :rtype: str :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'deleteLoadBalancerRule', 'id': load_balancer_rule_id } try: response = self.send_request(params) res = json.loads(response) clsk_job_id = res['deleteloadbalancerruleresponse']['jobid'] self.logger.debug('Start job - deleteLoadBalancerRule: %s' % res) return clsk_job_id except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def update_password(self, username, password): """Update password of a host/pool on management server. :param password: the new password for the host/cluster :param username: the username for the host/cluster :return: Dictionary with all host configuration attributes. :rtype: dict :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'updateHostPassword', 'password': password, 'username': username, 'hostid': self.id } try: response = self.send_request(params) res = json.loads(response)['updatehostpasswordresponse']['host'][0] self._data = res self.logger.debug('Update host %s password' % self) return self._data except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def list_load_balancer_rules(self): '''List load balancer rules :return: Dictionary with all network configuration attributes. :rtype: dict :raises ClskError: raise :class:`.base.ClskError` ''' params = { 'command': 'listLoadBalancerRules', 'networkid': self.id, 'listall': True } try: response = self.send_request(params) res = json.loads(response)['listloadbalancerrulesresponse'] if len(res) > 0: data = res['loadbalancerrule'] self.logger.debug('List netwrok %s load balancer rules: %s' % (self.name, data)) return data else: return [] except KeyError as ex: self.logger.error('Error parsing json data: %s' % ex) raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: self.logger.error(ex) raise ClskError(ex)
def delete_port_forward_rule(self, port_forward_rule_id): """Create port forward rules *Async command* :param str port_forward_rule_id: the ID of the firewall rule :return: Cloudstack asynchronous job id :rtype: str :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'deletePortForwardingRule', 'id': port_forward_rule_id } try: response = self.send_request(params) res = json.loads(response) clsk_job_id = res['deleteportforwardingruleresponse']['jobid'] self.logger.debug('Start job - deletePortForwardingRule: %s' % res) return clsk_job_id except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def list_port_forward_rules(self, ipaddressid=None): '''List port forwarding rules :return: Dictionary with all network configuration attributes. :rtype: dict :raises ClskError: raise :class:`.base.ClskError` ''' params = { 'command': 'listPortForwardingRules', 'networkid': self.id, 'listall': True } if ipaddressid: params['ipaddressid'] = ipaddressid try: response = self.send_request(params) res = json.loads(response)['listportforwardingrulesresponse'] if len(res) > 0: data = res['portforwardingrule'] self.logger.debug('List network %s port forwarding rules: %s' % (self.name, data)) return data else: return [] except KeyError as ex: self.logger.error('Error parsing json data: %s' % ex) raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: self.logger.error(ex) raise ClskError(ex)
def add_vmware_dc(self, name, vcenter, username, password): """Adds a VMware datacenter to specified zone. :param name: Name of VMware datacenter to be added to specified zone. :param vcenter: The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server. :param username: The Username required to connect to resource. :param password: The password for specified username. :return: Dictionary with following key: id: The VMware Datacenter ID name: The VMware Datacenter name vcenter: The VMware vCenter name/ip zoneid: the Zone ID associated with this VMware Datacenter :rtype: dict :raises ClskError: raise :class:`.base.ClskError` """ params = {'command':'addVmwareDc', 'zoneid':self.id, 'name':name, 'vcenter':vcenter, 'username':username, 'password':password} try: response = self.send_request(params) res = json.loads(response)['addvmwaredcresponse']['vmwaredc'] data = res except KeyError: raise ClskError('Error parsing json data.') except ApiError as ex: raise ClskError(ex) self.logger.debug('Add vmwaredc %s to zone %s' % (data, self)) return data
def delete(self, forced=None, forcedestroylocalstorage=None): """Deletes a host. :param forced: Force delete the host. All HA enabled vms running on the host will be put to HA; HA disabled ones will be stopped :param forcedestroylocalstorage: Force destroy local storage on this host. All VMs created on this local storage will be destroyed :return: True if operation is executed successfully :rtype: bool :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'deleteHost', 'password': forced, 'username': forcedestroylocalstorage, 'id': self.id } if forced: params['forced'] = forced if forcedestroylocalstorage: params['forcedestroylocalstorage'] = forcedestroylocalstorage try: response = self.send_request(params) res = json.loads(response)['deletehostresponse']['success'] self._data = res self.logger.debug('Delete host %s' % self) return self._data except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def list_accounts(self): """List accounts. :return: List of :class:`Account` :rtype: list :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'listAccounts', 'domainid': self.id, 'response': 'json' } try: response = self.send_request(params) res = json.loads(response)['listaccountsresponse'] if len(res) > 0: data = res['account'] else: data = [] except KeyError: raise ClskError('Error parsing json data.') except ApiError as ex: raise ClskError(ex) accounts = [] for item in data: # create Account instance account = Account(self._orchestrator, item) accounts.append(account) self.logger.debug("List domain %s accounts: %s" % (self.name, accounts)) return accounts
def list_hosts(self): """List hosts. :return: Lis of :class:`.host.Host` :rtype: List :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'listHosts', 'listAll': 'true', 'clusterid': self.id } try: response = self.send_request(params) print response res = json.loads(response)['listhostsresponse'] if len(res) > 0: data = res['host'] else: data = [] except KeyError: raise ClskError('Error parsing json data.') except ApiError as ex: raise ClskError(ex) hosts = [] for item in data: # create Account instance host = Host(self._orchestrator, item) hosts.append(host) self.logger.debug('List cluster %s hosts: %s' % (self.id, hosts)) return hosts
def update(self, bootable=None, displaytext=None, format=None, isdynamicallyscalable=None, isrouting=None, name=None, ostypeid=None, passwordenabled=None): """Update iso :param bootable: true if image is bootable, false otherwise :param displaytext: the display text of the image :param format: the format for the image :param isdynamicallyscalable: true if template/ISO contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory :param isrouting: true if the template type is routing i.e., if template is used to deploy router :param name: the name of the image file :param ostypeid: the ID of the OS type that best represents the OS of this image. :param passwordenabled: true if the image supports the password reset feature; default is false :return: :rtype: dict :raises ClskError: raise :class:`.base.ClskError` """ params = {'command': 'updateIso', 'id': self.id} if bootable: params['bootable'] = bootable if displaytext: params['displaytext'] = displaytext if format: params['format'] = format if isdynamicallyscalable: params['isdynamicallyscalable'] = isdynamicallyscalable if isrouting: params['isrouting'] = isrouting if name: params['name'] = name if ostypeid: params['ostypeid'] = ostypeid if passwordenabled: params['passwordenabled'] = passwordenabled try: response = self.send_request(params) res = json.loads(response)['updateisoresponse'] if len(res) > 0: self._data = res['iso'] self.logger.debug('Update iso %s' % self._data['name']) return self._data else: return None except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def list_pods(self): """List zone pods. :return: List with pods. :rtype: list :raises ClskError: raise :class:`.base.ClskError` """ params = {'command':'listPods', 'listAll':'true', 'zoneid':self.id} try: response = self.send_request(params) res = json.loads(response)['listpodsresponse']['pod'] data = res except KeyError: raise ClskError('Error parsing json data.') except ApiError as ex: raise ClskError(ex) pods = [] for item in data: # create Account instance pod = Pod(self._orchestrator, item) pods.append(pod) self.logger.debug('Get zone %s pods: %s' % (self.name, pods)) return pods
def start(self, hostid=None): """Start virtual machine. *Async command* :param str hostid: id of the host where start instance [optional] :return: Cloudstack asynchronous job id :rtype: str :raises ClskError: raise :class:`.base.ClskError` """ if self.state == 'Running': raise ClskError('Virtual machine is already running.') params = {'command': 'startVirtualMachine', 'id': self.id} if hostid: params['hostid'] = hostid try: response = self.send_request(params) res = json.loads(response) clsk_job_id = res['startvirtualmachineresponse']['jobid'] self.logger.debug( 'Start job over %s.%s - %s: %s' % (self._obj_type, self.name, 'startVirtualMachine', res)) return clsk_job_id except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def list_clusters(self): """List zone clusters. :return: List with clusters. :rtype: list :raises ClskError: raise :class:`.base.ClskError` """ params = {'command':'listClusters', 'listAll':'true', 'zoneid':self.id} response = self.send_request(params) try: response = self.send_request(params) res = json.loads(response)['listclustersresponse']['cluster'] data = res except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex) clusters = [] for item in data: # create Account instance cluster = Cluster(self._orchestrator, item) clusters.append(cluster) self.logger.debug('Get zone %s clusters: %s' % (self.name, clusters)) return clusters
def migrate(self, hostid=None, storageid=None): """Migrate virtual machine. *Async command* :param str hostid: Cloudstack host id :param str storageid: Cloudstack storage id :return: Cloudstack asynchronous job id :rtype: str :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'migrateVirtualMachine', 'virtualmachineid': self.id } if hostid: params['hostid'] = hostid elif storageid: params['storageid'] = storageid try: response = self.send_request(params) res = json.loads(response) clsk_job_id = res['migratevirtualmachineresponse']['jobid'] self.logger.debug( 'Start job over %s.%s - %s: %s' % (self._obj_type, self.name, 'migrateVirtualMachine', res)) return clsk_job_id except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def list_hosts(self): """List zone hosts. :return: List with hosts. :rtype: list :raises ClskError: raise :class:`.base.ClskError` """ params = {'command':'listHosts', 'listAll':'true', 'zoneid':self.id} try: response = self.send_request(params) res = json.loads(response)['listhostsresponse']['host'] data = res except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex) hosts = [] for item in data: # create Account instance host = Host(self._orchestrator, item) hosts.append(host) self.logger.debug('Get zone %s hosts: %s' % (self.name, hosts)) return hosts
def update(self, displayname): """Updates properties of a virtual machine. The instance has to be stopped and restarted for the new properties to take effect. UpdateVirtualMachine does not first check whether the instance is stopped. Therefore, stop the instance manually before issuing this call. TODO: manage device introduced using details :param str displayname: user generated name :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'updateVirtualMachine', 'id': self.id, 'displayname': displayname } try: response = self.send_request(params) res = json.loads(response) self._data = res['updatevirtualmachineresponse']['virtualmachine'] except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def list_configurations(self, page=None, pagesize=None): """Lists zone configurations. :param page: [optional] page number to display :param pagesize: [optional] number of item to display per page :return: Dictionary with following key: id: the value of the configuration, category: the category of the configuration description: the description of the configuration name: the name of the configuration scope: scope(zone/cluster/pool/account) of the parameter that needs to be updated value: the value of the configuration :rtype: dict :raises ClskError: raise :class:`.base.ClskError` """ params = {'command':'listConfigurations', 'zoneid':self.id} if page: params['page'] = page if pagesize: params['pagesize'] = pagesize try: response = self.send_request(params) res = json.loads(response)['listconfigurationsresponse']['configuration'] data = res self.logger.debug('Get zone %s configurations: %s' % (self.id, data)) except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex) return data
def change_password(self): """Resets the password for virtual machine. The virtual machine must be in a "Stopped" state and the template must already support this feature for this command to take effect. *Async command* :return: Cloudstack asynchronous job id :rtype: str :raises ClskError: raise :class:`.base.ClskError` """ params = {'command': 'resetPasswordForVirtualMachine', 'id': self.id} try: response = self.send_request(params) res = json.loads(response) clsk_job_id = res['resetpasswordforvirtualmachineresponse'][ 'jobid'] self.logger.debug('Start job over %s.%s - %s: %s' % (self._obj_type, self.name, 'resetPasswordForVirtualMachine', res)) return clsk_job_id except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)
def update_configuration(self, name, value): """Update zone configuration. :param name: the name of the configuration :param value: the value of the configuration :return: Dictionary with following key: id: the value of the configuration, category: the category of the configuration description: the description of the configuration name: the name of the configuration scope: scope(zone/cluster/pool/account) of the parameter that needs to be updated value: the value of the configuration :rtype: dict :raises ClskError: raise :class:`.base.ClskError` """ params = {'command':'updateConfiguration', 'name':name, 'value':value, 'zoneid':self.id} try: response = self.send_request(params) res = json.loads(response)['updateconfigurationresponse']['configuration'] data = res self.logger.debug('Set zone %s configuration: %s' % (self.id, data)) except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex) return data
def get_graphic_connection_status(self, graphic_type): """"Get graphics connection status for virtual machine. *Extended function* :param graphic_type: spice or vnc :return: Virtual Machine password :rtype: str :raises ClskError: raise :class:`.base.ClskError` """ if self.is_extended() is False: raise NotImplementedError() if self.state != 'Running': raise ClskError('Virtual machine %s is not running.' % self.name) # get hypervisor name hostname = self.hostname # get instance internal name vm_internal_name = self.instancename # get instance hypervisor hypervisor_type = self.hypervisor # KVM hypervisor if hypervisor_type == 'KVM': try: conn = None # get connection to qemu server virt_server = self.get_hypervisor(hostname).get_conn() # create instance of VirtDomain virt_domain = VirtDomain(virt_server, name=vm_internal_name) # get graphics password #deep_data = virt_domain.info() # get graphic status if graphic_type == 'spice': res = virt_domain.spice_connection_status() elif graphic_type == 'vnc': res = virt_domain.vnc_connection_status() else: raise VirtDomainError( "%s connection status is not supported" % graphic_type) # release libvirt connection virt_server.disconnect() del virt_server del virt_domain return res except (VirtDomainError) as ex: self.logger.error(ex) raise ClskError(ex) # other hypervisor else: raise ClskError('Hypervisor %s is not supported' % hypervisor_type) self.logger.info('Get %s graphic connection status for instance : %s' % (graphic_type, self.name))
def remove_vpn_user(self, username): """Removes vpn user. *Async command* :param username: username for the vpn user :return: Cloudstack asynchronous job id :rtype: str :raises ClskError: raise :class:`.base.ClskError` """ params = { 'command': 'removeVpnUser', 'username': username, 'account': self._data['account'], 'domainid': self._data['domainid'], } try: response = self.send_request(params) res = json.loads(response) clsk_job_id = res['removevpnuserresponse']['jobid'] self.logger.debug('Start job - removeVpnUser: %s' % res) return clsk_job_id except KeyError as ex: raise ClskError('Error parsing json data: %s' % ex) except ApiError as ex: raise ClskError(ex)