Code Monkey home page Code Monkey logo

openstack-cloud-plugin's Introduction

OpenStack Cloud plugin for Jenkins

Provision nodes from OpenStack on demand.

Build Status

Essentials

In order to provision new nodes when Jenkins load goes high, administrator needs to configure Cloud and one or more Templates on global configuration page. Cloud represents connection to particular OpenStack project (tenant). In order to use several openstack instances or projects, it is necessary to configure several Clouds in Jenkins. Template can be seen as a definition of particular kind of node. Template is the primary holder of all the attributes for OpenStack machine to be provisioned (image, flavor, etc.) as well as for Jenkins node (number of executors, etc.). Note the attributes can be configured on Cloud level as well. Such configuration will be then used as default for its templates. For example, if all nodes are supposed to use the same key-pair there is no need to state it in every template, it can be configured on cloud level and leave the filed blank in the templates.

Aside from machine/node attributes, every template require name and labels to be configured. Name will serve both as an identifier of the template as well as a name prefix for Jenkins node and OpenStack machine (that is why some limitations apply here). Labels field expects a set of Jenkins labels that will be assigned to all nodes that the template provisions. It will also be used to determine which cloud and template to use to process Jenkins load. When there is a build with no label requirements, any template can be used to provision the node. Build with label restriction can trigger provisioning only on templates with matching label set. The attributes at template level will inherit all global values (the value in effect is printed under the field on hte config page). In case required field do not have a default nor current value, it will be reported.

The exception is here is the Instance Cap field that determines the maximal ammount of maches to be running either per whole cloud or per template. This is so one can limit the total number and number per individual template at the same time.

User data

Every template can declare user-data script to be passed to cloud-init to customize the machine that is provisioned. Note that the image needs to support cloud init explicitly.

Before the script is sent to OpenStack, plugin injects several values using ${VARIABLE_NAME} syntax:

  • JENKINS_URL: The URL of the Jenkins instance
  • SLAVE_JAR_URL: URL of the slave.jar - the agent executable
  • SLAVE_JNLP_URL: The endpoint URL for JNLP connection
  • SLAVE_JNLP_SECRET: The JNLP 'secret' key. This key authorizes to connect Jenkins agent process to a Jenkins computer. Note that referencing this in server user-data (and then using it to launch agent process) makes it exposed to any user or automation permitted to access the Jenkins agent (including running builds). Also, when OpenStack deployment uses metadata service, which it often does, it must be deployed in a way this is guaranteed not to leak. See OSSN-0074 for further details.
  • SLAVE_LABELS: Labels of the corresponding Jenkins computer

Reporting

Openstack plugin utilizes Cloud Statistics that captures failures and time trends of past provisioning attempts.

Configuration As Code

Since version 2.46, JCasC is supported. Example:

jenkins:
  clouds:
    - openstack:
        name: "foo"
        endPointUrl: "https://acme.com:5000"
        credentialsId: "openstack_service_credentials"
        ignoreSsl: false
        zone: foo
        slaveOptions:
          bootSource:
            image:
              name: "Image Name"
          hardwareId: "hid"
          networkId: "net"
          userDataId: "user-data-id"
          instanceCap: 11
          instancesMin: 1
          floatingIpPool: "baz"
          securityGroups: "s1,s2"
          availabilityZone: "bax"
          startTimeout: 15
          keyPairName: "key"
          numExecutors: 2
          jvmOptions: "-Xmx1G"
          fsRoot: "/tmp/foo"
          launcherFactory:
            ssh:
              credentialsId: "openstack_ssh_key"
              javaPath: "/bin/true"
          retentionTime: 42
        templates:
          - name: "empty"
            labels: "linux"
          - name: "jnlp"
            labels: "jnlp"
            slaveOptions:
              launcherFactory: "jnlp"
          - name: "volumeSnapshot"
            labels: "volume"
            slaveOptions:
              bootSource:
                volumeSnapshot:
                  name: "Volume name"
          - name: "volumeFromImage"
            labels: "volume from image"
            slaveOptions:
              bootSource:
                volumeFromImage:
                  name: "Volume name"
                  volumeSize: 15
 
unclassified:
  globalConfigFiles:
    configs:
      - openstackUserData:
          id: user-data-id
          name: "My user data"
          comment: "... with a comment"
          content: >
            #cloud-config
            disable_root: 0
            ssh_pwauth: True
            chpasswd: { expire: False }
 
            users:
              - name: root
                password: toor
                lock-passwd: false
                inactive: false
                system: false
 
