Example #1
0
def submit_job_and_add_task(batch_client, job_id, vm_size, vm_count):
    """Submits a job to the Azure Batch service and adds a simple task.

    :param batch_client: The batch client to use.
    :type batch_client: `batchserviceclient.BatchServiceClient`
    :param str job_id: The id of the job to create.
    """

    cloud_service_config = batchmodels.CloudServiceConfiguration(os_family='5')
    pool_info = batchmodels.PoolInformation(
        auto_pool_specification=batchmodels.AutoPoolSpecification(
            auto_pool_id_prefix="HelloWorld",
            pool=batchmodels.PoolSpecification(
                vm_size=vm_size,
                target_dedicated_nodes=vm_count,
                cloud_service_configuration=cloud_service_config),
            keep_alive=False,
            pool_lifetime_option=batchmodels.PoolLifetimeOption.job))

    job = batchmodels.JobAddParameter(id=job_id, pool_info=pool_info)

    batch_client.job.add(job)

    task = batchmodels.TaskAddParameter(
        id="HelloWorld",
        command_line=common.helpers.wrap_commands_in_shell(
            'windows',
            ['echo Hello world from the Batch Hello world sample!']))

    batch_client.task.add(job_id=job.id, task=task)
def create_pool(batch_service_client, pool_id, resource_files):
    """
    Creates a pool of compute nodes with the specified OS settings.

    :param batch_service_client: A Batch service client.
    :type batch_service_client: `azure.batch.BatchServiceClient`
    :param str pool_id: An ID for the new pool.
    :param list resource_files: A collection of resource files for the pool's
    start task.
    :param str publisher: Marketplace image publisher
    :param str offer: Marketplace image offer
    :param str sku: Marketplace image sku
    """
    print('Creating pool [{}]...'.format(pool_id))

    # Create a new pool of Linux compute nodes using an Azure Virtual Machines
    # Marketplace image. For more information about creating pools of Linux
    # nodes, see:
    # https://azure.microsoft.com/documentation/articles/batch-linux-nodes/

    # Specify the commands for the pool's start task. The start task is run
    # on each node as it joins the pool, and when it's rebooted or re-imaged.
    # We use the start task to prep the node for running our task script.
    task_commands = [
        # Copy the python_tutorial_task.py script to the "shared" directory
        # that all tasks that run on the node have access to.
        #'echo %AZ_BATCH_TASK_WORKING_DIR%',
        #'echo %AZ_BATCH_NODE_SHARED_DIR%',
        'copy %AZ_BATCH_TASK_WORKING_DIR%\* %AZ_BATCH_NODE_SHARED_DIR%',
        # Install python with dependencies via PowerShell
        'powershell.exe -ExecutionPolicy Unrestricted -File %AZ_BATCH_NODE_SHARED_DIR%\InstallPython35.ps1'
    ]

    new_pool = batch.models.PoolAddParameter(
        id=pool_id,
        cloud_service_configuration=batchmodels.CloudServiceConfiguration(
            os_family="4", target_os_version="*"),
        vm_size=_POOL_VM_SIZE,
        target_dedicated=_POOL_NODE_COUNT,
        start_task=batch.models.StartTask(
            command_line=common.helpers.wrap_commands_in_shell(
                'windows', task_commands),
            run_elevated=True,
            wait_for_success=True,
            resource_files=resource_files),
    )

    try:
        batch_service_client.pool.add(new_pool)
    except batchmodels.batch_error.BatchErrorException as err:
        print_batch_exception(err)
        raise
    def test_batch_jobs(self, **kwargs):
        client = self.create_sharedkey_client(**kwargs)
        # Test Create Job
        auto_pool = models.AutoPoolSpecification(
            pool_lifetime_option=models.PoolLifetimeOption.job,
            pool=models.PoolSpecification(
                vm_size='small',
                cloud_service_configuration=models.CloudServiceConfiguration(
                    os_family='5'
                )
            )
        )
        job_prep = models.JobPreparationTask(command_line="cmd /c \"echo hello world\"")
        job_release = models.JobReleaseTask(command_line="cmd /c \"echo goodbye world\"")
        job_param = models.JobAddParameter(
            id=self.get_resource_name('batch_job1_'),
            pool_info=models.PoolInformation(
                auto_pool_specification=auto_pool
            ),
            job_preparation_task=job_prep,
            job_release_task=job_release
        )
        response = client.job.add(job_param)
        self.assertIsNone(response)

        # Test Update Job
        constraints = models.JobConstraints(max_task_retry_count=3)
        options = models.JobUpdateParameter(
            priority=500,
            constraints=constraints,
            pool_info=models.PoolInformation(
                auto_pool_specification=auto_pool
            )
        )
        response = client.job.update(job_param.id, options)
        self.assertIsNone(response)

        # Test Patch Job
        options = models.JobPatchParameter(priority=900)
        response = client.job.patch(job_param.id, options)
        self.assertIsNone(response)

        job = client.job.get(job_param.id)
        self.assertIsInstance(job, models.CloudJob)
        self.assertEqual(job.id, job_param.id)
        self.assertEqual(job.constraints.max_task_retry_count, 3)
        self.assertEqual(job.priority, 900)

        # Test Create Job with Auto Complete
        job_auto_param = models.JobAddParameter(
            id=self.get_resource_name('batch_job2_'),
            on_all_tasks_complete=models.OnAllTasksComplete.terminate_job,
            on_task_failure=models.OnTaskFailure.perform_exit_options_job_action,
            pool_info=models.PoolInformation(
                auto_pool_specification=auto_pool
            )
        )
        response = client.job.add(job_auto_param)
        self.assertIsNone(response)
        job = client.job.get(job_auto_param.id)
        self.assertIsInstance(job, models.CloudJob)
        self.assertEqual(job.on_all_tasks_complete, models.OnAllTasksComplete.terminate_job)
        self.assertEqual(job.on_task_failure, models.OnTaskFailure.perform_exit_options_job_action)

        # Test List Jobs
        jobs = client.job.list()
        self.assertIsInstance(jobs, models.CloudJobPaged)
        self.assertEqual(len(list(jobs)), 2)

        # Test Disable Job
        response = client.job.disable(job_param.id, models.DisableJobOption.requeue)
        self.assertIsNone(response)

        # Test Enable Job
        response = client.job.enable(job_param.id)
        self.assertIsNone(response)

        # Prep and release task status
        task_status = client.job.list_preparation_and_release_task_status(job_param.id)
        self.assertIsInstance(task_status, models.JobPreparationAndReleaseTaskExecutionInformationPaged)
        self.assertEqual(list(task_status), [])

        # Test Terminate Job
        response = client.job.terminate(job_param.id)
        self.assertIsNone(response)

        # Test Delete Job
        response = client.job.delete(job_auto_param.id)
        self.assertIsNone(response)

        # Test Job Lifetime Statistics
        stats = client.job.get_all_lifetime_statistics()
        self.assertIsInstance(stats, models.JobStatistics)
        self.assertEqual(stats.num_succeeded_tasks, 0)
        self.assertEqual(stats.num_failed_tasks, 0)
    def test_batch_update_pools(self, **kwargs):
        client = self.create_sharedkey_client(**kwargs)
        # Test Create Paas Pool
        test_paas_pool = models.PoolAddParameter(
            id=self.get_resource_name('batch_paas_'),
            vm_size='small',
            cloud_service_configuration=models.CloudServiceConfiguration(
                os_family='5'
            ),
            start_task=models.StartTask(
                command_line="cmd.exe /c \"echo hello world\"",
                resource_files=[models.ResourceFile('https://blobsource.com', 'filename.txt')],
                environment_settings=[models.EnvironmentSetting('ENV_VAR', 'env_value')],
                user_identity=models.UserIdentity(
                    auto_user=models.AutoUserSpecification(
                        elevation_level=models.ElevationLevel.admin
                    )
                )
            )
        )
        response = client.pool.add(test_paas_pool)
        self.assertIsNone(response)

        # Test Upgrade Pool OS
        self.assertBatchError(
            "PoolVersionEqualsUpgradeVersion",
            client.pool.upgrade_os,
            test_paas_pool.id,
            "*"
        )

        # Test Update Pool Parameters
        params = models.PoolUpdatePropertiesParameter([], [], [models.MetadataItem('foo', 'bar')])
        response = client.pool.update_properties(test_paas_pool.id, params)
        self.assertIsNone(response)

        # Test Patch Pool Parameters
        params = models.PoolPatchParameter(metadata=[models.MetadataItem('foo2', 'bar2')])
        response = client.pool.patch(test_paas_pool.id, params)
        self.assertIsNone(response)

        # Test Pool Exists
        response = client.pool.exists(test_paas_pool.id)
        self.assertTrue(response)

        # Test Get Pool
        pool = client.pool.get(test_paas_pool.id)
        self.assertIsInstance(pool, models.CloudPool)
        self.assertEqual(pool.id, test_paas_pool.id)
        self.assertEqual(pool.state, models.PoolState.active)
        self.assertEqual(pool.allocation_state, models.AllocationState.steady)
        self.assertEqual(pool.cloud_service_configuration.os_family, '5')
        self.assertEqual(pool.vm_size, 'small')
        self.assertIsNone(pool.start_task)
        self.assertEqual(pool.metadata[0].name, 'foo2')
        self.assertEqual(pool.metadata[0].value, 'bar2')

        # Test Get Pool with OData Clauses
        options = models.PoolGetOptions(select='id,state', expand='stats')
        pool = client.pool.get(test_paas_pool.id, options)
        self.assertIsInstance(pool, models.CloudPool)
        self.assertEqual(pool.id, test_paas_pool.id)
        self.assertEqual(pool.state, models.PoolState.active)
        self.assertIsNone(pool.allocation_state)
        self.assertIsNone(pool.vm_size)

        # Test Delete Pool
        response = client.pool.delete(test_paas_pool.id)
        self.assertIsNone(response)
