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 __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.ip_manager = VMIPManager() self.ip_manager.INTERVAL = 0.001 self.default_net = 'aa' self.function = re.compile('.*').match self.cancel = Mock() self.cancel.is_cancelled = None self.timeout = 1 self.logger = Mock() self.vm = Mock() self.vm.guest = Mock() self.vm.guest.toolsStatus = 'running'
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 test(self, get_network_by_device): # ARRANGE network = Mock() network.name = 'Net1' network.config.defaultPortConfig.vlan.vlanId = '65' get_network_by_device.return_value = network vm = self.mock_vm() si = Mock() pyvmomi_service = Mock() pyvmomi_service.find_by_uuid = Mock(return_value=vm) param = Mock() param.name = 'ip_regex' param.value = '.*' request = Mock() request.deployedAppJson.name = 'App1' request.deployedAppJson.vmdetails.vmCustomParams = [param] request.appRequestJson.deploymentService.model = 'vCenter Clone VM From VM' request.appRequestJson.deploymentService.attributes = [Mock()] resource_context = Mock() resource_context.attributes = {'Reserved Networks': 'Net1;B'} cancellation_context = Mock(is_cancelled=False) ip_manager = VMIPManager() vm_details_provider = VmDetailsProvider(pyvmomi_service, ip_manager) # ACT command = VmDetailsCommand(pyvmomi_service, vm_details_provider) datas = command.get_vm_details( si=si, logger=Mock(), resource_context=resource_context, requests=[request], cancellation_context=cancellation_context) # ASSERT self.assertEqual(len(datas), 1) vm_details = datas[0] if isinstance(vm_details, VmDetailsData): pass self.assertEqual(vm_details.appName, 'App1') self.assertEqual(vm_details.errorMessage, '') self.assertEqual(len(vm_details.vmInstanceData), 6) self.assertEqual(len(vm_details.vmNetworkData), 1) nic = vm_details.vmNetworkData[0] if isinstance(nic, VmDetailsNetworkInterface): pass self.assertEqual(nic.interfaceId, 'Mac1') self.assertEqual(nic.isPredefined, True) self.assertEqual(nic.isPrimary, True) self.assertEqual(nic.networkId, '65') self.assertEqual(len(nic.networkData), 4) self.assertEqual(self._get_value(nic.networkData, 'IP'), '1.2.3.4') self.assertEqual(self._get_value(nic.networkData, 'MAC Address'), 'Mac1') self.assertEqual(self._get_value(nic.networkData, 'Network Adapter'), 'NetDeviceLabel') self.assertEqual(self._get_value(nic.networkData, 'Port Group Name'), 'Net1')
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 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)
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) session = CloudShellAPISession(host=context.connectivity.server_address, token_id=context.connectivity.admin_auth_token, domain=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.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 DeployAppOrchestrationDriver(object): def __init__(self): 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)) with CloudShellSessionContext(context) as cloudshell_session: session = cloudshell_session 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: self.logger.exception("Get inventory command failed") 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: self.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, 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
class TestVMIPManager(TestCase): def setUp(self): self.ip_manager = VMIPManager() self.ip_manager.INTERVAL = 0.001 self.default_net = 'aa' self.function = re.compile('.*').match self.cancel = Mock() self.cancel.is_cancelled = None self.timeout = 1 self.logger = Mock() self.vm = Mock() self.vm.guest = Mock() self.vm.guest.toolsStatus = 'running' def test_get_match_method_none(self): method = self.ip_manager.get_ip_match_function(None) self.assertEqual(method, re.compile('.*').match) def test_get_match_method(self): method = self.ip_manager.get_ip_match_function('1.*') self.assertEqual(method, re.compile('1.*').match) def test_get_ip_toolsNotInstalled(self): vm = Mock() vm.guest = Mock() vm.guest.toolsStatus = 'toolsNotInstalled' self.assertRaises(ValueError, self.ip_manager.get_ip, vm, self.default_net, self.function, self.cancel, self.timeout, self.logger) def test_get_ip_no_timeout_no_found(self): self.vm.guest.ipAddress = None self.vm.guest.net = [] res = self.ip_manager.get_ip( self.vm, self.default_net, self.function, self.cancel, None, self.logger) expected = IpResult(None, IpReason.NotFound) self.assertEqual(expected.ip_address, res.ip_address) self.assertIsNone(res.ip_address) self.assertEqual(expected.reason, res.reason) def test_get_ip_no_timeout_found(self): self.vm.guest.ipAddress = '1.1.1.1' self.vm.guest.net = [] res = self.ip_manager.get_ip( self.vm, self.default_net, self.function, self.cancel, None, self.logger) expected = IpResult('1.1.1.1', IpReason.Success) self.assertEqual(expected.ip_address, res.ip_address) self.assertEqual(expected.reason, res.reason) def test_get_ip_no_timeout_multi_ip_regex_pattern(self): self.vm.guest.ipAddress = '1.1.1.1' nic = Mock() nic.network = None nic.ipAddress = ['2.2.2.2'] self.vm.guest.net = [nic] res = self.ip_manager.get_ip( self.vm, self.default_net, self.ip_manager.get_ip_match_function('^2\.2\.2\.2$'), self.cancel, None, self.logger) expected = IpResult('2.2.2.2', IpReason.Success) self.assertEqual(expected.ip_address, res.ip_address) self.assertEqual(expected.reason, res.reason) def test_get_ip_with_timeout(self): TestVMIPManager.counter = 0 self.ip_manager._obtain_ip = TestVMIPManager.mock_func res = self.ip_manager.get_ip( self.vm, self.default_net, self.function, self.cancel, self.timeout, self.logger) expected = IpResult('1.1.1.1', IpReason.Success) self.assertEqual(expected.ip_address, res.ip_address) self.assertEqual(expected.reason, res.reason) def test_get_ip_with_timeout_raised(self): TestVMIPManager.counter = 0 self.ip_manager._obtain_ip = TestVMIPManager.mock_func self.ip_manager.INTERVAL = 1.1 res = self.ip_manager.get_ip( self.vm, self.default_net, self.function, self.cancel, self.timeout, self.logger) expected = IpResult(None, IpReason.Timeout) self.assertEqual(expected.ip_address, res.ip_address) self.assertEqual(expected.reason, res.reason) self.ip_manager.INTERVAL = 0.001 def test_get_ip_cancelled(self): TestVMIPManager.counter = 0 cancel = Mock() cancel.is_cancelled = True res = self.ip_manager.get_ip( self.vm, self.default_net, self.function, cancel, self.timeout, self.logger) expected = IpResult(None, IpReason.Cancelled) self.assertEqual(expected.ip_address, res.ip_address) self.assertEqual(expected.reason, res.reason) counter = 0 @staticmethod def mock_func(*args): if TestVMIPManager.counter: return '1.1.1.1' TestVMIPManager.counter += 1
class TestVMIPManager(TestCase): def setUp(self): self.ip_manager = VMIPManager() self.ip_manager.INTERVAL = 0.001 self.default_net = 'aa' self.function = re.compile('.*').match self.cancel = Mock() self.cancel.is_cancelled = None self.timeout = 1 self.logger = Mock() self.vm = Mock() self.vm.guest = Mock() self.vm.guest.toolsStatus = 'running' def test_get_match_method_none(self): method = self.ip_manager.get_ip_match_function(None) self.assertEqual(method, re.compile('.*').match) def test_get_match_method(self): method = self.ip_manager.get_ip_match_function('1.*') self.assertEqual(method, re.compile('1.*').match) def test_get_ip_toolsNotInstalled(self): vm = Mock() vm.guest = Mock() vm.guest.toolsStatus = 'toolsNotInstalled' self.assertRaises(ValueError, self.ip_manager.get_ip, vm, self.default_net, self.function, self.cancel, self.timeout, self.logger) def test_get_ip_no_timeout_no_found(self): self.vm.guest.ipAddress = None self.vm.guest.net = [] res = self.ip_manager.get_ip(self.vm, self.default_net, self.function, self.cancel, None, self.logger) expected = IpResult(None, IpReason.NotFound) self.assertEqual(expected.ip_address, res.ip_address) self.assertIsNone(res.ip_address) self.assertEqual(expected.reason, res.reason) def test_get_ip_no_timeout_found(self): self.vm.guest.ipAddress = '1.1.1.1' self.vm.guest.net = [] res = self.ip_manager.get_ip(self.vm, self.default_net, self.function, self.cancel, None, self.logger) expected = IpResult('1.1.1.1', IpReason.Success) self.assertEqual(expected.ip_address, res.ip_address) self.assertEqual(expected.reason, res.reason) def test_get_ip_no_timeout_multi_ip_regex_pattern(self): self.vm.guest.ipAddress = '1.1.1.1' nic = Mock() nic.network = None nic.ipAddress = ['2.2.2.2'] self.vm.guest.net = [nic] res = self.ip_manager.get_ip( self.vm, self.default_net, self.ip_manager.get_ip_match_function('^2\.2\.2\.2$'), self.cancel, None, self.logger) expected = IpResult('2.2.2.2', IpReason.Success) self.assertEqual(expected.ip_address, res.ip_address) self.assertEqual(expected.reason, res.reason) def test_get_ip_with_timeout(self): TestVMIPManager.counter = 0 self.ip_manager._obtain_ip = TestVMIPManager.mock_func res = self.ip_manager.get_ip(self.vm, self.default_net, self.function, self.cancel, self.timeout, self.logger) expected = IpResult('1.1.1.1', IpReason.Success) self.assertEqual(expected.ip_address, res.ip_address) self.assertEqual(expected.reason, res.reason) def test_get_ip_with_timeout_raised(self): TestVMIPManager.counter = 0 self.ip_manager._obtain_ip = TestVMIPManager.mock_func self.ip_manager.INTERVAL = 1.1 res = self.ip_manager.get_ip(self.vm, self.default_net, self.function, self.cancel, self.timeout, self.logger) expected = IpResult(None, IpReason.Timeout) self.assertEqual(expected.ip_address, res.ip_address) self.assertEqual(expected.reason, res.reason) self.ip_manager.INTERVAL = 0.001 def test_get_ip_cancelled(self): TestVMIPManager.counter = 0 cancel = Mock() cancel.is_cancelled = True res = self.ip_manager.get_ip(self.vm, self.default_net, self.function, cancel, self.timeout, self.logger) expected = IpResult(None, IpReason.Cancelled) self.assertEqual(expected.ip_address, res.ip_address) self.assertEqual(expected.reason, res.reason) counter = 0 @staticmethod def mock_func(*args): if TestVMIPManager.counter: return '1.1.1.1' TestVMIPManager.counter += 1
class BreakingPointVBladeShellDriver(ResourceDriverInterface): SHELL_NAME = "BP vBlade" PORT_MODEL = "GenericVPort" DOMAIN = "Global" IP_KEY = "ipAddress" ID_KEY = "id" 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") # session = self.cs_helper.get_session(context.connectivity.server_address, # context.connectivity.admin_auth_token, # self.DOMAIN) session = CloudShellAPISession( host=context.connectivity.server_address, token_id=context.connectivity.admin_auth_token, domain=self.DOMAIN) vcenter_vblade = context.resource.attributes[ "{}.vBlade vCenter VM".format(self.SHELL_NAME)].replace("\\", "/") vcenter_vchassis = context.resource.attributes[ "{}.vChassis vCenter VM".format(self.SHELL_NAME)].replace( "\\", "/") username = context.resource.attributes["{}.User".format( self.SHELL_NAME)] password = self._decrypt_password( session, context.resource.attributes["{}.Password".format(self.SHELL_NAME)]) 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) vchassis_uuid = vm_loader.load_vm_uuid_by_name( si, vcenter_resource, vcenter_vchassis) logger.info("vChassis VM UUID: {0}".format(vchassis_uuid)) logger.info("Loading the IP of the vChassis VM") vchassis_ip = self._try_get_ip(self.pv_service, si, vchassis_uuid, vcenter_resource, logger) if vchassis_ip: bp_api = BP_API(ip=vchassis_ip, username=username, password=password, logger=logger) bp_api.login() modules_position = { module[self.IP_KEY]: module[self.ID_KEY] for module in bp_api.get_modules() if module[self.IP_KEY] } bp_api.logout() logger.debug("Modules position: {}".format(modules_position)) else: raise Exception( "Determination of vChassis IP address failed. Please, verify that VM is up and running" ) vblade_uuid = vm_loader.load_vm_uuid_by_name( si, vcenter_resource, vcenter_vblade) logger.info("vBlade VM UUID: {0}".format(vblade_uuid)) logger.info("Loading the IP of the vBlade VM") vblade_ip = self._try_get_ip(self.pv_service, si, vblade_uuid, vcenter_resource, logger) if vblade_ip: module_id = modules_position.get(vblade_ip) if module_id is None: raise Exception( "Provided vBlade IP incorrect or vBlade isn't connect to vChassis" ) session.UpdateResourceAddress( context.resource.name, "{blade_ip}\{chassis_ip}\M{module_id}".format( blade_ip=vblade_ip, chassis_ip=vchassis_ip, module_id=module_id)) else: raise Exception( "Determination of vBlade IP address failed. Please, verify that VM is up and running" ) vm = self.pv_service.get_vm_by_uuid(si, vblade_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(vblade_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