credentials:
  system:
    domainCredentials:
      - credentials:
          - openstackV3:
              scope: SYSTEM
              id: "openstack_service_credentials"
              description: "desc"
              userName: "foo"
              userDomain: "acme.com"
              projectName: "casc"
              projectDomain: "acme.com"
              password: "bar" # Do not hardcode plaintext secrets for real world declarations!
          - openstackV2:
              scope: SYSTEM
              id: "openstack_service_credentialsV2"
              description: "desc"
              username: "username"
              password: "pwd" # Do not hardcode plaintext secrets for real world declarations!
              tenant: "tnt"
          - basicSSHUserPrivateKey:
              scope: SYSTEM
              id: "openstack_ssh_key"
              username: "jenkins"
              privateKeySource:
                directEntry:
                  # Do not hardcode plaintext secrets for real world declarations!
                  privateKey: |
                    -----BEGIN OPENSSH PRIVATE KEY-----
                    b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
                    NhAAAAAwEAAQAAAQEAleOyx/pWbWBWrKOXyDpXio33Y6jAXdAi2mqo1nKIcIX75U71WxcR
                    2+i+IqlyVm85YcBQ3xKZ9KVxW9rCGn/KNJkQdQa+hGltJUHJNLPGCoZG0Qj5LLhXW3SSOQ
                    3X2e8FMLTmrHeBqOZhFJr9ijlDX23Hbo5JENGs8MCXAfFBcthBViWWouaon2qgH1xncT19
                    OVpQbAozwgqM1pl+6fL1yvBw89emAix+G+iy+r89fk+mb/5jwkikFsk9qhZrQIkrSsGS2h
                    noH+LeRUtMyDcjXcqC214PtyI38hA+TxjIfqNBz8VF9juhAq28kOVFMPBNxoI8bW2F6/1h
                    49Jkg9iLzQAAA8i2KKHJtiihyQAAAAdzc2gtcnNhAAABAQCV47LH+lZtYFaso5fIOleKjf
                    djqMBd0CLaaqjWcohwhfvlTvVbFxHb6L4iqXJWbzlhwFDfEpn0pXFb2sIaf8o0mRB1Br6E
                    aW0lQck0s8YKhkbRCPksuFdbdJI5DdfZ7wUwtOasd4Go5mEUmv2KOUNfbcdujkkQ0azwwJ
                    cB8UFy2EFWJZai5qifaqAfXGdxPX05WlBsCjPCCozWmX7p8vXK8HDz16YCLH4b6LL6vz1+
                    T6Zv/mPCSKQWyT2qFmtAiStKwZLaGegf4t5FS0zINyNdyoLbXg+3IjfyED5PGMh+o0HPxU
                    X2O6ECrbyQ5UUw8E3GgjxtbYXr/WHj0mSD2IvNAAAAAwEAAQAAAQBJrcbZBFZtp3iTnkri
                    8sLLaeOcinwc4U3wnZNm7p/g6AudeYWkBCAUQEEOWsrIcB39zgIy1Tr2hkjFxS+6xOxJlK
                    ABVpJaFlS/hqn4DRKhY8X1xPpvICJY42FpSEO9bf/YJGRrjMcgljZMYa+VvXY/t3/b+Xcz
                    HE5tfc3893GbmK9YUvFu6WdGg/3J3M/L3NvJVlPDfq7hQkx1EPVv/w5B+CNrVRayKypVRj
                    3cV/akjVuSblOs227nFzEtt6WDFky7H0T7rwoJKT0Co+4gVheQGibzU726MdXgVI2W2SPo
                    h3HcQfA74FLi6JeM1s/Fkl4UZctbxzXXrtW3v8ecEbEhAAAAgFc8FdBS7Jbo+ofOgfmTBE
                    fCkvVU/TIvPrkz6KAJxuBaYYGpT+YtSoJwpmdjOn0M23KiDA/4i+1G/NVZXa/N22rUd9Gp
                    uSikOImAwrhB3hjr5c/8lt+iC89fdWQBEZs2QsxLeHPIqNnjYlyDa6Rz0t4lQe54rmbtXR
                    FYgMGGBglTAAAAgQDEYxhyBdzLMg1U8XTe6rQ41ikPuePdeUghP0JCjq7M5TzdTRCC1oDe
                    vwREeLNFOvDLdl8sqYGJTegpdVM2FHIQBmbxamM2Ms0YSETsCMWUHJguh3mKvIx8ICPkoZ
                    eNN2HlSxh2ug3unE9vANuJKZztAsnPMoafMPyKmH5XbL+F1QAAAIEAw2NZu/9a815Rwr7C
                    JbAt3jdjyM6MIVAFb7BQS1wtGsitZCaeb0Pond+T4j7mOTbzMZhE0lstwsWWrDWlX9LkHV
                    RsDHpCNTnxRfQeA1NL5LoTIW8OfjV2/NiGAa6INerBBURRKlIRJYdLmdi/IoNSzwBzC/mV
                    kh2nsVg0sOMNkhkAAAAMb2dvbmR6YUBhcmNoAQIDBAUGBw==
                    -----END OPENSSH PRIVATE KEY-----

Tips and tricks

  • User can manually provision agent from particular cloud/template on Manage Jenkins > Manage Nodes.
  • Plugin identifies OpenStack image/snapshot to provision by its name. The image can be updated/replaced in openstack and the plugin will not require update provided its name have not changed.
  • In case maximal instance number is specified on template level, the stricter of the two (global and template value) will be applied. Global value exists to ensure that the number of machines provisioned by plugin will not exceed certain limit. The template value can further restrict that at most N machines of given kind can be utilized at the same time.
  • Plugin can report maximal number of instances was reached while there is not adequate number of Jenkins nodes. It is because plugin inspects running OpenStack machines in order to cover machines being provisioned/deleted (that do not have Jenkins nodes) and instances that plugin failed to delete. In case the instance get leaked, please report that as a bug with all relevant FINE level logs attached.
  • On every agent provisioned by the plugin, there is an environment variable OPENSTACK_PUBLIC_IP declared with the public IP address allocated for the machine.

Troubleshooting

Accessing logs

Plugin uses INFO and above levels to report things user should worry about. For debugging, set it to FINEST - note the ALL level is not sufficient to print these. To configure OpenStack plugin logging in Jenkins UI go to Manage Jenkins > System Log > New Log Recorder and use jenkins.plugins.openstack.compute as the logger name.

Access openstack client from groovy console

Use Jenkins.instance.clouds[0][email protected]() to access the openstack4j client. Users are discouraged to use this anything else but querying the openstack (otherwise there is no way to ensure plugin will work correctly). For older versions fo the plugin use Jenkins.instance.clouds[0].openstack.@client.

User Data / Cloud init is not evaluated

The image might not support it at all or can fail executing it. Check machine log in OpenStack for further details. Note that for now, there is no guarantee the script will complete before machine is connected to Jenkins and builds are started.

Changelog

Releases Page

openstack-cloud-plugin's People

Contributors

abayer avatar basil avatar cboylan avatar ccustine avatar choeffer avatar cristianonicolai avatar darxriggs avatar dependabot[bot] avatar emonty avatar farix1337 avatar felfert avatar kei-yamazaki avatar leo-ccin2p3 avatar mavlyutov avatar mnaser avatar nacx avatar npotluri-rh avatar olivergondza avatar pjanouse avatar pjdarton avatar rabadin avatar richnou avatar robot-bucket avatar scottmarlow avatar sergw avatar signed8bit avatar spark404 avatar timja avatar vijaykiran avatar witokondoria avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