Example #5
0
    def configure_pool(  # pylint: disable=too-many-arguments
        self,
        pool_id: str,
        vm_size: Optional[str] = None,
        vm_publisher: Optional[str] = None,
        vm_offer: Optional[str] = None,
        sku_starts_with: Optional[str] = None,
        vm_sku: Optional[str] = None,
        vm_version: Optional[str] = None,
        vm_node_agent_sku_id: Optional[str] = None,
        os_family: Optional[str] = None,
        os_version: Optional[str] = None,
        display_name: Optional[str] = None,
        target_dedicated_nodes: Optional[int] = None,
        use_latest_image_and_sku: bool = False,
        **kwargs,
    ) -> PoolAddParameter:
        """
        Configures a pool

        :param pool_id: A string that uniquely identifies the Pool within the Account
        :type pool_id: str

        :param vm_size: The size of virtual machines in the Pool.
        :type vm_size: str

        :param display_name: The display name for the Pool
        :type display_name: str

        :param target_dedicated_nodes: The desired number of dedicated Compute Nodes in the Pool.
        :type target_dedicated_nodes: Optional[int]

        :param use_latest_image_and_sku: Whether to use the latest verified vm image and sku
        :type use_latest_image_and_sku: bool

        :param vm_publisher: The publisher of the Azure Virtual Machines Marketplace Image.
            For example, Canonical or MicrosoftWindowsServer.
        :type vm_publisher: Optional[str]

        :param vm_offer: The offer type of the Azure Virtual Machines Marketplace Image.
            For example, UbuntuServer or WindowsServer.
        :type vm_offer: Optional[str]

        :param sku_starts_with: The start name of the sku to search
        :type sku_starts_with: Optional[str]

        :param vm_sku: The name of the virtual machine sku to use
        :type vm_sku: Optional[str]

        :param vm_version: The version of the virtual machine
        :param vm_version: str

        :param vm_node_agent_sku_id: The node agent sku id of the virtual machine
        :type vm_node_agent_sku_id: Optional[str]

        :param os_family: The Azure Guest OS family to be installed on the virtual machines in the Pool.
        :type os_family: Optional[str]

        :param os_version: The OS family version
        :type os_version: Optional[str]

        """
        if use_latest_image_and_sku:
            self.log.info('Using latest verified virtual machine image with node agent sku')
            sku_to_use, image_ref_to_use = self._get_latest_verified_image_vm_and_sku(
                publisher=vm_publisher, offer=vm_offer, sku_starts_with=sku_starts_with
            )
            pool = batch_models.PoolAddParameter(
                id=pool_id,
                vm_size=vm_size,
                display_name=display_name,
                virtual_machine_configuration=batch_models.VirtualMachineConfiguration(
                    image_reference=image_ref_to_use, node_agent_sku_id=sku_to_use
                ),
                target_dedicated_nodes=target_dedicated_nodes,
                **kwargs,
            )

        elif os_family:
            self.log.info(
                'Using cloud service configuration to create pool, virtual machine configuration ignored'
            )
            pool = batch_models.PoolAddParameter(
                id=pool_id,
                vm_size=vm_size,
                display_name=display_name,
                cloud_service_configuration=batch_models.CloudServiceConfiguration(
                    os_family=os_family, os_version=os_version
                ),
                target_dedicated_nodes=target_dedicated_nodes,
                **kwargs,
            )

        else:
            self.log.info('Using virtual machine configuration to create a pool')
            pool = batch_models.PoolAddParameter(
                id=pool_id,
                vm_size=vm_size,
                display_name=display_name,
                virtual_machine_configuration=batch_models.VirtualMachineConfiguration(
                    image_reference=batch_models.ImageReference(
                        publisher=vm_publisher,
                        offer=vm_offer,
                        sku=vm_sku,
                        version=vm_version,
                    ),
                    node_agent_sku_id=vm_node_agent_sku_id,
                ),
                target_dedicated_nodes=target_dedicated_nodes,
                **kwargs,
            )
        return pool
