jenkinsci / azure-vm-agents-plugin

This repo is for azure vm agents plugin for jenkins. Azure devops CICD is the team which owns it for now
https://plugins.jenkins.io/azure-vm-agents/
43 stars 96 forks source link

Block blobs are not supported #284

Open nirud opened 3 years ago

nirud commented 3 years ago

Version report

Jenkins and plugins versions report:

Jenkins: 2.277.4 OS: Linux - 5.4.0-1046-azure azure-vm-agent:780.v50d067d02f76

Jenkins is running in latest lts docker image The Agent is Windows Server 2016 Datacenter

Reproduction steps

I trying to deploy an agent and i do get the following stacktrace:

`AzureVMManagementServiceDelegate: deployment: Unable to deploy Also: java.lang.Exception: #block terminated with an error at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99) at reactor.core.publisher.Mono.block(Mono.java:1703) at com.azure.storage.common.implementation.StorageImplUtils.blockWithOptionalTimeout(StorageImplUtils.java:128) at com.azure.storage.blob.BlobClient.uploadWithResponse(BlobClient.java:266) at com.azure.storage.blob.BlobClient.uploadWithResponse(BlobClient.java:227) at com.azure.storage.blob.BlobClient.upload(BlobClient.java:174) at com.microsoft.azure.vmagent.AzureVMManagementServiceDelegate.uploadCustomScript(AzureVMManagementServiceDelegate.java:867) at com.microsoft.azure.vmagent.AzureVMManagementServiceDelegate.createDeployment(AzureVMManagementServiceDelegate.java:516) at com.microsoft.azure.vmagent.AzureVMManagementServiceDelegate.createDeployment(AzureVMManagementServiceDelegate.java:190) at com.microsoft.azure.vmagent.AzureVMAgentTemplate.provisionAgents(AzureVMAgentTemplate.java:1232) at com.microsoft.azure.vmagent.AzureVMCloud$1.call(AzureVMCloud.java:780) at com.microsoft.azure.vmagent.AzureVMCloud$1.call(AzureVMCloud.java:776) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) com.azure.storage.blob.models.BlobStorageException: Status code 400, "<?xml version="1.0" encoding="utf-8"?>

BlobTypeNotSupportedBlock blobs are not supported. RequestId:c1faaee5-e01c-0082-7772-578288000000 Time:2021-06-02T05:48:01.4190843Z" at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.azure.core.http.rest.RestProxy.instantiateUnexpectedException(RestProxy.java:343) at com.azure.core.http.rest.RestProxy.lambda$ensureExpectedStatus$5(RestProxy.java:382) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815) at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.signalCached(MonoCacheTime.java:337) at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.onNext(MonoCacheTime.java:354) at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2397) at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.onSubscribe(MonoCacheTime.java:293) at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:192) at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) at reactor.core.publisher.MonoCacheTime.subscribeOrReturn(MonoCacheTime.java:143) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157) at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onNext(FluxDoFinally.java:130) at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:118) at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:220) at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onNext(FluxDoFinally.java:130) at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onNext(FluxHandleFuseable.java:184) at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815) at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onComplete(MonoCollectList.java:128) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:259) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:401) at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:416) at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:470) at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:685) at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1504) at io.netty.handler.ssl.SslHandler.decodeNonJdkCompatible(SslHandler.java:1265) at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1302) at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508) at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795) at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480) at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) Caused: com.microsoft.azure.vmagent.exceptions.AzureCloudException: Failed to create Page Blob with script's length: 1375 at com.microsoft.azure.vmagent.exceptions.AzureCloudException.create(AzureCloudException.java:54) at com.microsoft.azure.vmagent.AzureVMManagementServiceDelegate.uploadCustomScript(AzureVMManagementServiceDelegate.java:870) at com.microsoft.azure.vmagent.AzureVMManagementServiceDelegate.createDeployment(AzureVMManagementServiceDelegate.java:516) at com.microsoft.azure.vmagent.AzureVMManagementServiceDelegate.createDeployment(AzureVMManagementServiceDelegate.java:190) at com.microsoft.azure.vmagent.AzureVMAgentTemplate.provisionAgents(AzureVMAgentTemplate.java:1232) at com.microsoft.azure.vmagent.AzureVMCloud$1.call(AzureVMCloud.java:780) at com.microsoft.azure.vmagent.AzureVMCloud$1.call(AzureVMCloud.java:776) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)` It downgraded to azure-vm-agents:765.vbb9943c5070c and there it does work. (I just guessed that the Feature "Support SSD / premium SSD managed disks" may have something to do with this and took the version before that). ### Results Expected result: Agent gets deployed Actual result: Agents does not get deployed
timja commented 3 years ago