openstack-cloud-plugin's Issues

IP allocation over quota in pool

I have just updated to version 2.1 and I am happy to choose the floating ip pool. But now I get the following error while creating an instance:

javax.servlet.ServletException: ClientResponseException{message=IP allocation over quota in pool public., status=403, status-code=FORBIDDEN}
    at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:796)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:876)
    at org.kohsuke.stapler.MetaClass$5.doDispatch(MetaClass.java:233)
...

I have already 3 floating ips allocated to my openstack tenant (which is my quota for floating ips) but they are not assigned to an instance yet. It would be great if they would be used before trying to allocate a new one. (I am not allowed to allocate/deallocate floating ips)

Do not delete slave pending removal while still not idle

Since the delete operation on slave actually do not delete it but merely put temporarily offline. It is a good way to schedule it for removal manually even when currently busy. JCloudsCleanupThread should not assume it is idle even though retention strategy requires it to be idle to be put int pending delete state.

Move OpenStack plugin configuration to it's own page

Similar to plugins like Gerrit Trigger plugin, it would be nice if the OpenStack plugin configuration is own it's own page. We find that all the plugins having configuration inside the global jenkins config page inconvenient and overloads the page.

Instance cap is reached although the instances are not allocated in OS

It seems that either the instance cap is not reset properly, or the message printed to the log is misleading. The following log excerpt corresponds to the state when there were no nodes provisioned by OpenStackCloud plugin visible in QEOS. However, it starts with complaining about reaching the instance cap:

May 18, 2016 6:59:04 AM jenkins.plugins.openstack.compute.JCloudsCloud getAvailableTemplateProvider
INFO: Global instance cap (60) reached while adding capacity for label: RHEL
May 18, 2016 6:59:04 AM jenkins.plugins.openstack.compute.JCloudsSlaveTemplate provision
INFO: Provisioning new openstack node os-rhel7-715 with options jenkins.plugins.openstack.compute.SlaveOptions@44b9cef5[imageId=bxms-rhel7.2-snapshot,hardwareId=4,networkId=<null>,userDataId=jenkins.plugins.openstack.compute.UserDataConfig.1454073256508,instanceCap=60,floatingIpPool=public,securityGroups=default,availabilityZone=nova,startTimeout=1800000,keyPairName=bxms-qe-jenkins,numExecutors=1,jvmOptions=-Xmx700m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -Djavax.net.ssl.trustStore=/qa/tools/keystore/mw.truststore -Djavax.net.ssl.trustStorePassword=changeit -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9110 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=false,fsRoot=/home/hudson/hudson_workspace,credentialsId=c7c5fd01-0bc7-48dc-bb50-c0e46d2b2464,slaveType=SSH,retentionTime=30]
...
May 18, 2016 6:59:04 AM hudson.slaves.NodeProvisioner update
INFO: Started provisioning os-rhel7 from qeos with 1 executors. Remaining excess workload:9.738923
May 18, 2016 6:59:04 AM hudson.slaves.NodeProvisioner update
INFO: Started provisioning os-rhel7 from qeos with 1 executors. Remaining excess workload:8.738923
May 18, 2016 6:59:04 AM hudson.slaves.NodeProvisioner update
INFO: Started provisioning os-rhel7 from qeos with 1 executors. Remaining excess workload:7.738923
May 18, 2016 6:59:04 AM hudson.slaves.NodeProvisioner update
INFO: Started provisioning os-rhel7 from qeos with 1 executors. Remaining excess workload:6.738923
May 18, 2016 6:59:04 AM hudson.slaves.NodeProvisioner update
INFO: Started provisioning os-rhel7 from qeos with 1 executors. Remaining excess workload:5.738923
May 18, 2016 6:59:04 AM hudson.slaves.NodeProvisioner update
INFO: Started provisioning os-rhel7 from qeos with 1 executors. Remaining excess workload:4.738923
May 18, 2016 6:59:04 AM hudson.slaves.NodeProvisioner update
INFO: Started provisioning os-rhel7 from qeos with 1 executors. Remaining excess workload:3.738923
May 18, 2016 6:59:04 AM hudson.slaves.NodeProvisioner update
INFO: Started provisioning os-rhel7 from qeos with 1 executors. Remaining excess workload:2.738923
May 18, 2016 6:59:04 AM hudson.slaves.NodeProvisioner update
INFO: Started provisioning os-rhel7 from qeos with 1 executors. Remaining excess workload:1.7389231
May 18, 2016 6:59:04 AM hudson.slaves.NodeProvisioner update
INFO: Started provisioning os-rhel7 from qeos with 1 executors. Remaining excess workload:0.7389231

I still have from time to time clean the OpenStack instances - they are usually not in ERROR state, but in ACTIVE, although they often do not have IP address associated (not even the internal IP, i.e. not the Floating-IP address). I then have to shut them down using QEOS API - could this mean that the plugin is still tracking them somewhere and believes that the instance count is higher than it actually is?

Cache image/network/flavor/floating pool listings

When global config page is populated, the lists are downloaded from openstack instance on demand. All three items require custom request that is repeated for every cloud/template on the page. (So for 4 templates in one cloud there is 20 requests). This needs to be cached for a couple of seconds to avoid this.

Pick random temaplate to provision in case several matches the label

In case the first matching template got misconfigured (unable to provision, snapshot not working, etc.), plugin keeps picking it for further provisioning. It would be better to pick one at random if more matches the label to avoid it. Additional advantage is it will constantly test all other templates for early problem discovery.

Terminate instances once disfunctional

In case the slave goes temporarily offline after disk monitoring (full temp/workspace) it is of no use to keep it around waiting for user to clean that up while occupying openstack node.

The slaves offline with OfflineCause$ChannelTermination might be in the same category.

Report cloud setup health

Currently, only way to know if there ware any problems provisioning/connection the machines is to browse through the logs. Introduce user friendly way to see past provisioning attempts.

Add possibility to throttle the instance creation