Example #6
0
def create_job_schedule(batch_client, job_schedule_id, vm_size, vm_count,
                        block_blob_client):
    """Creates an Azure Batch pool and job schedule with the specified ids.

    :param batch_client: The batch client to use.
    :type batch_client: `batchserviceclient.BatchServiceClient`
    :param str job_schedule_id: The id of the job schedule to create
    :param str vm_size: vm size (sku)
    :param int vm_count: number of vms to allocate
    :param block_blob_client: The storage block blob client to use.
    :type block_blob_client: `azure.storage.blob.BlockBlobService`
    """
    cloud_service_config = batchmodels.CloudServiceConfiguration(os_family='6')

    user_id = batchmodels.UserIdentity(
        auto_user=batchmodels.AutoUserSpecification(
            elevation_level=_USER_ELEVATION_LEVEL))

    python_download = batchmodels.ResourceFile(http_url=_PYTHON_DOWNLOAD,
                                               file_path='python373.exe')

    pool_info = batchmodels.PoolInformation(
        auto_pool_specification=batchmodels.AutoPoolSpecification(
            auto_pool_id_prefix="JobScheduler",
            pool=batchmodels.PoolSpecification(
                vm_size=vm_size,
                target_dedicated_nodes=vm_count,
                cloud_service_configuration=cloud_service_config,
                start_task=batchmodels.StartTask(
                    command_line=common.helpers.wrap_commands_in_shell(
                        'windows', ['{}'.format(_PYTHON_INSTALL)]),
                    resource_files=[python_download],
                    wait_for_success=True,
                    user_identity=user_id)),
            keep_alive=False,
            pool_lifetime_option=batchmodels.PoolLifetimeOption.job))

    sas_url = common.helpers.upload_blob_and_create_sas(
        block_blob_client, _CONTAINER_NAME, _SIMPLE_TASK_NAME,
        _SIMPLE_TASK_PATH,
        datetime.datetime.utcnow() + datetime.timedelta(minutes=30))

    job_spec = batchmodels.JobSpecification(
        pool_info=pool_info,
        # Terminate job once all tasks under it are complete to allow for a new
        # job to be created under the schedule
        on_all_tasks_complete=batchmodels.OnAllTasksComplete.terminate_job,
        job_manager_task=batchmodels.JobManagerTask(
            id="JobManagerTask",
            command_line=common.helpers.wrap_commands_in_shell(
                'windows', ['python {}'.format(_SIMPLE_TASK_NAME)]),
            resource_files=[
                batchmodels.ResourceFile(file_path=_SIMPLE_TASK_NAME,
                                         http_url=sas_url)
            ]))

    do_not_run_after = datetime.datetime.utcnow() \
        + datetime.timedelta(minutes=30)

    schedule = batchmodels.Schedule(
        do_not_run_after=do_not_run_after,
        recurrence_interval=datetime.timedelta(minutes=10))

    scheduled_job = batchmodels.JobScheduleAddParameter(
        id=job_schedule_id, schedule=schedule, job_specification=job_spec)

    batch_client.job_schedule.add(cloud_job_schedule=scheduled_job)
