class ContainerImageCondition(BaseCondition): TREE_NODE = "Container Image" PRETTY = deferred_verpick({ version.LOWEST: "Image", '5.7': "Container Image", }) FIELD_VALUE = deferred_verpick({ version.LOWEST: "Image", '5.7': "Container Image", })
class PolicyProfileAssignable(object): """This class can be inherited by anything that provider load_details method. It provides functionality to assign and unassign Policy Profiles """ manage_policies_tree = deferred_verpick({ version.LOWEST: CheckboxTree("//div[@id='protect_treebox']/ul"), "5.7": BootstrapTreeview("protectbox") }) @property def assigned_policy_profiles(self): try: return self._assigned_policy_profiles except AttributeError: self._assigned_policy_profiles = set([]) return self._assigned_policy_profiles def assign_policy_profiles(self, *policy_profile_names): """ Assign Policy Profiles to this object. Args: policy_profile_names: :py:class:`str` with Policy Profile names. After Control/Explorer coverage goes in, PolicyProfile objects will be also passable. """ map(self.assigned_policy_profiles.add, policy_profile_names) self._assign_unassign_policy_profiles(True, *policy_profile_names) def unassign_policy_profiles(self, *policy_profile_names): """ Unssign Policy Profiles to this object. Args: policy_profile_names: :py:class:`str` with Policy Profile names. After Control/Explorer coverage goes in, PolicyProfile objects will be also passable. """ for pp_name in policy_profile_names: try: self.assigned_policy_profiles.remove(pp_name) except KeyError: pass self._assign_unassign_policy_profiles(False, *policy_profile_names) def _assign_unassign_policy_profiles(self, assign, *policy_profile_names): """DRY function for managing policy profiles. See :py:func:`assign_policy_profiles` and :py:func:`assign_policy_profiles` Args: assign: Wheter to assign or unassign. policy_profile_names: :py:class:`str` with Policy Profile names. """ self.load_details(refresh=True) pol_btn("Manage Policies") for policy_profile in policy_profile_names: if assign: self.manage_policies_tree.check_node(policy_profile) else: self.manage_policies_tree.uncheck_node(policy_profile) form_buttons.save() flash.assert_no_errors()
class ReplicatorControlPolicy(BasePolicy): TYPE = "Control" TREE_NODE = "Replicator" PRETTY = deferred_verpick({ LOWEST: TREE_NODE, "5.9.2": "Container Replicator" })
class ReplicatorCondition(BaseCondition): TREE_NODE = "Replicator" FIELD_VALUE = deferred_verpick({ LOWEST: "Replicator", "5.9.2": "Container Replicator" }) PRETTY = FIELD_VALUE
class ProviderCondition(BaseCondition): TREE_NODE = deferred_verpick({ version.LOWEST: "Container Provider", '5.7.2': "Provider", }) PRETTY = "Provider" FIELD_VALUE = "Provider"
class PodControlPolicy(BasePolicy): TYPE = "Control" TREE_NODE = "Pod" PRETTY = deferred_verpick({ LOWEST: TREE_NODE, "5.9.2": "Container Pod" })
class ContainerNodeControlPolicy(BasePolicy): TYPE = "Control" TREE_NODE = "Container Node" PRETTY = deferred_verpick({ LOWEST: "Node", "5.9.2": TREE_NODE })
class VMControlPolicy(BasePolicy): TYPE = "Control" TREE_NODE = "Vm" PRETTY = deferred_verpick({LOWEST: "VM and Instance"})
class HostControlPolicy(BasePolicy): TYPE = "Control" TREE_NODE = "Host" PRETTY = deferred_verpick({LOWEST: "Host / Node"})
class PhysicalInfrastructureControlPolicy(BasePolicy): TYPE = "Control" TREE_NODE = "Physical Infrastructure" PRETTY = deferred_verpick({LOWEST: "Physical Server"})
class ContainerImageControlPolicy(BasePolicy): TYPE = "Control" TREE_NODE = "Container Image" PRETTY = deferred_verpick({LOWEST: TREE_NODE})
class ContainerNodeCondition(BaseCondition): TREE_NODE = "Container Node" FIELD_VALUE = deferred_verpick({LOWEST: "Node", "5.9.2": "Container Node"}) PRETTY = FIELD_VALUE
class PodCondition(BaseCondition): TREE_NODE = "Pod" FIELD_VALUE = deferred_verpick({LOWEST: "Pod", "5.9.2": "Container Pod"}) PRETTY = FIELD_VALUE
class VMCondition(BaseCondition): TREE_NODE = "VM and Instance" FIELD_VALUE = deferred_verpick({LOWEST: "VM and Instance"}) PRETTY = "VM"
class HostCondition(BaseCondition): TREE_NODE = "Host" FIELD_VALUE = deferred_verpick({LOWEST: "Host / Node"}) PRETTY = "Host / Node"
class ContainerImageCondition(BaseCondition): TREE_NODE = "Container Image" FIELD_VALUE = deferred_verpick({LOWEST: "Container Image"}) PRETTY = "Container Image"
class ProviderCondition(BaseCondition): TREE_NODE = "Provider" FIELD_VALUE = deferred_verpick({LOWEST: "Provider"}) PRETTY = "Provider"
class ProviderControlPolicy(BasePolicy): TYPE = "Control" TREE_NODE = "Provider" PRETTY = deferred_verpick({LOWEST: TREE_NODE})
class Snapshot(object): snapshot_tree = deferred_verpick({ version.LOWEST: Tree("//div[@id='snapshots_treebox']/ul"), '5.7.0.1': BootstrapTreeview('snapshot_treebox')}) def __init__(self, name=None, description=None, memory=None, parent_vm=None): super(Vm.Snapshot, self).__init__() self.name = name self.description = description self.memory = memory self.vm = parent_vm def _nav_to_snapshot_mgmt(self): snapshot_title = '"Snapshots" for Virtual Machine "{}"'.format(self.vm.name) if summary_title() != snapshot_title: self.vm.load_details() sel.click(InfoBlock.element("Properties", "Snapshots")) @property def exists(self): self._nav_to_snapshot_mgmt() title = self.description if self.vm.provider.one_of(RHEVMProvider) else self.name try: self.snapshot_tree.find_path_to( re.compile(r"{}.*?".format(title))) return True except CandidateNotFound: return False except NoSuchElementException: return False except NameError: return False def _click_tree_path(self, prop): """Find and click the given property in a snapshot tree path. Args: prop (str): Property to check (name or description). Returns: None """ self.snapshot_tree.click_path( *self.snapshot_tree.find_path_to(re.compile(prop))) @property def active(self): """Check if the snapshot is active. Returns: bool: True if snapshot is active, False otherwise. """ self._nav_to_snapshot_mgmt() title = self.description if self.vm.provider.one_of(RHEVMProvider) else self.name try: self._click_tree_path(title) if sel.is_displayed_text("{} (Active)".format(title)): return True except CandidateNotFound: return False return False def create(self, force_check_memory=False): snapshot_dict = { 'description': self.description } self._nav_to_snapshot_mgmt() toolbar.select('Create a new snapshot for this VM') if self.name is not None: snapshot_dict['name'] = self.name if force_check_memory or self.vm.provider.mgmt.is_vm_running(self.vm.name): snapshot_dict["snapshot_memory"] = self.memory fill(snapshot_form, snapshot_dict, action=snapshot_form.create_button) wait_for(lambda: self.exists, num_sec=300, delay=20, fail_func=sel.refresh, handle_exception=True) def delete(self, cancel=False): self._nav_to_snapshot_mgmt() title = self.description if self.vm.provider.one_of(RHEVMProvider) else self.name self._click_tree_path(title) toolbar.select('Delete Snapshots', 'Delete Selected Snapshot', invokes_alert=True) sel.handle_alert(cancel=cancel) if not cancel: flash.assert_message_match('Remove Snapshot initiated for 1 ' 'VM and Instance from the CFME Database') wait_for(lambda: not self.exists, num_sec=300, delay=20, fail_func=sel.refresh) def delete_all(self, cancel=False): self._nav_to_snapshot_mgmt() toolbar.select('Delete Snapshots', 'Delete All Existing Snapshots', invokes_alert=True) sel.handle_alert(cancel=cancel) if not cancel: flash.assert_message_match('Remove All Snapshots initiated for 1 VM and ' 'Instance from the CFME Database') def revert_to(self, cancel=False): self._nav_to_snapshot_mgmt() title = self.description if self.vm.provider.one_of(RHEVMProvider) else self.name self._click_tree_path(title) toolbar.select('Revert to selected snapshot', invokes_alert=True) sel.handle_alert(cancel=cancel) flash.assert_message_match('Revert To Snapshot initiated for 1 VM and Instance from ' 'the CFME Database') def refresh(self): self._nav_to_snapshot_mgmt() toolbar.select('Reload current display')
class AzureInstance(Instance): # CFME & provider power control options Added by Jeff Teehan on 5-16-2016 START = "Start" POWER_ON = START # For compatibility with the infra objects. STOP = "Stop" SUSPEND = "Suspend" DELETE = "Delete" TERMINATE = deferred_verpick({ version.LOWEST: 'Terminate', '5.6.1': 'Delete', }) # CFME-only power control options SOFT_REBOOT = "Soft Reboot" HARD_REBOOT = "Hard Reboot" # unsupported by azure, used for negative tests # Provider-only power control options RESTART = "Restart" # CFME power states STATE_ON = "on" STATE_OFF = "off" STATE_SUSPENDED = "suspended" STATE_TERMINATED = "terminated" STATE_UNKNOWN = "unknown" STATE_ARCHIVED = "archived" @property def ui_powerstates_available(self): return { 'on': [self.STOP, self.SUSPEND, self.SOFT_REBOOT, self.TERMINATE], 'off': [self.START, self.TERMINATE] } @property def ui_powerstates_unavailable(self): return { 'on': [self.START], 'off': [self.STOP, self.SUSPEND, self.SOFT_REBOOT] } def create(self, cancel=False, **prov_fill_kwargs): """Provisions an Azure instance with the given properties through CFME Args: cancel: Clicks the cancel button if `True`, otherwise clicks the submit button (Defaults to `False`) prov_fill_kwargs: dictionary of provisioning field/value pairs Note: For more optional keyword arguments, see :py:data:`cfme.cloud.provisioning.ProvisioningForm` """ super(AzureInstance, self).create(form_values=prov_fill_kwargs, cancel=cancel) def power_control_from_provider(self, option): """Power control the instance from the provider Args: option: power control action to take against instance Raises: OptionNotAvailable: option param must have proper value """ if option == AzureInstance.START: self.provider.mgmt.start_vm(self.name) elif option == AzureInstance.STOP: self.provider.mgmt.stop_vm(self.name) elif option == AzureInstance.RESTART: self.provider.mgmt.restart_vm(self.name) elif option == AzureInstance.SUSPEND: self.provider.mgmt.suspend_vm(self.name) elif option == AzureInstance.TERMINATE: self.provider.mgmt.delete_vm(self.name) else: raise OptionNotAvailable(option + " is not a supported action")
class Genealogy(object): """Class, representing genealogy of an infra object with possibility of data retrieval and comparison. Args: o: The :py:class:`Vm` or :py:class:`Template` object. """ genealogy_tree = deferred_verpick({ version.LOWEST: CheckboxTree("//div[@id='genealogy_treebox']/ul"), 5.7: BootstrapTreeview('genealogy_treebox') }) section_comparison_tree = CheckboxTree("//div[@id='all_sections_treebox']/div/table") apply_button = form_buttons.FormButton("Apply sections") mode_mapping = { "exists": "Exists Mode", "details": "Details Mode", } attr_mapping = { "all": "All Attributes", "different": "Attributes with different values", "same": "Attributes with same values", } def __init__(self, o): self.o = o def navigate(self): self.o.load_details() sel.click(InfoBlock.element("Relationships", "Genealogy")) def compare(self, *objects, **kwargs): """Compares two or more objects in the genealogy. Args: *objects: :py:class:`Vm` or :py:class:`Template` or :py:class:`str` with name. Keywords: sections: Which sections to compare. attributes: `all`, `different` or `same`. Default: `all`. mode: `exists` or `details`. Default: `exists`.""" sections = kwargs.get("sections") attributes = kwargs.get("attributes", "all").lower() mode = kwargs.get("mode", "exists").lower() assert len(objects) >= 2, "You must specify at least two objects" objects = map(lambda o: o.name if isinstance(o, (Vm, Template)) else o, objects) self.navigate() for obj in objects: if not isinstance(obj, list): path = self.genealogy_tree.find_path_to(obj) self.genealogy_tree.check_node(*path) toolbar.select("Compare selected VMs") # COMPARE PAGE flash.assert_no_errors() if sections is not None: map(lambda path: self.section_comparison_tree.check_node(*path), sections) sel.click(self.apply_button) flash.assert_no_errors() # Set requested attributes sets toolbar.select(self.attr_mapping[attributes]) # Set the requested mode toolbar.select(self.mode_mapping[mode]) @property def tree(self): """Returns contents of the tree with genealogy""" self.navigate() return self.genealogy_tree.read_contents() @property def ancestors(self): """Returns list of ancestors of the represented object.""" self.navigate() path = self.genealogy_tree.find_path_to(re.compile(r"^.*?\(Selected\)$")) if not path: raise ValueError("Something wrong happened, path not found!") processed_path = [] for step in path[:-1]: # We will remove the (parent) and (Selected) suffixes processed_path.append(re.sub(r"\s*(?:\(Current\)|\(Parent\))$", "", step)) return processed_path
class RHEVMProvider(InfraProvider): catalog_name = deferred_verpick({ version.LOWEST: 'RHEV', '5.9.0.17': 'Red Hat Virtualization', }) type_name = "rhevm" mgmt_class = RHEVMSystem db_types = ["Redhat::InfraManager"] endpoints_form = RHEVMEndpointForm discover_dict = {"rhevm": True} settings_key = 'ems_redhat' # xpath locators for elements, to be used by selenium _console_connection_status_element = '//*[@id="connection-status"]|//*[@id="message-div"]' _canvas_element = '(//*[@id="remote-console"]/canvas|//*[@id="spice-screen"]/canvas)' _ctrl_alt_del_xpath = '//*[@id="ctrlaltdel"]' _fullscreen_xpath = '//*[@id="fullscreen"]' bad_credentials_error_msg = "Credential validation was not successful" ems_events = [('vm_create', { 'event_type': 'USER_ADD_VM_FINISHED_SUCCESS', 'vm_or_template_id': None }), ('vm_stop', { 'event_type': 'USER_STOP_VM', 'vm_or_template_id': None }), ('vm_start', { 'event_type': 'USER_RUN_VM', 'vm_or_template_id': None }), ('vm_delete', { 'event_type': 'USER_REMOVE_VM_FINISHED', 'vm_or_template_id': None })] def __init__(self, name=None, endpoints=None, zone=None, key=None, hostname=None, ip_address=None, start_ip=None, end_ip=None, provider_data=None, appliance=None): super(RHEVMProvider, self).__init__(name=name, endpoints=endpoints, zone=zone, key=key, provider_data=provider_data, appliance=appliance) self.hostname = hostname self.start_ip = start_ip self.end_ip = end_ip if ip_address: self.ip_address = ip_address @property def view_value_mapping(self): return { 'name': self.name, 'prov_type': version.pick({ version.LOWEST: 'Red Hat Virtualization Manager', '5.8.0.10': 'Red Hat Virtualization' }), } def deployment_helper(self, deploy_args): """ Used in utils.virtual_machines """ if 'default_cluster' not in deploy_args: return {'cluster': self.data['default_cluster']} return {} @classmethod def from_config(cls, prov_config, prov_key, appliance=None): endpoints = {} for endp in prov_config['endpoints']: for expected_endpoint in (RHEVMEndpoint, CANDUEndpoint): if expected_endpoint.name == endp: endpoints[endp] = expected_endpoint( **prov_config['endpoints'][endp]) if prov_config.get('discovery_range'): start_ip = prov_config['discovery_range']['start'] end_ip = prov_config['discovery_range']['end'] else: start_ip = end_ip = prov_config.get('ipaddress') return cls(name=prov_config['name'], endpoints=endpoints, zone=prov_config.get('server_zone', 'default'), key=prov_key, start_ip=start_ip, end_ip=end_ip, appliance=appliance) # Following methods will only work if the remote console window is open # and if selenium focused on it. These will not work if the selenium is # focused on Appliance window. def get_console_connection_status(self): try: return self.appliance.browser.widgetastic.selenium.find_element_by_xpath( self._console_connection_status_element).text except: raise ItemNotFound( "Element not found on screen, is current focus on console window?" ) def get_remote_console_canvas(self): try: return self.appliance.browser.widgetastic.selenium.find_element_by_xpath( self._canvas_element) except: raise ItemNotFound( "Element not found on screen, is current focus on console window?" ) def get_console_ctrl_alt_del_btn(self): try: return self.appliance.browser.widgetastic.selenium.find_element_by_xpath( self._ctrl_alt_del_xpath) except: raise ItemNotFound( "Element not found on screen, is current focus on console window?" ) def get_console_fullscreen_btn(self): try: return self.appliance.browser.widgetastic.selenium.find_element_by_xpath( self._fullscreen_xpath) except: raise ItemNotFound( "Element not found on screen, is current focus on console window?" )
class OpenStackInstance(Instance): # CFME & provider power control options START = "Start" # START also covers RESUME and UNPAUSE (same as in CFME 5.4+ web UI) POWER_ON = START # For compatibility with the infra objects. SUSPEND = "Suspend" DELETE = "Delete" TERMINATE = deferred_verpick({ version.LOWEST: 'Terminate', '5.6.1': 'Delete', }) # CFME-only power control options SOFT_REBOOT = "Soft Reboot" HARD_REBOOT = "Hard Reboot" # Provider-only power control options STOP = "Stop" PAUSE = "Pause" RESTART = "Restart" SHELVE = "Shelve" SHELVE_OFFLOAD = "Shelve Offload" # CFME power states STATE_ON = "on" STATE_OFF = "off" STATE_ERROR = "non-operational" STATE_PAUSED = "paused" STATE_SUSPENDED = "suspended" STATE_REBOOTING = "reboot_in_progress" STATE_SHELVED = "shelved" STATE_SHELVED_OFFLOAD = "shelved_offloaded" STATE_UNKNOWN = "unknown" STATE_ARCHIVED = "archived" STATE_TERMINATED = "terminated" @property def ui_powerstates_available(self): return { 'on': [self.SUSPEND, self.SOFT_REBOOT, self.HARD_REBOOT, self.TERMINATE], 'off': [self.START, self.TERMINATE] } @property def ui_powerstates_unavailable(self): return { 'on': [self.START], 'off': [self.SUSPEND, self.SOFT_REBOOT, self.HARD_REBOOT] } def create(self, cancel=False, **prov_fill_kwargs): """Provisions an OpenStack instance with the given properties through CFME Args: cancel: Clicks the cancel button if `True`, otherwise clicks the submit button (Defaults to `False`) prov_fill_kwargs: dictionary of provisioning field/value pairs Note: For more optional keyword arguments, see :py:data:`cfme.cloud.provisioning.ProvisioningForm` """ super(OpenStackInstance, self).create(form_values=prov_fill_kwargs, cancel=cancel) def power_control_from_provider(self, option): """Power control the instance from the provider Args: option: power control action to take against instance Raises: OptionNotAvailable: option param must have proper value """ if option == OpenStackInstance.START: self.provider.mgmt.start_vm(self.name) elif option == OpenStackInstance.STOP: self.provider.mgmt.stop_vm(self.name) elif option == OpenStackInstance.SUSPEND: self.provider.mgmt.suspend_vm(self.name) elif option == OpenStackInstance.PAUSE: self.provider.mgmt.pause_vm(self.name) elif option == OpenStackInstance.SHELVE: # TODO: rewrite it once wrapanapi will get shelve # and shelve_offload methods self.provider.mgmt._find_instance_by_name(self.name).shelve() elif option == OpenStackInstance.SHELVE_OFFLOAD: self.provider.mgmt._find_instance_by_name( self.name).shelve_offload() elif option == OpenStackInstance.RESTART: self.provider.mgmt.restart_vm(self.name) elif option == OpenStackInstance.TERMINATE: self.provider.mgmt.delete_vm(self.name) else: raise OptionNotAvailable(option + " is not a supported action")