When openstack-cloud-plugin provisions several instances at once, it might make the underlying OpenStack unrealiable (from my experience, when provisioning several (like 5) machines at once, some of them failed to provision). It would be nice to have a configuration option to limit the number of concurrent instances being provisioned.

Floating ip pool not found

I have just updated to Version 2.0.
Now I get the error "Floating ip pool not found" while creating an instance/node. The instance is created in openstack but has no floating ip assigned. In jenkins there is no new node created.

If I uncheck "Associate floating IP" in jenkins settings the creation works but it can not be contacted by jenkins (as expected).

This is the full stack trace:

javax.servlet.ServletException: ClientResponseException{message=Floating ip pool not found., status=404, status-code=NOT_FOUND}
    at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:796)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:876)
    at org.kohsuke.stapler.MetaClass$6.doDispatch(MetaClass.java:249)
    at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:53)
    at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:746)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:876)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:649)
    at org.kohsuke.stapler.Stapler.service(Stapler.java:238)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:686)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1494)
    at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:132)
    at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:123)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
    at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:86)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
    at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:51)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at jenkins.security.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:117)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:142)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at jenkins.security.BasicHeaderProcessor.doFilter(BasicHeaderProcessor.java:93)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
    at hudson.security.HttpSessionContextIntegrationFilter2.doFilter(HttpSessionContextIntegrationFilter2.java:67)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:76)
    at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:171)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
    at org.kohsuke.stapler.compression.CompressionFilter.doFilter(CompressionFilter.java:49)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
    at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:81)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
    at org.kohsuke.stapler.DiagnosticThreadNameFilter.doFilter(DiagnosticThreadNameFilter.java:30)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1474)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:499)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:533)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
    at org.eclipse.jetty.server.Server.handle(Server.java:370)
    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)
    at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:960)
    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1021)
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:668)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
    at winstone.BoundedExecutorService$1.run(BoundedExecutorService.java:77)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: ClientResponseException{message=Floating ip pool not found., status=404, status-code=NOT_FOUND}
    at org.openstack4j.core.transport.HttpExceptionHandler.mapException(HttpExceptionHandler.java:38)
    at org.openstack4j.core.transport.HttpExceptionHandler.mapException(HttpExceptionHandler.java:23)
    at org.openstack4j.core.transport.propagation.PropagateOnStatus.propagate(PropagateOnStatus.java:31)
    at org.openstack4j.core.transport.ExecutionOptions.propagate(ExecutionOptions.java:53)
    at org.openstack4j.core.transport.HttpEntityHandler.handle(HttpEntityHandler.java:39)
    at org.openstack4j.connectors.httpclient.HttpResponseImpl.getEntity(HttpResponseImpl.java:69)
    at org.openstack4j.openstack.internal.BaseOpenStackService$Invocation.execute(BaseOpenStackService.java:189)
    at org.openstack4j.openstack.compute.internal.ComputeFloatingIPServiceImpl.allocateIP(ComputeFloatingIPServiceImpl.java:48)
    at jenkins.plugins.openstack.compute.internal.Openstack.assignFloatingIp(Openstack.java:236)
    at jenkins.plugins.openstack.compute.JCloudsSlaveTemplate.provision(JCloudsSlaveTemplate.java:246)
    at jenkins.plugins.openstack.compute.JCloudsSlaveTemplate.provisionSlave(JCloudsSlaveTemplate.java:173)
    at jenkins.plugins.openstack.compute.JCloudsCloud.doProvision(JCloudsCloud.java:248)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.kohsuke.stapler.Function$InstanceFunction.invoke(Function.java:298)
    at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:161)
    at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:96)
    at org.kohsuke.stapler.MetaClass$1.doDispatch(MetaClass.java:121)
    at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:53)
    at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:746)
    ... 63 more

Allow to specify minimum number of slaves to be running for a given template

Hi @olivergondza

we have been successfully using your new version of the plugin in our CI, but the ~1-5 minute startup time of our slaves on our openstack prevent us using this plugin for checking pull requests.

This got us thinking, could you add an option to keep at least a pool of certain size of nodes at all times?

This would probably require two things:

  1. when plugin would want to destroy a node, it would need to check not only retention time, but configuration for minimum number of nodes in pool.
  2. When number of aviable executors(?) goes below a treshold, plugin would automatically start a new node.

What do you think?

The provisioned instance is not deleted if delete fails

When openstack-cloud-plugin deletes a slave and OpenStack fails to delete the machine, the plugin does not re-attempt to delete the machine again. This results in OpenStack filled with instances in ERROR state which ultimately leads to openstack-cloud-plugin unable to provision any new slave, because instance cap is reached.

The same behaviour can be observed when manually working with OpenStack - sometimes the instance deletion fails and you have to delete it 2 or 3 times again until the delete succeeds.

Ideally, the openstack-cloud-plugin should be able to cope with this unreliable OpenStack behaviour and re-attempt to delete the instance if it failed several times (ideally until a configurable number of retries is reached).

Check for available resources before starting instances in jobs

It would be nice if jobs that declare they need additional resources can check that there is enough resources in openstack before trying to spin up VMs. This feature should also allow retrying up to a timeout limit before failing the job.

Our use case is that we have many integration jobs that spin up full labs of VMs before running the job. The current openstack plugin fails the build if the instances could not be spun up. We would prefer that the job confirmed that there was enough resources to spin up the additional instances before trying, and if the resources were not available check again periodically until I can allocate the resources. It should then fail the build only once reaching some timeout value like 30 minutes or so.

Job not started

Hello,

The jenkins version we have will keep the job in pending mode, not starting it because no compatible slave are available.
Actually, it would need to start the job to deploy the node in openstack.

Any way to force the start for cloud node ?

Publish to cloud storage

It would be nice if the plugin supported publishing files to cloud storage like swift. The JClouds plugin had support for a publisher that pushed the files to a cloud provider.

Extract cloud / template fields for easier overriding

Some image attributes are now scoped to cloud (bootTimeout) and some only to the template (fsRoot). It is useful not to repeat oneself and have a possibility to override cloud defaults. (Only retentionTime can be overriden at this point.)