Example #7
0
    def get_pool(self, pool_id, vm_size="standard_d15_v2", node_count=0):
        '''
        Creates an Azure Batch pool.

        :param pool_id: The pool_id of the pool to create
        :type pool_id: string

        :param vm_size: the type of compute nodes in the pool. (Defaults to 'standard_d15_v2')
        :type vm_size: string

        :param node_count: The number of compute nodes to initially create in the pool. Defaults to 0.
        :type node_count: number

        :rtype: string
        :return: the pool_id of the create pool
        '''
        batch_client = self.batch_client()
        pool_list = list(batch_client.pool.list())

        for pool in pool_list:
            if pool.id == pool_id:  #We have a pool with this pool_id, is it busy?
                node_list = list(batch_client.compute_node.list(pool.id))
                for node in node_list:
                    if node.running_tasks_count > 0:
                        logging.info(
                            "pool '{0}' exists and is busy".format(pool_id))
                        break
                return pool.id

        logging.info(
            "pool '{0}' does not exist and will be created".format(pool_id))

        user_identity = batchmodels.UserIdentity(
            auto_user=batchmodels.AutoUserSpecification(
                elevation_level='admin'))
        start_task = batchmodels.StartTask(
            command_line="cmd /c %AZ_BATCH_APP_PACKAGE_STARTUP%\startup.bat",
            user_identity=user_identity,
            wait_for_success=True)
        new_pool = batchmodels.PoolAddParameter(id=pool_id,
                                                vm_size=vm_size,
                                                start_task=start_task)
        new_pool.target_dedicated = node_count
        new_pool.max_tasks_per_node = 1
        cloud_service_configuration = batchmodels.CloudServiceConfiguration(
            os_family=4)
        new_pool.cloud_service_configuration = cloud_service_configuration
        new_pool.application_package_references = [
            batchmodels.ApplicationPackageReference("anaconda2"),
            batchmodels.ApplicationPackageReference("startup")
        ]

        #add the vnet
        #The ARM resource identifier of the virtual network subnet which the compute nodes of the pool will join. The virtual
        #network must be in the same region and subscription as the Azure Batch
        #account. This property can only be specified for pools created with a
        #cloudServiceConfiguration.
        #		value	u'Property subnetId should be of the form /subscriptions/{0}/resourceGroups/{1}/providers/{2}/virtualNetworks/{3}/subnets/{4}'	unicode
        new_pool.network_configuration = batchmodels.NetworkConfiguration(
            self.vnet + "/subnets/default")

        try:
            batch_client.pool.add(new_pool)
        except Exception, e:
            print e