What type is your storage account?

https://stackoverflow.com/a/41572070/4951015

This is your error:

Status code 400, "<?xml version="1.0" encoding="utf-8"?> <Error><Code>BlobTypeNotSupported</Code><Message>Block blobs are not supported. RequestId:c1faaee5-e01c-0082-7772-578288000000 Time:2021-06-02T05:48:01.4190843Z</Message></Error>"
nirud commented 3 years ago

The type is Premium LRS.

It does work with 765.vbb9943c5070c and the same storage account.

I also tried to let the plugin create a new storage account, but that lead to the same stack trace.

timja commented 3 years ago

by let the plugin create a new storage account did you give it a new name?

the new / existing doesn't actually create a new one / do anything really.

it just checks if the storage account exists and if it doesn't then it creates a new one

nirud commented 3 years ago

I choose "new" and gave it a new name. And i saw in the azure portal that it created a new storage account.

timja commented 3 years ago

Ok can you provide your config please?

Configuration as code export or xml config, redact anything you wish with ****

nirud commented 3 years ago

Yes i can: here is the JCaC (i removed sensitive or unrelated things):

JCasC:
    enabled: true
    pluginVersion: "1.50"
    configScripts:
      default: |
        jobs:
         *** 

        credentials:
          system:
            domainCredentials:
            - credentials:
              - azure:
                ***
        jenkins:
          nodes:
          - permanent:
            ***
          agentProtocols:
          - "JNLP4-connect"
          - "Ping"
          crumbIssuer:
            standard:
              excludeClientIPFromCrumb: true
          disableRememberMe: false
          mode: EXCLUSIVE
          numExecutors: 0
          primaryView:
            all:
              name: "all"
          quietPeriod: 5
          scmCheckoutRetryCount: 0
          remotingSecurity:
            enabled: true
          securityRealm:
            azure:
              ****
          slaveAgentPort: 50000
          views:
          - all:
              name: "all"
          authorizationStrategy:
             ****
          clouds:
            - azureVM:
                azureCredentialsId: ****
                cloudName: "Azure"
                configurationStatus: "pass"
                deploymentTimeout: 1200
                existingResourceGroupName: ****
                maxVirtualMachinesLimit: 20
                resourceGroupReferenceType: "existing"
                vmTemplates:
                - agentLaunchMethod: "SSH"
                  agentWorkspace: "C:\\workspace"
                  builtInImage: "Windows Server 2016"
                  credentialsId: "****"
                  diskType: "managed"
                  doNotUseMachineIfInitFails: true
                  enableMSI: false
                  enableUAMI: false
                  executeInitScriptAsRoot: true
                  existingStorageAccountName: "upwjenkins"
                  imageReference:
                    offer: "WindowsServer"
                    publisher: "MicrosoftWindowsServer"
                    sku: "2016-Datacenter"
                    version: "latest"
                  imageTopLevelType: "advanced"
                  initScript: |-
                    # Generell Setup
                    Set-ExecutionPolicy Unrestricted
                    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
                    Set-MpPreference -DisableRealtimeMonitoring $true

                    #Disable Automatic Windows Updates
                    Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU -Name AUOptions -Value 1

                    # Download and Install Java
                    Set-Location C:\
                    $source = "****
                    $destination = "C:\OpenJDK.msi"
                    $client = new-object System.Net.WebClient
                    $client.downloadFile($source, $destination)
                    $proc = Start-Process "msiexec.exe" -ArgumentList "/i ^${destination} ADDLOCAL=FeatureMain /quiet" -Wait -PassThru
                    $proc.WaitForExit()
                    $javaHome = "C:\Program Files\AdoptOpenJDK\jdk-11.0.7.10-hotspot"
                    [System.Environment]::SetEnvironmentVariable("JAVA_HOME", ^${javaHome}, "Machine")
                    [System.Environment]::SetEnvironmentVariable("PATH", $Env:Path + ";^${javaHome}\bin", "Machine")
                    $Env:Path += ";^${javaHome}\bin"

                    # Install Git
                    $source = "https://github.com/git-for-windows/git/releases/download/v2.29.0.windows.1/Git-2.29.0-64-bit.exe"
                    $destination = "C:\Git-64-bit.exe"
                    $webClient = New-Object System.Net.WebClient
                    $webClient.DownloadFile($source, $destination)
                    $proc = Start-Process -FilePath $destination -ArgumentList "/VERYSILENT" -Wait -PassThru
                    $proc.WaitForExit()
                    $Env:Path += ";C:\Program Files\Git\cmd;C:\Program Files\Git\usr\bin"
                    #Disable git credential manager, get more details in https://support.cloudbees.com/hc/en-us/articles/221046888-Build-Hang-or-Fail-with-Git-for-Windows
                    git config --system --unset credential.helper
                    git config --system core.longpaths true

                    #Install Wix
                    $source = "https://github.com/wixtoolset/wix3/releases/download/wix3112rtm/wix311-binaries.zip"
                    $destination = "C:\wix311.zip"
                    $client = new-object System.Net.WebClient
                    $client.downloadFile($source, $destination)
                    $wixDir = "C:\Program Files (x86)\Wix"
                    Expand-Archive -LiteralPath $destination -DestinationPath $wixDir
                    [System.Environment]::SetEnvironmentVariable("PATH", $Env:Path + ";^${wixDir}", "Machine")
                  installDocker: false
                  installGit: false
                  installMaven: false
                  labels: "wix"
                  location: "West Europe"
                  noOfParallelJobs: 1
                  osDiskSize: 0
                  osType: "Windows"
                  preInstallSsh: true
                  retentionStrategy:
                    azureVMCloudRetentionStrategy:
                      idleTerminationMinutes: 60
                  shutdownOnIdle: true 
                  storageAccountNameReferenceType: "existing"
                  storageAccountType: "Premium_LRS"
                  subnetName: "dwag-mpw"
                  templateDesc: "Wix Installer Builder"
                  templateDisabled: false
                  templateName: "wix"
                  usageMode: "Only build jobs with label expressions matching this node"
                  usePrivateIP: true
                  virtualMachineSize: "Standard_B8ms"
                  virtualNetworkName: "VN-jnk-agents"
                  virtualNetworkResourceGroupName: "RG-INFRA"
        security:
          apiToken:
            usageStatisticsEnabled: false
        unclassified:
          location:
            url: ****
          mailer:
            charset: "UTF-8"
            useSsl: false
        tool:
          git:
            installations:
            - home: "git"
              name: "Default"
            - home: "jgit"
              name: "jgit"
      welcome-message: |
        jenkins:
          systemMessage: "Jenkins Master"

  sidecars:
    configAutoReload:
      enabled: false
timja commented 3 years ago

@nirud if you check the help for storageAccountType it says to not use Premium when using managed disks, that should fix your issue and allow you to upgrade the plugin.

I'll look at a fix for this as well though and a UI warning

timja commented 3 years ago

I've had a go at fixing this, it seems like Premium_LRS is only really designed for storing VHDs for unmanaged disks.

The track 2 azure storage SDK does not make working with these blobs easy at all, the 'general' methods all only work with block blobs, I can't see it in the JavaDoc at all but if I dig into the code a few layers down they grab the block blob client.

There is support for PageBlobs but you have to split the file into 512 byte blocks and upload each page individually.

While certainly possible to do (or create an upstream issue for better support)

I would like to wait and see if others hit this, given it appears this instance is because of mis-configuration.

nirud commented 3 years ago

Hi,

that is fine for me. I will change the configuration. But it would be nice if there is a clearer warning in the UI. Or maybe this could be a check in the "Validate Configuration" function for the templates, that would have made my troubleshooting easier.

timja commented 3 years ago

UI warning is added in https://github.com/jenkinsci/azure-vm-agents-plugin/pull/285 which is being released atm

Edit: https://github.com/jenkinsci/azure-vm-agents-plugin/releases/tag/781.v5877a4d99d28