To do so, we need to extract the overridable properties to separate object to be attached to both cloud and every template. To compute the effective value the most specific value will be used (with rising priority): field default, cloud value, template value. Here is what I suggest:

Properties of cloud (not overridable)

  • name
  • identity
  • credential
  • endPointUrl
  • zone

Properties of template (not "centralisable")

  • name
  • labelString

Overridable properties

  • retentionTime
  • startTimeout
  • floatingIps
  • imageId
  • hardwareId
  • userDataId
  • numExecutors
  • jvmOptions
  • fsRoot
  • keyPairName
  • networkId
  • securityGroups
  • credentialsId
  • slaveType
  • availabilityZone

I am not sure what to do about instanceCap. There is a use-case to spin at most X instances of an image (due to licensing). The best thing I can think of is to have both cloud and template instance cap and provisioning will be aborted as soon as it hits one or the other. This way one can restrict total number of machines provisioned in the wort case and further constrain individual templates when needed. (Note this is not overriding as template can not relax cloud's constrain (unless we will have a special handling for instance cap of course)).

cryptic error message is shown when connecting with "tenant" account without "user" set: "Cannot connect to specified cloud, please check the identity and credentials: apiType compute not found in catalog []"

I used my "tenant" name and not "user:tenant" in the plugin configuration section on Jenkins | Configure Server page.

got this error message when clicking "Test Connection":

Cannot connect to specified cloud, please check the identity and credentials: 
apiType compute not found in catalog []

my endpoint URL: http://api-sfly1.client.metacloud.net:5000/v2.0
Jenkins version: 1.617
Openstack Cloud plugin version: 1.7

it would be nice to notify user that "user:tenant" should be used instead of just "tenant". and also explain the difference if possible...

Do not fail slave launch in case ssh is not available immediatelly.

#21

@signed8bit:

In my case, the launch method will immediately fail due to a connection error. I'd tried setting the various retry options in the SSHLauncher and never really saw retries happening. Other attempts just have an ssh connection hanging seemingly indefinitely e.g. several minutes. Given enough time I could successfully launch the slave manually via the Jenkins UI.

@juliogonzalez:

It tries to connect before the instance is ready to accept SSH connections, either because it's launching or not even connected to the network (connection refused sometimes, no route to host other times), and it doesn't retry anymore.

"Creating a new JClouds Slave" is blocking Jenkins initialization

using Jenkins 1.618 on Ubuntu 14.

I see this in /var/log/jenkins/jenkins.log:

Jun 29, 2015 5:14:30 PM jenkins.plugins.openstack.compute.JCloudsSlave createComputer
INFO: Creating a new JClouds Slave

and Jenkins seems to be stuck with this...
I suppose this will be unblocked eventually, but I think this should not prevent Jenkins UI from loading...

Propagate slave name into cloud `PlannedNode`

In the following message ASDF is in fact template name. IOW, the number suffix is missing so there is no way to identify particular slave/machine.

Mar 17, 2016 9:29:39 AM hudson.slaves.NodeProvisioner update
WARNING: Provisioned slave ASDF failed to launch

Network list unpopulated

The Instance Template section for inputting the network on which slaves should be created is empty, even when there are several available networks

Can't start slave due to getting image errors

javax.servlet.ServletException: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY at line 1 column 819
    at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:796)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:876)
    at org.kohsuke.stapler.MetaClass$6.doDispatch(MetaClass.java:249)
    at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:53)
    at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:746)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:876)
    at org.kohsuke.stapler.Stapler.invoke(Stapler.java:649)
    at org.kohsuke.stapler.Stapler.service(Stapler.java:238)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:686)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1494)
    at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:132)
    at hudson.plugins.greenballs.GreenBallFilter.doFilter(GreenBallFilter.java:58)
    at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:129)
    at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:123)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
    at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:49)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
    at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:51)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at jenkins.security.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:117)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:142)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at jenkins.security.BasicHeaderProcessor.doFilter(BasicHeaderProcessor.java:93)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
    at hudson.security.HttpSessionContextIntegrationFilter2.doFilter(HttpSessionContextIntegrationFilter2.java:67)
    at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:76)
    at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:171)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
    at org.kohsuke.stapler.compression.CompressionFilter.doFilter(CompressionFilter.java:49)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
    at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:81)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
    at org.kohsuke.stapler.DiagnosticThreadNameFilter.doFilter(DiagnosticThreadNameFilter.java:30)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1474)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:499)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:533)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
    at org.eclipse.jetty.server.Server.handle(Server.java:370)
    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)
    at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:960)
    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1021)
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:668)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
    at winstone.BoundedExecutorService$1.run(BoundedExecutorService.java:77)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY at line 1 column 819
    at com.google.gson.stream.JsonReader.nextString(JsonReader.java:821)
    at com.google.gson.internal.bind.TypeAdapters$13.read(TypeAdapters.java:358)
    at com.google.gson.internal.bind.TypeAdapters$13.read(TypeAdapters.java:346)
    at org.jclouds.json.internal.NullFilteringTypeAdapterFactories$MapTypeAdapter.read(NullFilteringTypeAdapterFactories.java:311)
    at org.jclouds.json.internal.NullFilteringTypeAdapterFactories$MapTypeAdapter.read(NullFilteringTypeAdapterFactories.java:281)
    at org.jclouds.json.internal.DeserializationConstructorAndReflectiveTypeAdapterFactory$ParameterReader.read(DeserializationConstructorAndReflectiveTypeAdapterFactory.java:260)
    at org.jclouds.json.internal.DeserializationConstructorAndReflectiveTypeAdapterFactory$DeserializeIntoParameterizedConstructor.read(DeserializationConstructorAndReflectiveTypeAdapterFactory.java:172)
    at org.jclouds.json.internal.NullFilteringTypeAdapterFactories$IterableTypeAdapter.readAndBuild(NullFilteringTypeAdapterFactories.java:90)
    at org.jclouds.json.internal.NullFilteringTypeAdapterFactories$IterableTypeAdapter.read(NullFilteringTypeAdapterFactories.java:82)
    at org.jclouds.json.internal.NullFilteringTypeAdapterFactories$IterableTypeAdapter.read(NullFilteringTypeAdapterFactories.java:61)
    at org.jclouds.json.internal.DeserializationConstructorAndReflectiveTypeAdapterFactory$ParameterReader.read(DeserializationConstructorAndReflectiveTypeAdapterFactory.java:260)
    at org.jclouds.json.internal.DeserializationConstructorAndReflectiveTypeAdapterFactory$DeserializeIntoParameterizedConstructor.read(DeserializationConstructorAndReflectiveTypeAdapterFactory.java:172)
    at com.google.gson.Gson.fromJson(Gson.java:803)
    at com.google.gson.Gson.fromJson(Gson.java:768)
    at com.google.gson.Gson.fromJson(Gson.java:717)
    at org.jclouds.json.internal.GsonWrapper.fromJson(GsonWrapper.java:42)
    at org.jclouds.http.functions.ParseJson.apply(ParseJson.java:82)
    at org.jclouds.http.functions.ParseJson.apply(ParseJson.java:76)
    at org.jclouds.http.functions.ParseJson.apply(ParseJson.java:62)
    at org.jclouds.http.functions.ParseJson.apply(ParseJson.java:42)
    at shaded.com.google.common.base.Functions$FunctionComposition.apply(Functions.java:216)
    at org.jclouds.rest.internal.InvokeHttpMethod.invoke(InvokeHttpMethod.java:90)
    at org.jclouds.rest.internal.InvokeHttpMethod.apply(InvokeHttpMethod.java:73)
    at org.jclouds.rest.internal.InvokeHttpMethod.apply(InvokeHttpMethod.java:44)
    at org.jclouds.reflect.FunctionalReflection$FunctionalInvocationHandler.handleInvocation(FunctionalReflection.java:117)
    at shaded.com.google.common.reflect.AbstractInvocationHandler.invoke(AbstractInvocationHandler.java:87)
    at com.sun.proxy.$Proxy105.listInDetail(Unknown Source)
    at org.jclouds.openstack.nova.v2_0.compute.NovaComputeServiceAdapter.listImages(NovaComputeServiceAdapter.java:169)
    at org.jclouds.compute.config.ComputeServiceAdapterContextModule$2.get(ComputeServiceAdapterContextModule.java:121)
    at org.jclouds.compute.config.ComputeServiceAdapterContextModule$2.get(ComputeServiceAdapterContextModule.java:118)
    at org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier$SetAndThrowAuthorizationExceptionSupplierBackedLoader.load(MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.java:73)
    at org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier$SetAndThrowAuthorizationExceptionSupplierBackedLoader.load(MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.java:57)
    at shaded.com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3524)
    at shaded.com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2317)
    at shaded.com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2280)
    at shaded.com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2195)
    at shaded.com.google.common.cache.LocalCache.get(LocalCache.java:3934)
    at shaded.com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3938)
    at shaded.com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4821)
    at org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.get(MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.java:119)
    at org.jclouds.compute.suppliers.ImageCacheSupplier.get(ImageCacheSupplier.java:64)
    at org.jclouds.compute.suppliers.ImageCacheSupplier.get(ImageCacheSupplier.java:45)
    at org.jclouds.openstack.nova.v2_0.compute.functions.ServerInZoneToNodeMetadata.findOperatingSystemForServerOrNull(ServerInZoneToNodeMetadata.java:182)
    at org.jclouds.openstack.nova.v2_0.compute.functions.ServerInZoneToNodeMetadata.apply(ServerInZoneToNodeMetadata.java:112)
    at org.jclouds.openstack.nova.v2_0.compute.functions.ServerInZoneToNodeMetadata.apply(ServerInZoneToNodeMetadata.java:70)
    at shaded.com.google.common.base.Functions$FunctionComposition.apply(Functions.java:216)
    at shaded.com.google.common.collect.Iterators$8.transform(Iterators.java:794)
    at shaded.com.google.common.collect.TransformedIterator.next(TransformedIterator.java:48)
    at shaded.com.google.common.collect.Iterators$7.computeNext(Iterators.java:646)
    at shaded.com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:143)
    at shaded.com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:138)
    at shaded.com.google.common.collect.Iterators.addAll(Iterators.java:356)
    at shaded.com.google.common.collect.Iterables.addAll(Iterables.java:354)
    at shaded.com.google.common.collect.Sets.newLinkedHashSet(Sets.java:328)
    at org.jclouds.compute.internal.BaseComputeService.listNodes(BaseComputeService.java:335)
    at sun.reflect.GeneratedMethodAccessor1317.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.google.inject.internal.DelegatingInvocationHandler.invoke(DelegatingInvocationHandler.java:40)
    at com.sun.proxy.$Proxy90.listNodes(Unknown Source)
    at jenkins.plugins.openstack.compute.JCloudsCloud.getRunningNodesCount(JCloudsCloud.java:322)
    at jenkins.plugins.openstack.compute.JCloudsCloud.doProvision(JCloudsCloud.java:305)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.kohsuke.stapler.Function$InstanceFunction.invoke(Function.java:298)
    at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:161)
    at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:96)
    at org.kohsuke.stapler.MetaClass$1.doDispatch(MetaClass.java:121)
    at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:53)
    at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:746)
    ... 65 more

