class TestDriverHelper(TestCase): def setUp(self): self.helper = CloudshellDriverHelper() self.helper.cloudshell_data_retriever_service = Mock() self.helper.cloudshell_data_retriever_service.getVCenterConnectionDetails = Mock( return_value=True) self.helper.session_class = Mock() self.context = Mock() self.context.connectivity = Mock() self.context.connectivity.serverAddress = 'host' self.context.connectivity.adminAuthToken = 'token' self.context.reservation = Mock() self.context.reservation.domain = 'domain' def test_get_session(self): self.helper.get_session(self.context.connectivity.serverAddress, self.context.connectivity.adminAuthToken, self.context.reservation.domain) self.assertTrue( self.helper.session_class.called_with( self.context.connectivity.serverAddress, self.context.connectivity.adminAuthToken, 'admin', 'admin', self.context.reservation.domain)) def test_get_connection_details(self): session = Mock() vcenter_data_model = Mock() res = self.helper.get_connection_details(session, vcenter_data_model, self.context) self.assertTrue(res)
class TestDriverHelper(TestCase): def setUp(self): self.helper = CloudshellDriverHelper() self.helper.cloudshell_data_retriever_service = Mock() self.helper.cloudshell_data_retriever_service.getVCenterConnectionDetails = Mock(return_value=True) self.helper.session_class = Mock() self.context = Mock() self.context.connectivity = Mock() self.context.connectivity.serverAddress = "host" self.context.connectivity.adminAuthToken = "token" self.context.reservation = Mock() self.context.reservation.domain = "domain" def test_get_session(self): self.helper.get_session( self.context.connectivity.serverAddress, self.context.connectivity.adminAuthToken, self.context.reservation.domain, ) self.assertTrue( self.helper.session_class.called_with( self.context.connectivity.serverAddress, self.context.connectivity.adminAuthToken, "admin", "admin", self.context.reservation.domain, ) ) def test_get_connection_details(self): session = Mock() vcenter_data_model = Mock() res = self.helper.get_connection_details(session, vcenter_data_model, self.context) self.assertTrue(res)
def __init__(self): super(PaloAltoStaticShellDriver, self).__init__() self._cli = None self.cs_helper = CloudshellDriverHelper() self.model_parser = ResourceModelParser() self.ip_manager = VMIPManager() self.task_waiter = SynchronousTaskWaiter() self.pv_service = pyVmomiService(SmartConnect, Disconnect, self.task_waiter)
def setUp(self): self.helper = CloudshellDriverHelper() self.helper.cloudshell_data_retriever_service = Mock() self.helper.cloudshell_data_retriever_service.getVCenterConnectionDetails = Mock( return_value=True) self.helper.session_class = Mock() self.context = Mock() self.context.connectivity = Mock() self.context.connectivity.serverAddress = 'host' self.context.connectivity.adminAuthToken = 'token' self.context.reservation = Mock() self.context.reservation.domain = 'domain'
def __init__(self): self.cs_helper = CloudshellDriverHelper() self.model_parser = ResourceModelParser() self.ip_manager = VMIPManager() self.task_waiter = SynchronousTaskWaiter() self.logger = get_qs_logger('VM AutoLoad') self.pv_service = pyVmomiService(SmartConnect, Disconnect, self.task_waiter)
class DeployFromImage(ResourceDriverInterface): def cleanup(self): pass def __init__(self): self.cs_helper = CloudshellDriverHelper() self.resource_model_parser = ResourceModelParser() def initialize(self, context): pass def Deploy(self, context, Name=None): """ Deploys app from image :type context: models.QualiDriverModels.ResourceCommandContext """ session = self.cs_helper.get_session( context.connectivity.server_address, context.connectivity.admin_auth_token, context.reservation.domain) # get vCenter resource name, template name, template folder vcenter_image_resource_model = \ self.resource_model_parser.convert_to_resource_model(context.resource, vCenterVMFromImageResourceModel) vcenter_res = vcenter_image_resource_model.vcenter_name if not Name: Name = jsonpickle.decode( context.resource.app_context.app_request_json)['name'] deployment_info = self._get_deployment_info( vcenter_image_resource_model, Name) result = session.ExecuteCommand( context.reservation.reservation_id, vcenter_res, "Resource", "deploy_from_image", self._get_command_inputs_list(deployment_info), False) return result.Output def _get_deployment_info(self, image_model, name): """ :type image_model: vCenterVMFromImageResourceModel """ return DeployDataHolder({ 'app_name': name, 'image_params': image_model }) def _get_command_inputs_list(self, data_holder): return [ InputNameValue('deploy_data', jsonpickle.encode(data_holder, unpicklable=False)) ]
def setUp(self): self.helper = CloudshellDriverHelper() self.helper.cloudshell_data_retriever_service = Mock() self.helper.cloudshell_data_retriever_service.getVCenterConnectionDetails = Mock(return_value=True) self.helper.session_class = Mock() self.context = Mock() self.context.connectivity = Mock() self.context.connectivity.serverAddress = "host" self.context.connectivity.adminAuthToken = "token" self.context.reservation = Mock() self.context.reservation.domain = "domain"
class DeployFromImage(ResourceDriverInterface): def cleanup(self): pass def __init__(self): self.cs_helper = CloudshellDriverHelper() self.resource_model_parser = ResourceModelParser() def initialize(self, context): pass def Deploy(self, context, Name=None): """ Deploys app from image :type context: models.QualiDriverModels.ResourceCommandContext """ session = self.cs_helper.get_session(context.connectivity.server_address, context.connectivity.admin_auth_token, context.reservation.domain) # get vCenter resource name, template name, template folder vcenter_image_resource_model = \ self.resource_model_parser.convert_to_resource_model(context.resource, vCenterVMFromImageResourceModel) vcenter_res = vcenter_image_resource_model.vcenter_name if not Name: Name = jsonpickle.decode(context.resource.app_context.app_request_json)['name'] deployment_info = self._get_deployment_info(vcenter_image_resource_model, Name) result = session.ExecuteCommand(context.reservation.reservation_id, vcenter_res, "Resource", "deploy_from_image", self._get_command_inputs_list(deployment_info), False) return result.Output def _get_deployment_info(self, image_model, name): """ :type image_model: vCenterVMFromImageResourceModel """ return DeployDataHolder({'app_name': name, 'image_params': image_model }) def _get_command_inputs_list(self, data_holder): return [InputNameValue('deploy_data', jsonpickle.encode(data_holder, unpicklable=False))]
class DeployFromTemplateDriver(ResourceDriverInterface): def __init__(self): self.resource_model_parser = ResourceModelParser() self.cs_helper = CloudshellDriverHelper() def cleanup(self): pass def initialize(self, context): pass def Deploy(self, context, Name=None): """ Deploys app from template :type context: models.QualiDriverModels.ResourceCommandContext :param Name: Name of the Deployment :type Name: str :rtype: str """ session = self.cs_helper.get_session( context.connectivity.server_address, context.connectivity.admin_auth_token, context.reservation.domain) vcenter_template_resource_model = \ self.resource_model_parser.convert_to_resource_model(context.resource, vCenterVMFromTemplateResourceModel) if not Name: Name = jsonpickle.decode( context.resource.app_context.app_request_json)['name'] deploy_from_template_details = DeployFromTemplateDetails( vcenter_template_resource_model, Name) params = [ InputNameValue( 'deploy_data', jsonpickle.encode(deploy_from_template_details, unpicklable=False)) ] reservation_id = context.reservation.reservation_id result = session.ExecuteCommand( reservation_id, vcenter_template_resource_model.vcenter_name, "Resource", "deploy_from_template", params, False) return result.Output
class DeployCloneFromVMDriver(ResourceDriverInterface): def __init__(self): self.resource_model_parser = ResourceModelParser() self.cs_helper = CloudshellDriverHelper() def cleanup(self): pass def initialize(self, context): pass def Deploy(self, context, Name=None): """ Deploys app from template :type context: models.QualiDriverModels.ResourceCommandContext :param Name: Name of the Deployment :type Name: str :rtype: str """ session = self.cs_helper.get_session(context.connectivity.server_address, context.connectivity.admin_auth_token, context.reservation.domain) vcenter_template_resource_model = \ self.resource_model_parser.convert_to_resource_model(context.resource, VCenterDeployVMFromLinkedCloneResourceModel) if not Name: Name = jsonpickle.decode(context.resource.app_context.app_request_json)['name'] deploy_from_template_details = DeployFromTemplateDetails(vcenter_template_resource_model, Name) params = [InputNameValue('deploy_data', jsonpickle.encode(deploy_from_template_details, unpicklable=False))] reservation_id = context.reservation.reservation_id result = session.ExecuteCommand(reservation_id, vcenter_template_resource_model.vcenter_name, "Resource", "deploy_from_linked_clone", params, False) return result.Output
class DeployAppOrchestrationDriver(object): def __init__(self): self.cs_helper = CloudshellDriverHelper() self.model_parser = ResourceModelParser() self.ip_manager = VMIPManager() self.task_waiter = SynchronousTaskWaiter() self.logger = get_qs_logger('VM AutoLoad') self.pv_service = pyVmomiService(SmartConnect, Disconnect, self.task_waiter) def get_inventory(self, context): """ Will locate vm in vcenter and fill its uuid :type context: cloudshell.shell.core.context.ResourceCommandContext """ vcenter_vm_name = context.resource.attributes['vCenter VM'] vcenter_vm_name = vcenter_vm_name.replace('\\', '/') vcenter_name = context.resource.attributes['vCenter Name'] self.logger.info('start autoloading vm_path: {0} on vcenter: {1}'.format(vcenter_vm_name, vcenter_name)) session = self.cs_helper.get_session(context.connectivity.server_address, context.connectivity.admin_auth_token, DOMAIN) vcenter_api_res = session.GetResourceDetails(vcenter_name) vcenter_resource = self.model_parser.convert_to_vcenter_model(vcenter_api_res) si = None try: self.logger.info('connecting to vcenter ({0})'.format(vcenter_api_res.Address)) si = self._get_connection_to_vcenter(self.pv_service, session, vcenter_resource, vcenter_api_res.Address) self.logger.info('loading vm uuid') vm_loader = VMLoader(self.pv_service) uuid = vm_loader.load_vm_uuid_by_name(si, vcenter_resource, vcenter_vm_name) self.logger.info('vm uuid: {0}'.format(uuid)) self.logger.info('loading the ip of the vm') ip = self._try_get_ip(self.pv_service, si, uuid, vcenter_resource) if ip: session.UpdateResourceAddress(context.resource.name, ip) except Exception as e: self.logger.error(e) raise finally: if si: self.pv_service.disconnect(si) return self._get_auto_load_response(uuid, vcenter_name, context.resource) def _get_auto_load_response(self, uuid, vcenter_name, resource): vm_details = self._get_vm_details(uuid, vcenter_name, resource) # return vm_details autoload_atts = [AutoLoadAttribute('', 'VmDetails', vm_details)] return AutoLoadDetails([], autoload_atts) def _try_get_ip(self, pv_service, si, uuid, vcenter_resource): ip = None try: vm = pv_service.get_vm_by_uuid(si, uuid) ip_res = self.ip_manager.get_ip(vm, vcenter_resource.holding_network, self.ip_manager.get_ip_match_function(None), cancellation_context=None, timeout=None, logger=self.logger) if ip_res.ip_address: ip = ip_res.ip_address except Exception as e: self.logger.debug('Error while trying to load VM({0}) IP'.format(uuid)) return ip @staticmethod def _get_vm_details(uuid, vcenter_name, resource): vm_details = ApiVmDetails() vm_details.UID = uuid vm_details.CloudProviderName = vcenter_name vm_details.VmCustomParams = [] str_vm_details = jsonpickle.encode(vm_details, unpicklable=False) return str_vm_details def _get_connection_to_vcenter(self, pv_service, session, vcenter_resource, address): password = self._decrypt_password(session, vcenter_resource.password) si = pv_service.connect(address, vcenter_resource.user, password, 443) return si @staticmethod def _decrypt_password(session, password): return session.DecryptPassword(password).Value
def __init__(self): """ Initialize the driver session, this function is called everytime a new instance of the driver is created in here the driver is going to be bootstrapped :param context: models.QualiDriverModels.InitCommandContext """ self.cs_helper = CloudshellDriverHelper() synchronous_task_waiter = SynchronousTaskWaiter() pv_service = pyVmomiService(connect=SmartConnect, disconnect=Disconnect, task_waiter=synchronous_task_waiter) self.resource_model_parser = ResourceModelParser() port_group_name_generator = DvPortGroupNameGenerator() vnic_to_network_mapper = VnicToNetworkMapper( quali_name_generator=port_group_name_generator) resource_remover = CloudshellResourceRemover() ovf_service = OvfImageDeployerService(self.resource_model_parser) self.vm_loader = VMLoader(pv_service) vm_deployer = VirtualMachineDeployer( pv_service=pv_service, name_generator=generate_unique_name, ovf_service=ovf_service, cs_helper=self.cs_helper, resource_model_parser=ResourceModelParser()) dv_port_group_creator = DvPortGroupCreator( pyvmomi_service=pv_service, synchronous_task_waiter=synchronous_task_waiter) virtual_machine_port_group_configurer = \ VirtualMachinePortGroupConfigurer(pyvmomi_service=pv_service, synchronous_task_waiter=synchronous_task_waiter, vnic_to_network_mapper=vnic_to_network_mapper, vnic_service=VNicService(), name_gen=port_group_name_generator) virtual_switch_to_machine_connector = VirtualSwitchToMachineConnector( dv_port_group_creator, virtual_machine_port_group_configurer) # Command Wrapper self.command_wrapper = CommandWrapper( pv_service=pv_service, cloud_shell_helper=self.cs_helper, resource_model_parser=self.resource_model_parser, context_based_logger_factory=ContextBasedLoggerFactory()) # Deploy Command self.deploy_command = DeployCommand(deployer=vm_deployer) # Virtual Switch Revoke self.virtual_switch_disconnect_command = \ VirtualSwitchToMachineDisconnectCommand( pyvmomi_service=pv_service, port_group_configurer=virtual_machine_port_group_configurer, resource_model_parser=self.resource_model_parser) # Virtual Switch Connect virtual_switch_connect_command = \ VirtualSwitchConnectCommand( pv_service=pv_service, virtual_switch_to_machine_connector=virtual_switch_to_machine_connector, dv_port_group_name_generator=DvPortGroupNameGenerator(), vlan_spec_factory=VlanSpecFactory(), vlan_id_range_parser=VLanIdRangeParser()) self.connection_orchestrator = ConnectionCommandOrchestrator( connector=virtual_switch_connect_command, disconnector=self.virtual_switch_disconnect_command, resource_model_parser=self.resource_model_parser) # Destroy VM Command self.destroy_virtual_machine_command = \ DestroyVirtualMachineCommand(pv_service=pv_service, resource_remover=resource_remover, disconnector=self.virtual_switch_disconnect_command) # Power Command self.vm_power_management_command = \ VirtualMachinePowerManagementCommand(pyvmomi_service=pv_service, synchronous_task_waiter=synchronous_task_waiter) ip_manager = VMIPManager() # Refresh IP command self.refresh_ip_command = RefreshIpCommand( pyvmomi_service=pv_service, resource_model_parser=ResourceModelParser(), ip_manager=ip_manager) # Save Snapshot self.snapshot_saver = SaveSnapshotCommand( pyvmomi_service=pv_service, task_waiter=synchronous_task_waiter) # Snapshot Restorer self.snapshot_restorer = SnapshotRestoreCommand( pyvmomi_service=pv_service, task_waiter=synchronous_task_waiter) self.snapshots_retriever = RetrieveSnapshotsCommand( pyvmomi_service=pv_service)
def __init__(self): self.resource_model_parser = ResourceModelParser() self.cs_helper = CloudshellDriverHelper()
class BreakingPointVChassisShellDriver(ResourceDriverInterface): DOMAIN = "Global" SHELL_NAME = "BP vChassis" def __init__(self): self.cs_helper = CloudshellDriverHelper() self.model_parser = ResourceModelParser() self.ip_manager = VMIPManager() self.task_waiter = SynchronousTaskWaiter() self.pv_service = pyVmomiService(SmartConnect, Disconnect, self.task_waiter) def initialize(self, context): """ Initialize the driver session, this function is called everytime a new instance of the driver is created This is a good place to load and cache the driver configuration, initiate sessions etc. :param InitCommandContext context: the context the command runs on """ pass def cleanup(self): """ Destroy the driver session, this function is called everytime a driver instance is destroyed This is a good place to close any open sessions, finish writing to log files """ pass def get_inventory(self, context): """ Will locate vm in vcenter and fill its uuid :type context: cloudshell.shell.core.context.ResourceCommandContext """ logger = get_logger_with_thread_id(context) logger.info("Start Autoload process") vcenter_vm_name = context.resource.attributes["{}.vCenter VM".format(self.SHELL_NAME)] vcenter_vm_name = vcenter_vm_name.replace("\\", "/") vcenter_name = context.resource.attributes["{}.vCenter Name".format(self.SHELL_NAME)] logger.info("Start AutoLoading VM_path: {0} on vcenter: {1}".format(vcenter_vm_name, vcenter_name)) session = self.cs_helper.get_session(context.connectivity.server_address, context.connectivity.admin_auth_token, self.DOMAIN) vcenter_api_res = session.GetResourceDetails(vcenter_name) vcenter_resource = self.model_parser.convert_to_vcenter_model(vcenter_api_res) si = None try: logger.info("Connecting to vcenter ({0})".format(vcenter_api_res.Address)) si = self._get_connection_to_vcenter(self.pv_service, session, vcenter_resource, vcenter_api_res.Address) logger.info("Loading VM UUID") vm_loader = VMLoader(self.pv_service) uuid = vm_loader.load_vm_uuid_by_name(si, vcenter_resource, vcenter_vm_name) logger.info("VM UUID: {0}".format(uuid)) logger.info("Loading the IP of the VM") ip = self._try_get_ip(self.pv_service, si, uuid, vcenter_resource, logger) if ip: session.UpdateResourceAddress(context.resource.name, ip) autoload_atts = [AutoLoadAttribute("", "VmDetails", self._get_vm_details(uuid, vcenter_name))] return AutoLoadDetails([], autoload_atts) except Exception: logger.exception("Get inventory command failed") raise finally: if si: self.pv_service.disconnect(si) def _try_get_ip(self, pv_service, si, uuid, vcenter_resource, logger): ip = None try: vm = pv_service.get_vm_by_uuid(si, uuid) ip_res = self.ip_manager.get_ip(vm, vcenter_resource.holding_network, self.ip_manager.get_ip_match_function(None), cancellation_context=None, timeout=None, logger=logger) if ip_res.ip_address: ip = ip_res.ip_address except Exception: logger.debug("Error while trying to load VM({0}) IP".format(uuid), exc_info=True) return ip @staticmethod def _get_vm_details(uuid, vcenter_name): vm_details = ApiVmDetails() vm_details.UID = uuid vm_details.CloudProviderName = vcenter_name vm_details.CloudProviderFullName = vcenter_name vm_details.VmCustomParams = [] str_vm_details = jsonpickle.encode(vm_details, unpicklable=False) return str_vm_details def _get_connection_to_vcenter(self, pv_service, session, vcenter_resource, address): password = self._decrypt_password(session, vcenter_resource.password) si = pv_service.connect(address, vcenter_resource.user, password, VCENTER_CONNECTION_PORT) return si @staticmethod def _decrypt_password(session, password): return session.DecryptPassword(password).Value
def __init__(self): self.parser = ResourceModelParser() self.pv_service = pyVmomiService(SmartConnect, Disconnect, SynchronousTaskWaiter()) self.cs_helper = CloudshellDriverHelper() self.context_based_logger_factory = ContextBasedLoggerFactory()
class PaloAltoStaticShellDriver(ResourceDriverInterface, FirewallResourceDriverInterface, GlobalLock): SUPPORTED_OS = [r"Palo Alto"] SHELL_NAME = "PaloAlto Static vFirewall" PORT_MODEL = "GenericVPort" DOMAIN = "Global" def __init__(self): super(PaloAltoStaticShellDriver, self).__init__() self._cli = None self.cs_helper = CloudshellDriverHelper() self.model_parser = ResourceModelParser() self.ip_manager = VMIPManager() self.task_waiter = SynchronousTaskWaiter() self.pv_service = pyVmomiService(SmartConnect, Disconnect, self.task_waiter) def initialize(self, context): """ Initialize the driver session, this function is called everytime a new instance of the driver is created This is a good place to load and cache the driver configuration, initiate sessions etc. """ resource_config = create_firewall_resource_from_context( shell_name=self.SHELL_NAME, supported_os=self.SUPPORTED_OS, context=context) # session_pool_size = int(resource_config.sessions_concurrency_limit or 1) session_pool_size = int(resource_config.sessions_concurrency_limit) self._cli = get_cli(session_pool_size) return 'Finished initializing' def cleanup(self): """ Destroy the driver session, this function is called everytime a driver instance is destroyed This is a good place to close any open sessions, finish writing to log files """ pass def get_inventory(self, context): """ Will locate vm in vcenter and fill its uuid """ logger = get_logger_with_thread_id(context) logger.info("Start Autoload process") session = self.cs_helper.get_session( context.connectivity.server_address, context.connectivity.admin_auth_token, self.DOMAIN) vcenter_vblade = context.resource.attributes[ "{}.vFirewall vCenter VM".format(self.SHELL_NAME)].replace( "\\", "/") vcenter_name = context.resource.attributes["{}.vCenter Name".format( self.SHELL_NAME)] logger.info("Start AutoLoading VM_Path: {0} on vCenter: {1}".format( vcenter_vblade, vcenter_name)) vcenter_api_res = session.GetResourceDetails(vcenter_name) vcenter_resource = self.model_parser.convert_to_vcenter_model( vcenter_api_res) si = None try: logger.info("Connecting to vCenter ({0})".format( vcenter_api_res.Address)) si = self._get_connection_to_vcenter(self.pv_service, session, vcenter_resource, vcenter_api_res.Address) logger.info("Loading VMs UUID") vm_loader = VMLoader(self.pv_service) vfw_uuid = vm_loader.load_vm_uuid_by_name(si, vcenter_resource, vcenter_vblade) logger.info("PanOS vFirewall VM UUID: {0}".format(vfw_uuid)) logger.info("Loading the IP of the PanOS vFirewall VM") vfw_ip = self._try_get_ip(self.pv_service, si, vfw_uuid, vcenter_resource, logger) if vfw_ip: session.UpdateResourceAddress(context.resource.name, vfw_ip) else: raise Exception( "Determination of PanOS vFirewall IP address failed." "Please, verify that VM is up and running") vm = self.pv_service.get_vm_by_uuid(si, vfw_uuid) phys_interfaces = [] for device in vm.config.hardware.device: if isinstance(device, vim.vm.device.VirtualEthernetCard): phys_interfaces.append(device) resources = [] attributes = [] for port_number, phys_interface in enumerate(phys_interfaces): if port_number == 0: # First interface (port number 0) should be Management continue network_adapter_number = phys_interface.deviceInfo.label.lower( ).strip("network adapter ") unique_id = hash(phys_interface.macAddress) relative_address = "P{}".format(port_number) resources.append( AutoLoadResource(model="{}.{}".format( self.SHELL_NAME, self.PORT_MODEL), name="Port {}".format(port_number), relative_address=relative_address, unique_identifier=unique_id)) attributes.append( AutoLoadAttribute( attribute_name="{}.{}.MAC Address".format( self.SHELL_NAME, self.PORT_MODEL), attribute_value=phys_interface.macAddress, relative_address=relative_address)) attributes.append( AutoLoadAttribute( attribute_name="{}.{}.Requested vNIC Name".format( self.SHELL_NAME, self.PORT_MODEL), attribute_value=network_adapter_number, relative_address=relative_address)) attributes.append( AutoLoadAttribute( attribute_name="{}.{}.Logical Name".format( self.SHELL_NAME, self.PORT_MODEL), attribute_value="Interface {}".format(port_number), relative_address=relative_address)) attributes.append( AutoLoadAttribute("", "VmDetails", self._get_vm_details(vfw_uuid, vcenter_name))) autoload_details = AutoLoadDetails(resources=resources, attributes=attributes) except Exception: logger.exception("Get inventory command failed") raise finally: if si: self.pv_service.disconnect(si) return autoload_details def _try_get_ip(self, pv_service, si, uuid, vcenter_resource, logger): ip = None try: vm = pv_service.get_vm_by_uuid(si, uuid) ip_res = self.ip_manager.get_ip( vm, vcenter_resource.holding_network, self.ip_manager.get_ip_match_function(None), cancellation_context=None, timeout=None, logger=logger) if ip_res.ip_address: ip = ip_res.ip_address except Exception: logger.debug("Error while trying to load VM({0}) IP".format(uuid), exc_info=True) return ip @staticmethod def _get_vm_details(uuid, vcenter_name): vm_details = ApiVmDetails() vm_details.UID = uuid vm_details.CloudProviderName = vcenter_name vm_details.CloudProviderFullName = vcenter_name vm_details.VmCustomParams = [] str_vm_details = jsonpickle.encode(vm_details, unpicklable=False) return str_vm_details def _get_connection_to_vcenter(self, pv_service, session, vcenter_resource, address): password = self._decrypt_password(session, vcenter_resource.password) si = pv_service.connect(address, vcenter_resource.user, password, VCENTER_CONNECTION_PORT) return si @staticmethod def _decrypt_password(session, password): return session.DecryptPassword(password).Value def health_check(self, context): """Checks if the device is up and connectable :param ResourceCommandContext context: ResourceCommandContext object with all Resource Attributes inside :return: Success or fail message :rtype: str """ logger = get_logger_with_thread_id(context) api = get_api(context) logger.info("CONTEXT: {}".format(context)) logger.info("SHELL_NAME: {}".format(self.SHELL_NAME)) logger.info("SUPPORTED_OS: {}".format(self.SUPPORTED_OS)) resource_config = create_firewall_resource_from_context( shell_name=self.SHELL_NAME, supported_os=self.SUPPORTED_OS, context=context) logger.info("RESOURCE_CONFIG: {}".format(resource_config.__dict__)) cli_handler = CliHandler(self._cli, resource_config, logger, api) state_operations = StateRunner(logger, api, resource_config, cli_handler) return state_operations.health_check() def run_custom_command(self, context, custom_command): """Send custom command :param ResourceCommandContext context: ResourceCommandContext object with all Resource Attributes inside :return: result :rtype: str """ logger = get_logger_with_thread_id(context) api = get_api(context) resource_config = create_firewall_resource_from_context( shell_name=self.SHELL_NAME, supported_os=self.SUPPORTED_OS, context=context) cli_handler = CliHandler(self._cli, resource_config, logger, api) send_command_operations = RunCommandRunner(logger=logger, cli_handler=cli_handler) response = send_command_operations.run_custom_command( parse_custom_commands(command=custom_command)) return response def run_custom_config_command(self, context, custom_command): """Send custom command in configuration mode :param ResourceCommandContext context: ResourceCommandContext object with all Resource Attributes inside :return: result :rtype: str """ logger = get_logger_with_thread_id(context) api = get_api(context) resource_config = create_firewall_resource_from_context( shell_name=self.SHELL_NAME, supported_os=self.SUPPORTED_OS, context=context) cli_handler = CliHandler(self._cli, resource_config, logger, api) send_command_operations = RunCommandRunner(logger=logger, cli_handler=cli_handler) result_str = send_command_operations.run_custom_config_command( parse_custom_commands(command=custom_command)) return result_str @GlobalLock.lock def save(self, context, folder_path, configuration_type): """Save a configuration file to the provided destination :param ResourceCommandContext context: The context object for the command with resource and reservation info :param str folder_path: The path to the folder in which the configuration file will be saved :param str configuration_type: startup or running config :return The configuration file name :rtype: str """ logger = get_logger_with_thread_id(context) api = get_api(context) resource_config = create_firewall_resource_from_context( self.SHELL_NAME, self.SUPPORTED_OS, context) cli_handler = CliHandler(self._cli, resource_config, logger, api) configuration_type = configuration_type or 'running' configuration_operations = ConfigurationRunner(logger, resource_config, api, cli_handler) logger.info('Save started') response = configuration_operations.save(folder_path, configuration_type) logger.info('Save completed') return response @GlobalLock.lock def restore(self, context, path, configuration_type, restore_method): """Restores a configuration file :param ResourceCommandContext context: The context object for the command with resource and reservation info :param str path: The path to the configuration file, including the configuration file name :param str restore_method: Determines whether the restore should append or override the current configuration :param str configuration_type: Specify whether the file should update the startup or running config """ logger = get_logger_with_thread_id(context) api = get_api(context) resource_config = create_firewall_resource_from_context( self.SHELL_NAME, self.SUPPORTED_OS, context) cli_handler = CliHandler(self._cli, resource_config, logger, api) configuration_type = configuration_type or 'running' restore_method = restore_method or 'override' configuration_operations = ConfigurationRunner(logger, resource_config, api, cli_handler) logger.info('Restore started') configuration_operations.restore(path, configuration_type, restore_method) logger.info('Restore completed') def orchestration_save(self, context, mode, custom_params): """Saves the Shell state and returns a description of the saved artifacts and information This command is intended for API use only by sandbox orchestration scripts to implement a save and restore workflow :param ResourceCommandContext context: the context object containing resource and reservation info :param str mode: Snapshot save mode, can be one of two values 'shallow' (default) or 'deep' :param str custom_params: Set of custom parameters for the save operation :return: SavedResults serialized as JSON :rtype: OrchestrationSaveResult """ logger = get_logger_with_thread_id(context) api = get_api(context) resource_config = create_firewall_resource_from_context( self.SHELL_NAME, self.SUPPORTED_OS, context) cli_handler = CliHandler(self._cli, resource_config, logger, api) configuration_operations = ConfigurationRunner(logger, resource_config, api, cli_handler) logger.info('Orchestration save started') response = configuration_operations.orchestration_save( mode, custom_params) logger.info('Orchestration save completed') return response def orchestration_restore(self, context, saved_artifact_info, custom_params): """Restores a saved artifact previously saved by this Shell driver using the orchestration_save function :param ResourceCommandContext context: The context object for the command with resource and reservation info :param str saved_artifact_info: A JSON string representing the state to restore including saved artifacts and info :param str custom_params: Set of custom parameters for the restore operation """ logger = get_logger_with_thread_id(context) api = get_api(context) resource_config = create_firewall_resource_from_context( self.SHELL_NAME, self.SUPPORTED_OS, context) cli_handler = CliHandler(self._cli, resource_config, logger, api) configuration_operations = ConfigurationRunner(logger, resource_config, api, cli_handler) logger.info('Orchestration restore started') configuration_operations.orchestration_restore(saved_artifact_info, custom_params) logger.info('Orchestration restore completed') @GlobalLock.lock def load_firmware(self, context, path): """Upload and updates firmware on the resource :param ResourceCommandContext context: The context object for the command with resource and reservation info :param str path: path to tftp server where firmware file is stored """ logger = get_logger_with_thread_id(context) api = get_api(context) resource_config = create_firewall_resource_from_context( self.SHELL_NAME, self.SUPPORTED_OS, context) cli_handler = CliHandler(self._cli, resource_config, logger, api) logger.info('Start Load Firmware') firmware_operations = FirmwareRunner(logger, cli_handler) response = firmware_operations.load_firmware(path) logger.info('Finish Load Firmware: {}'.format(response)) def shutdown(self, context): """Sends a graceful shutdown to the device :param ResourceCommandContext context: The context object for the command with resource and reservation info """ logger = get_logger_with_thread_id(context) api = get_api(context) resource_config = create_firewall_resource_from_context( self.SHELL_NAME, self.SUPPORTED_OS, context) cli_handler = CliHandler(self._cli, resource_config, logger, api) state_operations = StateRunner(logger, api, resource_config, cli_handler) return state_operations.shutdown()
class VCenterAutoModelDiscovery(object): def __init__(self): self.parser = ResourceModelParser() self.pv_service = pyVmomiService(SmartConnect, Disconnect) self.cs_helper = CloudshellDriverHelper() self.context_based_logger_factory = ContextBasedLoggerFactory() def validate_and_discover(self, context): """ :type context: models.QualiDriverModels.AutoLoadCommandContext """ logger = self.context_based_logger_factory.create_logger_for_context( logger_name='vCenterShell', context=context) logger.info('Autodiscovery started') session = self.cs_helper.get_session(context.connectivity.server_address, context.connectivity.admin_auth_token, DOMAIN) self._check_if_attribute_not_empty(context.resource, ADDRESS) resource = context.resource auto_attr = [] si = self._check_if_vcenter_user_pass_valid(context, session, resource.attributes) if not si: error_message = 'Could not connect to the vCenter: {0}, with given credentials'\ .format(context.resource.address) logger.error(error_message) raise ValueError(error_message) all_dc = self.pv_service.get_all_items_in_vcenter(si, vim.Datacenter) dc = self._validate_datacenter(si, all_dc, auto_attr, resource.attributes) all_items_in_dc = self.pv_service.get_all_items_in_vcenter(si, None, dc) dc_name = dc.name for key, value in resource.attributes.items(): if key in [USER, PASSWORD, DEFAULT_DATACENTER, VM_CLUSTER]: continue validation_method = self._get_validation_method(key) validation_method(si, all_items_in_dc, auto_attr, dc_name, resource.attributes, key) logger.info('Autodiscovery completed') return AutoLoadDetails([], auto_attr) @staticmethod def _get_default_from_vc_by_type_and_name(items_in_vc, vim_type, name=None): items = [] if not isinstance(vim_type, collections.Iterable): vim_type = [vim_type] for item in items_in_vc: if item.name == name: return item item_type = type(item) if [t for t in vim_type if item_type is t]: items.append(item) if len(items) == 1: return items[0] if len(items) > 1: return 'too many options' return 'not found' def _validate_datacenter(self, si, all_item_in_vc, auto_att, attributes): dc = self._validate_attribute(si, attributes, vim.Datacenter, DEFAULT_DATACENTER) if not dc: dc = self._get_default(all_item_in_vc, vim.Datacenter, DEFAULT_DATACENTER) auto_att.append(AutoLoadAttribute('', DEFAULT_DATACENTER, dc.name)) return dc def _validate_attribute(self, si, attributes, vim_type, name, prefix=''): if name in attributes and attributes[name]: att_value = attributes[name] if prefix: att_value = '{0}/{1}'.format(prefix, att_value) obj = self.pv_service.get_folder(si, att_value) if not obj or isinstance(obj, str): raise ValueError('Could not find {0}'.format(name)) if vim_type and not isinstance(obj, vim_type): raise ValueError('The given {0}: {1} is not of the correct type'.format(name, attributes[name])) return obj return False def _get_default(self, all_item_in_vc, vim_type, key): obj = self._get_default_from_vc_by_type_and_name(all_item_in_vc, vim_type) if isinstance(obj, str): if obj == 'too many options': raise ValueError('{0} must be selected'.format(key)) raise ValueError('Could not find {0}'.format(key)) return obj def _check_if_vcenter_user_pass_valid(self, context, session, attributes): self._check_if_attribute_not_empty(attributes, USER) self._check_if_attribute_not_empty(attributes, PASSWORD) connection_details = self._get_connection_details(session, attributes[PASSWORD], attributes[USER], context.resource.address) try: si = self.pv_service.connect(connection_details.host, connection_details.username, connection_details.password, connection_details.port) except Exception: raise ValueError('could not connect to the vcenter: {0}, with the given credentials ({1})'.format( connection_details.host, connection_details.username)) return si def _validate_default_dvswitch(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): accepted_types = (vim.DistributedVirtualSwitch, vim.VmwareDistributedVirtualSwitch) d_switch = self._validate_attribute(si, attributes, accepted_types, key, dc_name) if not d_switch: d_switch = self._get_default(all_items_in_vc, accepted_types, key) d_name = self.get_full_name(dc_name, d_switch) # removing the upper folder d_name = d_name.replace('network/', '') else: d_name = attributes[key] auto_att.append(AutoLoadAttribute('', key, d_name)) def _validate_vm_storage(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): accepted_types = (vim.Datastore, vim.StoragePod) datastore = self._validate_attribute(si, attributes, accepted_types, key, dc_name) if not datastore: datastore = self._get_default(all_items_in_vc, accepted_types, key) d_name = self.get_full_name(dc_name, datastore) # removing the upper folder d_name = d_name.replace('datastore/', '') else: d_name = attributes[key] auto_att.append(AutoLoadAttribute('', key, d_name)) def _validate_vm_location(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): accepted_types = None folder = self._validate_attribute(si, attributes, accepted_types, key, dc_name) if not folder: raise ValueError('VM Folder cannot be empty') f_name = attributes[key] auto_att.append(AutoLoadAttribute('', key, f_name)) def _validate_default_port_group_location(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): if not attributes[key]: return self._validate_attribute(si, attributes, None, key, dc_name) def _validate_vm_cluster(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): accepted_types = (vim.ClusterComputeResource, vim.HostSystem) cluster = self._validate_attribute(si, attributes, accepted_types, key, dc_name) if not cluster: cluster = self._get_default(all_items_in_vc, accepted_types, key) c_name = self.get_full_name(dc_name, cluster) # removing the upper folder c_name = c_name.replace('host/', '') else: c_name = attributes[key] auto_att.append(AutoLoadAttribute('', key, c_name)) return cluster def _validate_vm_resource_pool(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): cluster = self._validate_vm_cluster(si, all_items_in_vc, auto_att, dc_name, attributes, VM_CLUSTER) if key not in attributes or not attributes[key]: return pool_name = attributes[key] pool = self._find_resource_pool_by_path(pool_name, cluster) if pool: auto_att.append(AutoLoadAttribute('', key, pool_name)) return raise ValueError('The given resource pool not found: {0}'.format(pool_name)) def _find_resource_pool_by_path(self, name, root): paths = name.split('/') for path in paths: root = self._find_resource_pool(path, root) if not root: return None return root def _find_resource_pool(self, name, root): if hasattr(root, 'resourcePool'): resource_pool = root.resourcePool if hasattr(resource_pool, 'name') and resource_pool.name == name: return resource_pool if isinstance(resource_pool, collections.Iterable): for pool in resource_pool: if pool.name == name: return pool if hasattr(resource_pool, 'resourcePool'): return self._find_resource_pool(name, resource_pool) return None def _validate_holding_network(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): holding_network = self._validate_attribute(si, attributes, vim.Network, key, dc_name) if not holding_network: raise ValueError('Holding Network cannot be empty') n_name = attributes[key] auto_att.append(AutoLoadAttribute('', key, n_name)) def _validate_shutdown_method(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): method = attributes[key] if self._is_in_array(key, method, SHUTDOWN_METHODS): auto_att.append(AutoLoadAttribute('', key, method)) @staticmethod def _is_in_array(key, value, arr): if value in arr: return True raise ValueError('{0} can only be: {1} instead of: {2}'.format(key, arr, value)) @staticmethod def _is_found(item, key): if not item: raise ValueError('The {0} could not be found in the given vCenter'.format(key)) @staticmethod def _get_connection_details(session, password, user, address): password = session.DecryptPassword(password).Value return VCenterConnectionDetails(address, user, password) @staticmethod def _check_if_attribute_not_empty(attributes, name): if not ((hasattr(attributes, name) and getattr(attributes, name)) or (isinstance(attributes, dict) and name in attributes and attributes[name])): raise ValueError('{0} cannot be empty'.format(name)) @staticmethod def _validate_empty(si, all_items_in_vc, attributes, auto_attr, dc_name, key): return def _get_validation_method(self, name): if not name: return self._validate_empty name = name.lower() name = name.split(' ') name = '_'.join(name) method_name = '_validate_{0}'.format(name) return getattr(self, method_name, self._validate_empty) @staticmethod def get_full_name(dc_name, managed_object, name=''): if managed_object.name == dc_name: return name curr_path = managed_object.name if name: curr_path = '{0}/{1}'.format(managed_object.name, name) return VCenterAutoModelDiscovery.get_full_name(dc_name, managed_object.parent, curr_path)
def __init__(self): self.parser = ResourceModelParser() self.pv_service = pyVmomiService(SmartConnect, Disconnect) self.cs_helper = CloudshellDriverHelper() self.context_based_logger_factory = ContextBasedLoggerFactory()
class VCenterAutoModelDiscovery(object): def __init__(self): self.parser = ResourceModelParser() self.pv_service = pyVmomiService(SmartConnect, Disconnect, SynchronousTaskWaiter()) self.cs_helper = CloudshellDriverHelper() self.context_based_logger_factory = ContextBasedLoggerFactory() def validate_and_discover(self, context): """ :type context: models.QualiDriverModels.AutoLoadCommandContext """ logger = self.context_based_logger_factory.create_logger_for_context( logger_name='vCenterShell', context=context) logger.info('Autodiscovery started') session = self.cs_helper.get_session(context.connectivity.server_address, context.connectivity.admin_auth_token, DOMAIN) self._check_if_attribute_not_empty(context.resource, ADDRESS) resource = context.resource auto_attr = [] si = self._check_if_vcenter_user_pass_valid(context, session, resource.attributes) if not si: error_message = 'Could not connect to the vCenter: {0}, with given credentials'\ .format(context.resource.address) logger.error(error_message) raise ValueError(error_message) all_dc = self.pv_service.get_all_items_in_vcenter(si, vim.Datacenter) dc = self._validate_datacenter(si, all_dc, auto_attr, resource.attributes) all_items_in_dc = self.pv_service.get_all_items_in_vcenter(si, None, dc) dc_name = dc.name for key, value in resource.attributes.items(): if key in [USER, PASSWORD, DEFAULT_DATACENTER, VM_CLUSTER]: continue validation_method = self._get_validation_method(key) validation_method(si, all_items_in_dc, auto_attr, dc_name, resource.attributes, key) logger.info('Autodiscovery completed') return AutoLoadDetails([], auto_attr) @staticmethod def _get_default_from_vc_by_type_and_name(items_in_vc, vim_type, name=None): items = [] if not isinstance(vim_type, collections.Iterable): vim_type = [vim_type] for item in items_in_vc: if item.name == name: return item item_type = type(item) if [t for t in vim_type if item_type is t]: items.append(item) if len(items) == 1: return items[0] if len(items) > 1: return 'too many options' return 'not found' def _validate_datacenter(self, si, all_item_in_vc, auto_att, attributes): dc = self._validate_attribute(si, attributes, vim.Datacenter, DEFAULT_DATACENTER) if not dc: dc = self._get_default(all_item_in_vc, vim.Datacenter, DEFAULT_DATACENTER) auto_att.append(AutoLoadAttribute('', DEFAULT_DATACENTER, dc.name)) return dc def _validate_attribute(self, si, attributes, vim_type, name, prefix=''): if name in attributes and attributes[name]: att_value = attributes[name] if prefix: att_value = '{0}/{1}'.format(prefix, att_value) obj = self.pv_service.get_folder(si, att_value) if not obj or isinstance(obj, str): raise ValueError('Could not find {0}'.format(name)) if vim_type and not isinstance(obj, vim_type): raise ValueError('The given {0}: {1} is not of the correct type'.format(name, attributes[name])) return obj return False def _get_default(self, all_item_in_vc, vim_type, key): obj = self._get_default_from_vc_by_type_and_name(all_item_in_vc, vim_type) if isinstance(obj, str): if obj == 'too many options': raise ValueError('{0} must be selected'.format(key)) raise ValueError('Could not find {0}'.format(key)) return obj def _check_if_vcenter_user_pass_valid(self, context, session, attributes): self._check_if_attribute_not_empty(attributes, USER) self._check_if_attribute_not_empty(attributes, PASSWORD) connection_details = self._get_connection_details(session, attributes[PASSWORD], attributes[USER], context.resource.address) try: si = self.pv_service.connect(connection_details.host, connection_details.username, connection_details.password, connection_details.port) except Exception: raise ValueError('could not connect to the vcenter: {0}, with the given credentials ({1})'.format( connection_details.host, connection_details.username)) return si def _validate_vm_storage(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): accepted_types = (vim.Datastore, vim.StoragePod) datastore = self._validate_attribute(si, attributes, accepted_types, key, dc_name) if not datastore: datastore = self._get_default(all_items_in_vc, accepted_types, key) d_name = self.get_full_name(dc_name, datastore) # removing the upper folder d_name = d_name.replace('datastore/', '') else: d_name = attributes[key] auto_att.append(AutoLoadAttribute('', key, d_name)) def _validate_vm_location(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): accepted_types = None folder = self._validate_attribute(si, attributes, accepted_types, key, dc_name) if not folder: raise ValueError('VM Folder cannot be empty') f_name = attributes[key] auto_att.append(AutoLoadAttribute('', key, f_name)) def _validate_vm_cluster(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): accepted_types = (vim.ClusterComputeResource, vim.HostSystem) cluster = self._validate_attribute(si, attributes, accepted_types, key, dc_name) if not cluster: cluster = self._get_default(all_items_in_vc, accepted_types, key) c_name = self.get_full_name(dc_name, cluster) # removing the upper folder c_name = c_name.replace('host/', '') else: c_name = attributes[key] auto_att.append(AutoLoadAttribute('', key, c_name)) return cluster def _validate_vm_resource_pool(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): cluster = self._validate_vm_cluster(si, all_items_in_vc, auto_att, dc_name, attributes, VM_CLUSTER) if key not in attributes or not attributes[key]: return pool_name = attributes[key] pool = self._find_resource_pool_by_path(pool_name, cluster) if pool: auto_att.append(AutoLoadAttribute('', key, pool_name)) return raise ValueError('The given resource pool not found: {0}'.format(pool_name)) def _find_resource_pool_by_path(self, name, root): paths = name.split('/') for path in paths: root = self._find_resource_pool(path, root) if not root: return None return root def _find_resource_pool(self, name, root): if hasattr(root, 'resourcePool'): resource_pool = root.resourcePool if hasattr(resource_pool, 'name') and resource_pool.name == name: return resource_pool if isinstance(resource_pool, collections.Iterable): for pool in resource_pool: if pool.name == name: return pool if hasattr(resource_pool, 'resourcePool'): return self._find_resource_pool(name, resource_pool) return None def _validate_holding_network(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): holding_network = self._validate_attribute(si, attributes, vim.Network, key, dc_name) if not holding_network: raise ValueError('Holding Network cannot be empty') n_name = attributes[key] auto_att.append(AutoLoadAttribute('', key, n_name)) def _validate_shutdown_method(self, si, all_items_in_vc, auto_att, dc_name, attributes, key): method = attributes[key] if self._is_in_array(key, method, SHUTDOWN_METHODS): auto_att.append(AutoLoadAttribute('', key, method)) @staticmethod def _is_in_array(key, value, arr): if value in arr: return True raise ValueError('{0} can only be: {1} instead of: {2}'.format(key, arr, value)) @staticmethod def _is_found(item, key): if not item: raise ValueError('The {0} could not be found in the given vCenter'.format(key)) @staticmethod def _get_connection_details(session, password, user, address): password = session.DecryptPassword(password).Value return VCenterConnectionDetails(address, user, password) @staticmethod def _check_if_attribute_not_empty(attributes, name): if not ((hasattr(attributes, name) and getattr(attributes, name)) or (isinstance(attributes, dict) and name in attributes and attributes[name])): raise ValueError('{0} cannot be empty'.format(name)) @staticmethod def _validate_empty(si, all_items_in_vc, attributes, auto_attr, dc_name, key): return def _get_validation_method(self, name): if not name: return self._validate_empty name = name.lower() name = name.split(' ') name = '_'.join(name) method_name = '_validate_{0}'.format(name) return getattr(self, method_name, self._validate_empty) @staticmethod def get_full_name(dc_name, managed_object, name=''): if managed_object.name == dc_name: return name curr_path = managed_object.name if name: curr_path = '{0}/{1}'.format(managed_object.name, name) return VCenterAutoModelDiscovery.get_full_name(dc_name, managed_object.parent, curr_path)