I googled and got the following issue:
https://issues.apache.org/jira/browse/JCLOUDS-655
Do we have a plan to upgrade to jcloud 1.9.x?

Allow jobs to specify flavor type

It would be convenient if jobs can specify the flavor type in the job when spinning up VMs. In global configuration we can configure some Image types and then allow the specific jobs to override the flavor type in cases where they might need a larger slave.

Properly wait for machine to be up before launching

The problem manifests by "No route to host" messages in slave log after the failed launch attempt.

  • Do not wait for launch in #provison (dirty hack)
  • Wait until the host is reachable (+ service running on given port?). Probably responsibility for the launcher implementation to decide in separate method.

Cloud JNLP slave type not working.

Using fresh install of Jenkins 1.616 with following plugins:

Windows Slaves Plugin 1.0
Translation Assistance plugin 1.12
Token Macro Plugin 1.10
Subversion Plug-in 2.5
SSH Slaves plugin 1.9
SSH Credentials Plugin 1.11
Script Security Plugin 1.14
SCM API Plugin 0.2
PAM Authentication plugin 1.2
OWASP Markup Formatter Plugin 1.3
Openstack Cloud Plugin 1.7
Maven Integration plugin 2.9
Matrix Project Plugin 1.4.1
Matrix Authorization Strategy Plugin 1.2
MapDB API Plugin 1.0.6.0
Mailer Plugin 1.15
LDAP Plugin 1.11
JUnit Plugin 1.6
Javadoc Plugin 1.3
External Monitor Job Type Plugin 1.4
CVS Plug-in 2.12
Credentials Plugin 1.22
Config File Provider Plugin 2.8.1
Ant Plugin 1.2

Cloud templates set to use JNLP slave launcher do not reflect setting when added as nodes in Jenkins master. No errors pop up in java.util.logging.

SSH port is not configurable

It's obviously an edge case but, for our infra, all of our OpenStack images use a different SSH port from the default 22.

Would be nice if this was configurable per-slavetemplate.

Plugin doesn't respect glance API version

Current Glance API version is 2. So in service catalog we have endpoint to image-service in format "HOST/v2". When plugin trying to get list of available images, it send request "GET /v2/images/detail". However, in v2 API there is no target "/images/detail", and so list of images not loaded.

Please, fix plugin to force use v1 API. Or implement v2 support.

Jenkins 1.651
Plugin 2.6

Thanks.

Do not wait for computer to be launched forever

I have just seen several threads waiting seemingly forever:

"Computer.threadPoolForRemoting [#17]" #377 daemon prio=5
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for <0x5932175d> (a java.util.concurrent.FutureTask)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:425)
    at java.util.concurrent.FutureTask.get(FutureTask.java:187)
    at jenkins.plugins.openstack.compute.JCloudsCloud.ensureLaunched(JCloudsCloud.java:230)
    at jenkins.plugins.openstack.compute.JCloudsCloud.access$200(JCloudsCloud.java:51)
    at jenkins.plugins.openstack.compute.JCloudsCloud$1.call(JCloudsCloud.java:213)
    at jenkins.plugins.openstack.compute.JCloudsCloud$1.call(JCloudsCloud.java:196)
    at jenkins.util.ContextResettingExecutorService$2.call(ContextResettingExecutorService.java:46)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

The problem seems to be in ssh-launched configured to operate without timeout(c4e0e1e);

"Computer.threadPoolForRemoting [#29]" #550 daemon prio=5
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for <0x5ae0bf57> (a java.util.concurrent.FutureTask)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:425)
    at java.util.concurrent.FutureTask.get(FutureTask.java:187)
    at java.util.concurrent.AbstractExecutorService.invokeAll(AbstractExecutorService.java:243)
    at java.util.concurrent.Executors$DelegatedExecutorService.invokeAll(Executors.java:648)
    at hudson.plugins.sshslaves.SSHLauncher.launch(SSHLauncher.java:733)
    - locked <0x3c7d9d47> (a hudson.plugins.sshslaves.SSHLauncher)
    at jenkins.plugins.openstack.compute.JCloudsLauncher.launch(JCloudsLauncher.java:23)
    at hudson.slaves.SlaveComputer$1.call(SlaveComputer.java:233)
    at jenkins.util.ContextResettingExecutorService$2.call(ContextResettingExecutorService.java:46)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

Retention strategy can set node to pending delete state while launching

Sometimes. my slaves was put to pending delete state before fully launched. Inserting TRACE exception revealed it is retention strategy to blame.

Mar 24, 2016 1:51:40 AM jenkins.plugins.openstack.compute.JCloudsSlaveTemplate provision
INFO: Provisioned: NovaServer{..., name=SLAVE_NAME, ...}
Mar 24, 2016 1:51:43 AM jenkins.plugins.openstack.compute.JCloudsSlave createComputer
INFO: Creating a new JClouds Slave
Mar 24, 2016 1:51:45 AM jenkins.plugins.openstack.compute.JCloudsComputer setPendingDelete
INFO: Setting SLAVE_NAME pending delete status to true
java.lang.Exception: TRACE
  at jenkins.plugins.openstack.compute.JCloudsComputer.setPendingDelete(JCloudsComputer.java:60)
  at jenkins.plugins.openstack.compute.JCloudsRetentionStrategy.check(JCloudsRetentionStrategy.java:45)
  at jenkins.plugins.openstack.compute.JCloudsRetentionStrategy.check(JCloudsRetentionStrategy.java:15)
  at hudson.slaves.ComputerRetentionWork.doRun(ComputerRetentionWork.java:66)
  at hudson.triggers.SafeTimerTask.run(SafeTimerTask.java:54)
  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
  at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
  at java.lang.Thread.run(Thread.java:745)

[03/24/16 01:51:46] SSH Launch of SLAVE_NAME on 10.8.48.61 failed in 3,006 ms
...

Support alternative image selection methods

We rebuild a lot of our OpenStack images frequently (usually weekly) which causes their ImageIDs to change when they're rebuilt.

This means that someone needs to manually go and change the image ID in Jenkins every time an image has been rebuilt.

This would allow a configurable type of image selector. For example, we currently use a selection of image properties to choose which image to use (e.g. image should have "os=Ubuntu" and "major_version=14.04").

I've already prototyped this (mostly in this commit: https://github.com/jgriffiths1993/openstack-cloud-plugin/commit/67581864b3a7ae0dbdaf84b5b8c93352e53619c9) which adds a selector for choosing an image based on multiple properties.

System Test/Unit Test

Hello,

I was going through your test files and it seems that mostly all the UT's created are basically related to your functionality and not much about the interaction with the cloud. Have you considered and it may happen that your functionality is correct but the cloud response is incorrect , since cloud has a number of vulnerabilities.
Do you think a set number of Test Cases related to cloud interaction is important in this scenario

Do not try to provision if there required fields are not configured

If some of the required fields[1] is not provided (and it might not be trivial to see due to overriding logic), plugin tries to boot and OpenStack failure is provided to the user[2]. That is not really user friendly. Data needs to be checked before sending it to openstack in order to provide messages that are easier to grasp.

[1] TODO

  • imageId/bootSource
  • hardwareId
  • flavourId
  • launcherFactory

[2]

jenkins.plugins.openstack.compute.JCloudsCloud$ProvisioningFailedException: Openstack failed to provision the slave
    at jenkins.plugins.openstack.compute.JCloudsCloud$NodeCallable.call(JCloudsCloud.java:297)
    at jenkins.plugins.openstack.compute.JCloudsCloud$NodeCallable.call(JCloudsCloud.java:277)
    at jenkins.util.ContextResettingExecutorService$2.call(ContextResettingExecutorService.java:46)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: jenkins.plugins.openstack.compute.internal.Openstack$ActionFailed: Boot failed
    at jenkins.plugins.openstack.compute.internal.Openstack.bootAndWaitActive(Openstack.java:236)
    at jenkins.plugins.openstack.compute.JCloudsSlaveTemplate.provision(JCloudsSlaveTemplate.java:256)
    at jenkins.plugins.openstack.compute.JCloudsSlaveTemplate.provisionSlave(JCloudsSlaveTemplate.java:179)
    at jenkins.plugins.openstack.compute.JCloudsCloud$NodeCallable.call(JCloudsCloud.java:295)
    ... 6 more
Caused by: ClientResponseException{message=Missing imageRef attribute, status=400, status-code=BAD_REQUEST}
    at org.openstack4j.core.transport.HttpExceptionHandler.mapException(HttpExceptionHandler.java:38)
    at org.openstack4j.core.transport.HttpExceptionHandler.mapException(HttpExceptionHandler.java:23)
    at org.openstack4j.core.transport.HttpEntityHandler.handleLessThan500(HttpEntityHandler.java:100)
    at org.openstack4j.core.transport.HttpEntityHandler.handle(HttpEntityHandler.java:46)
    at org.openstack4j.connectors.httpclient.HttpResponseImpl.getEntity(HttpResponseImpl.java:69)
    at org.openstack4j.openstack.internal.BaseOpenStackService$Invocation.execute(BaseOpenStackService.java:189)
    at org.openstack4j.openstack.internal.BaseOpenStackService$Invocation.execute(BaseOpenStackService.java:183)
    at org.openstack4j.openstack.compute.internal.ServerServiceImpl.boot(ServerServiceImpl.java:127)
    at org.openstack4j.openstack.compute.internal.ServerServiceImpl.bootAndWaitActive(ServerServiceImpl.java:137)
    at jenkins.plugins.openstack.compute.internal.Openstack._bootAndWaitActive(Openstack.java:243)
    at jenkins.plugins.openstack.compute.internal.Openstack.bootAndWaitActive(Openstack.java:231)
    ... 9 more

Select control population is not scoped to the tenant.

When creating a new Slave Template, the select controls (e.g. Networks) are populated with every network to which the user has access - not just those for the particular tenant being used.

This means that a network or an image can be selected when they're not actually accessible from the specific tenant.

Not sure if the openstack4j interface supports filtering lists but, if so, it should be possible to pass the tenant ID to to the openstack API call.

Plugin might leak server when not provisioned/connected in time

#31 resolved the most obvious problem - machines gets provisioned in openstack in ERROR state. There are two similar cases:

  • machine is not provisioned within the timeout
  • slave gets created though never connected in time

In both cases, plugin should free the instance and remove the broken slave in the latter case.

Provisioning continues even if openstack4j fails

For some reason, the plugin is not able to ssh to the machines. While investigating log, I've found following in jenkins.log:

Jan 18, 2016 10:15:18 AM jenkins.plugins.openstack.compute.JCloudsSlaveTemplate get
INFO: Provisioned: NovaServer{id=*masked*, name=openstacknode-161, image={id=*masked*, links=[{href=*masked*, rel=bookmark}]}, flavor=NovaFlavor{id=3, ephemeral=0, swap=0, rxtx_factor=1.0, is_public=true, links=[GenericLink{href=*masked*, rel=bookmark}],
}, status=ERROR, diskconfig=MANUAL, userId=*masked*, created=Mon Jan 18 10:13:03 EST 2016, updated=Mon Jan 18 10:15:18 EST 2016, tenantId=*masked*, hostId=*masked*, addresses=NovaAddresses{addresses={*masked*=[NovaAddress{address=*masked*, type=fixed, version=4, macaddr=*masked*,
}]},
}, powerstate=0, fault=org.openstack4j.openstack.compute.domain.NovaFault@70feb8d5, vmState=error, metadata={jenkins-instance=*masked*}}

This is related to 2.0-beta release of the plugin. CC'ing @olivergondza. So, as you can see there was a NovaFault related error - which is not exposed in the log and I guess that if status==ERROR, plugin should quit provisioning all the same.

One off slaves not getting deleted.

Jobs set for one off openstack slaves sit in offline purgatory indefinitely.

Poking around source it looks like:
openstack-cloud-plugin/openstack-cloud/src/main/java/jenkins/plugins/openstack/compute/JCloudsOneOffSlave.java

does not set 'isPendingDelete' to true.

Submitted pull request as possible fix:
#19

Support for Heat

It would be nice if the plugin supported Heat to allocate vm environments for jobs. That declare additional openstack instances.

Format of username and tenant appears to have swapped around

In the master branch, the Openstack constructor expects the username to be:
<username> or <username>/<tenant>

This used to be:
<tenant>/<username>

If we're keeping it this way can we update the help text to show this, or change the format back.

Identify leaked machines and kill them

However hard we try not to leak any instance, it still seems to happen. Fortunately, all have Jenkins instance fingerprint in machine metadata so we can collect them and delete.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.