From 2b8a88ea9fbb5765bcc4f55485bf0ec06e5d902c Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Thu, 11 Jul 2019 14:20:01 +0530 Subject: [PATCH 01/23] Add docker file to build ignite compatible nodejs image --- tools/ignite/nodejs/Dockerfile | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tools/ignite/nodejs/Dockerfile diff --git a/tools/ignite/nodejs/Dockerfile b/tools/ignite/nodejs/Dockerfile new file mode 100644 index 00000000000..f3fba9d7b11 --- /dev/null +++ b/tools/ignite/nodejs/Dockerfile @@ -0,0 +1,28 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +FROM openwhisk/action-nodejs-v12:1.14.0-incubating AS ownode + +FROM weaveworks/ignite-ubuntu + +RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - +RUN apt-get -y install nodejs + +COPY --from=ownode /nodejsAction /nodejsAction +COPY --from=ownode /node_modules /node_modules +WORKDIR /nodejsAction +CMD node --expose-gc app.js \ No newline at end of file From 71f148091e51195a82d451202348b80ecd864b46 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 10:15:25 +0530 Subject: [PATCH 02/23] Switch to centos for default dockerfile --- tools/ignite/nodejs/Dockerfile | 11 +++++----- tools/ignite/nodejs/Dockerfile.ubuntu | 30 +++++++++++++++++++++++++++ tools/ignite/nodejs/action.service | 11 ++++++++++ 3 files changed, 47 insertions(+), 5 deletions(-) mode change 100644 => 100755 tools/ignite/nodejs/Dockerfile create mode 100755 tools/ignite/nodejs/Dockerfile.ubuntu create mode 100755 tools/ignite/nodejs/action.service diff --git a/tools/ignite/nodejs/Dockerfile b/tools/ignite/nodejs/Dockerfile old mode 100644 new mode 100755 index f3fba9d7b11..f69b3aa3bd6 --- a/tools/ignite/nodejs/Dockerfile +++ b/tools/ignite/nodejs/Dockerfile @@ -17,12 +17,13 @@ FROM openwhisk/action-nodejs-v12:1.14.0-incubating AS ownode -FROM weaveworks/ignite-ubuntu +FROM weaveworks/ignite-centos -RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - -RUN apt-get -y install nodejs +RUN curl -sL https://rpm.nodesource.com/setup_10.x | bash - +RUN sudo yum -y install nodejs COPY --from=ownode /nodejsAction /nodejsAction COPY --from=ownode /node_modules /node_modules -WORKDIR /nodejsAction -CMD node --expose-gc app.js \ No newline at end of file + +RUN chmod 664 /etc/systemd/system/action.service \ + && systemctl enable action.service diff --git a/tools/ignite/nodejs/Dockerfile.ubuntu b/tools/ignite/nodejs/Dockerfile.ubuntu new file mode 100755 index 00000000000..6510c3e862a --- /dev/null +++ b/tools/ignite/nodejs/Dockerfile.ubuntu @@ -0,0 +1,30 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +FROM openwhisk/action-nodejs-v12:1.14.0-incubating AS ownode + +FROM weaveworks/ignite-ubuntu + +RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - +RUN apt-get -y install nodejs + +COPY --from=ownode /nodejsAction /nodejsAction +COPY --from=ownode /node_modules /node_modules +COPY ./action.service /etc/systemd/system/ + +RUN chmod 664 /etc/systemd/system/action.service \ + && systemctl enable action.service diff --git a/tools/ignite/nodejs/action.service b/tools/ignite/nodejs/action.service new file mode 100755 index 00000000000..43858406512 --- /dev/null +++ b/tools/ignite/nodejs/action.service @@ -0,0 +1,11 @@ +[Unit] +Description=OpenWhisk Nodejs action server +Wants=network-online.target +After=network-online.target + +[Service] +WorkingDirectory=/nodejsAction +ExecStart=/usr/bin/node --expose-gc app.js + +[Install] +WantedBy=multi-user.target From e45392b4abf68f030fafa902229afe64284ff165 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 12:22:55 +0530 Subject: [PATCH 03/23] Implement base skeleton for IgniteContainerFactory --- .../apache/openwhisk/core/WhiskConfig.scala | 3 + .../containerpool/ignite/IgniteClient.scala | 58 +++++++++++++++ .../ignite/IgniteContainer.scala | 73 +++++++++++++++++++ .../ignite/IgniteContainerFactory.scala | 60 +++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala create mode 100644 core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala create mode 100644 core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala diff --git a/common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala b/common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala index 1b9baf45f23..29765ea94e5 100644 --- a/common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala +++ b/common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala @@ -264,4 +264,7 @@ object ConfigKeys { val whiskConfig = "whisk.config" val swaggerUi = "whisk.swagger-ui" + + val ignite = "whisk.ignite.client" + val igniteClient = s"$ignite.client" } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala new file mode 100644 index 00000000000..157456755ad --- /dev/null +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.openwhisk.core.containerpool.ignite + +import java.io.FileNotFoundException +import java.nio.file.{Files, Paths} + +import akka.actor.ActorSystem +import org.apache.openwhisk.common.{Logging, TransactionId} +import org.apache.openwhisk.core.ConfigKeys +import org.apache.openwhisk.core.containerpool.docker.{DockerClientConfig, ProcessRunner} +import pureconfig.loadConfigOrThrow + +import scala.concurrent.{ExecutionContext, Future} +import scala.concurrent.duration.Duration +import scala.util.Try + +case class IgniteTimeoutConfig(create: Duration) + +case class IgniteConfig(timeouts: IgniteTimeoutConfig) + +class IgniteClient(config: IgniteConfig = loadConfigOrThrow[IgniteConfig](ConfigKeys.igniteClient), + dockerConfig: DockerClientConfig = loadConfigOrThrow[DockerClientConfig](ConfigKeys.dockerClient))( + implicit ec: ExecutionContext, + system: ActorSystem, + log: Logging) + extends ProcessRunner { + + protected val igniteCmd: Seq[String] = { + val alternatives = List("/usr/bin/ignite", "/usr/local/bin/ignite") + + val dockerBin = Try { + alternatives.find(a => Files.isExecutable(Paths.get(a))).get + } getOrElse { + throw new FileNotFoundException(s"Couldn't locate ignite binary (tried: ${alternatives.mkString(", ")}).") + } + Seq(dockerBin) + } +} + +trait IgniteApi { + def rm(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] +} diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala new file mode 100644 index 00000000000..c8f09e16112 --- /dev/null +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.openwhisk.core.containerpool.ignite + +import java.time.Instant + +import akka.actor.ActorSystem +import akka.stream.scaladsl.Source +import akka.util.ByteString +import org.apache.openwhisk.common.{Logging, TransactionId} +import org.apache.openwhisk.core.containerpool.logging.LogLine +import org.apache.openwhisk.core.containerpool.{Container, ContainerAddress, ContainerId} +import org.apache.openwhisk.core.entity.ByteSize +import org.apache.openwhisk.core.entity.ExecManifest.ImageName +import org.apache.openwhisk.core.entity.size._ +import spray.json._ + +import scala.concurrent.{ExecutionContext, Future} + +case class IgniteId(asString: String) { + require(asString.nonEmpty, "IgniteId must not be empty") +} + +object IgniteContainer { + + def create(transid: TransactionId, + image: ImageName, + memory: ByteSize = 256.MB, + cpuShares: Int = 0, + name: Option[String] = None)(implicit + as: ActorSystem, + ec: ExecutionContext, + log: Logging, + ignite: IgniteApi): Future[IgniteContainer] = { + implicit val tid: TransactionId = transid + ??? + } + +} + +class IgniteContainer(protected val id: ContainerId, protected val addr: ContainerAddress, igniteId: IgniteId)( + implicit + override protected val as: ActorSystem, + protected val ec: ExecutionContext, + protected val logging: Logging, + ignite: IgniteApi) + extends Container { + + override def destroy()(implicit transid: TransactionId): Future[Unit] = { + super.destroy() + ignite.rm(igniteId) + } + + private val logMsg = "LogMessage are collected via Docker CLI" + override def logs(limit: ByteSize, waitForSentinel: Boolean)( + implicit transid: TransactionId): Source[ByteString, Any] = + Source.single(ByteString(LogLine(logMsg, "stdout", Instant.now.toString).toJson.compactPrint)) +} diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala new file mode 100644 index 00000000000..53b6bde50cd --- /dev/null +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.openwhisk.core.containerpool.ignite + +import akka.actor.ActorSystem +import org.apache.openwhisk.common.{Logging, TransactionId} +import org.apache.openwhisk.core.WhiskConfig +import org.apache.openwhisk.core.containerpool.{Container, ContainerFactory, ContainerFactoryProvider} +import org.apache.openwhisk.core.entity.{ByteSize, ExecManifest, InvokerInstanceId} + +import scala.concurrent.{ExecutionContext, Future} + +object IgniteContainerFactoryProvider extends ContainerFactoryProvider { + override def instance(actorSystem: ActorSystem, + logging: Logging, + config: WhiskConfig, + instanceId: InvokerInstanceId, + parameters: Map[String, Set[String]]): ContainerFactory = { + new IgniteContainerFactory(instanceId, parameters)( + actorSystem, + actorSystem.dispatcher, + logging, + new IgniteClient()(actorSystem.dispatcher, actorSystem, logging)) + } +} + +class IgniteContainerFactory(instance: InvokerInstanceId, parameters: Map[String, Set[String]])( + implicit actorSystem: ActorSystem, + ec: ExecutionContext, + logging: Logging, + ignite: IgniteApi) + extends ContainerFactory { + override def createContainer(tid: TransactionId, + name: String, + actionImage: ExecManifest.ImageName, + userProvidedImage: Boolean, + memory: ByteSize, + cpuShares: Int)(implicit config: WhiskConfig, logging: Logging): Future[Container] = { + IgniteContainer.create(tid, actionImage, memory, cpuShares, Some(name)) + } + + override def init(): Unit = ??? + + override def cleanup(): Unit = ??? +} From d79b0b83fa0f572608fc2282a0922b2b68107ce3 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 14:28:20 +0530 Subject: [PATCH 04/23] Ignore parameters which are Docker specific --- .../ignite/IgniteContainerFactory.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala index 53b6bde50cd..5131d8ee4ab 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala @@ -31,7 +31,8 @@ object IgniteContainerFactoryProvider extends ContainerFactoryProvider { config: WhiskConfig, instanceId: InvokerInstanceId, parameters: Map[String, Set[String]]): ContainerFactory = { - new IgniteContainerFactory(instanceId, parameters)( + //Ignore parameters as they are specific for Docker based creation. They do not map to Ignite + new IgniteContainerFactory(instanceId)( actorSystem, actorSystem.dispatcher, logging, @@ -39,11 +40,10 @@ object IgniteContainerFactoryProvider extends ContainerFactoryProvider { } } -class IgniteContainerFactory(instance: InvokerInstanceId, parameters: Map[String, Set[String]])( - implicit actorSystem: ActorSystem, - ec: ExecutionContext, - logging: Logging, - ignite: IgniteApi) +class IgniteContainerFactory(instance: InvokerInstanceId)(implicit actorSystem: ActorSystem, + ec: ExecutionContext, + logging: Logging, + ignite: IgniteApi) extends ContainerFactory { override def createContainer(tid: TransactionId, name: String, From f6c9ec6bb5d181826fff09497e79ca06a9eed2c2 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 14:29:58 +0530 Subject: [PATCH 05/23] Rename config as its client specific --- .../openwhisk/core/containerpool/ignite/IgniteClient.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala index 157456755ad..e5e3f2f7ff2 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala @@ -32,9 +32,9 @@ import scala.util.Try case class IgniteTimeoutConfig(create: Duration) -case class IgniteConfig(timeouts: IgniteTimeoutConfig) +case class IgniteClientConfig(timeouts: IgniteTimeoutConfig) -class IgniteClient(config: IgniteConfig = loadConfigOrThrow[IgniteConfig](ConfigKeys.igniteClient), +class IgniteClient(config: IgniteClientConfig = loadConfigOrThrow[IgniteClientConfig](ConfigKeys.igniteClient), dockerConfig: DockerClientConfig = loadConfigOrThrow[DockerClientConfig](ConfigKeys.dockerClient))( implicit ec: ExecutionContext, system: ActorSystem, From 6a087da65e9062be1da7a5a96f87e8ad3ae96eb6 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 15:10:38 +0530 Subject: [PATCH 06/23] Derive the ignite api --- .../src/main/resources/application.conf | 12 +++++ .../containerpool/ignite/IgniteClient.scala | 9 ++++ .../ignite/IgniteContainer.scala | 45 ++++++++++++++++++- .../ignite/IgniteContainerFactory.scala | 7 ++- 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/core/invoker/src/main/resources/application.conf b/core/invoker/src/main/resources/application.conf index 4f362094cf9..7281591f584 100644 --- a/core/invoker/src/main/resources/application.conf +++ b/core/invoker/src/main/resources/application.conf @@ -117,4 +117,16 @@ whisk { invoker { protocol: http } + + ignite { + # to pass additional args to 'docker run'; format is `{key1: [v1, v2], key2: [v1, v2]}` + extra-args { + + } + client { + timeouts { + create: 10 minutes + } + } + } } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala index e5e3f2f7ff2..c6f13fe4b2b 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala @@ -23,6 +23,7 @@ import java.nio.file.{Files, Paths} import akka.actor.ActorSystem import org.apache.openwhisk.common.{Logging, TransactionId} import org.apache.openwhisk.core.ConfigKeys +import org.apache.openwhisk.core.containerpool.{ContainerAddress, ContainerId} import org.apache.openwhisk.core.containerpool.docker.{DockerClientConfig, ProcessRunner} import pureconfig.loadConfigOrThrow @@ -54,5 +55,13 @@ class IgniteClient(config: IgniteClientConfig = loadConfigOrThrow[IgniteClientCo } trait IgniteApi { + def inspectIPAddress(containerId: ContainerId)(implicit transid: TransactionId): Future[ContainerAddress] + + def containerId(igniteId: IgniteId)(implicit transid: TransactionId): Future[ContainerId] + + def run(imageToUse: String, args: Seq[String])(implicit transid: TransactionId): Future[IgniteId] + + def importImage(publicImageName: String)(implicit transid: TransactionId): Future[Boolean] + def rm(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala index c8f09e16112..44f7f3af61b 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala @@ -24,10 +24,17 @@ import akka.stream.scaladsl.Source import akka.util.ByteString import org.apache.openwhisk.common.{Logging, TransactionId} import org.apache.openwhisk.core.containerpool.logging.LogLine -import org.apache.openwhisk.core.containerpool.{Container, ContainerAddress, ContainerId} +import org.apache.openwhisk.core.containerpool.{ + BlackboxStartupError, + Container, + ContainerAddress, + ContainerId, + WhiskContainerStartupError +} import org.apache.openwhisk.core.entity.ByteSize import org.apache.openwhisk.core.entity.ExecManifest.ImageName import org.apache.openwhisk.core.entity.size._ +import org.apache.openwhisk.http.Messages import spray.json._ import scala.concurrent.{ExecutionContext, Future} @@ -46,9 +53,43 @@ object IgniteContainer { as: ActorSystem, ec: ExecutionContext, log: Logging, + config: IgniteConfig, ignite: IgniteApi): Future[IgniteContainer] = { implicit val tid: TransactionId = transid - ??? + + val params = config.extraArgs.flatMap { + case (key, valueList) => valueList.toList.flatMap(Seq(key, _)) + } + //TODO Environment handling + + //TODO cpus - VM vCPU count, 1 or even numbers between 1 and 32 (default 1) + //It does not map to cpuShares currently. We may use it proportionally + + //size - VM filesystem size, for example 5GB or 2048MB (default 4.0 GB) + val args = Seq("--cpus", 1.toString, "--memory", s"${memory.toMB}m", "--size", "1GB") ++ name + .map(n => Seq("--name", n)) + .getOrElse(Seq.empty) ++ params + + val imageToUse = image.publicImageName + for { + importSuccessful <- ignite.importImage(imageToUse) + igniteId <- ignite.run(imageToUse, args).recoverWith { + case _ => + if (importSuccessful) { + Future.failed(WhiskContainerStartupError(Messages.resourceProvisionError)) + } else { + Future.failed(BlackboxStartupError(Messages.imagePullError(imageToUse))) + } + } + containerId <- ignite.containerId(igniteId) + ip <- ignite.inspectIPAddress(containerId).recoverWith { + // remove the container immediately if inspect failed as + // we cannot recover that case automatically + case _ => + ignite.rm(igniteId) + Future.failed(WhiskContainerStartupError(Messages.resourceProvisionError)) + } + } yield new IgniteContainer(containerId, ip, igniteId) } } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala index 5131d8ee4ab..6a10f5ec33e 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala @@ -19,9 +19,10 @@ package org.apache.openwhisk.core.containerpool.ignite import akka.actor.ActorSystem import org.apache.openwhisk.common.{Logging, TransactionId} -import org.apache.openwhisk.core.WhiskConfig +import org.apache.openwhisk.core.{ConfigKeys, WhiskConfig} import org.apache.openwhisk.core.containerpool.{Container, ContainerFactory, ContainerFactoryProvider} import org.apache.openwhisk.core.entity.{ByteSize, ExecManifest, InvokerInstanceId} +import pureconfig.loadConfigOrThrow import scala.concurrent.{ExecutionContext, Future} @@ -40,11 +41,15 @@ object IgniteContainerFactoryProvider extends ContainerFactoryProvider { } } +case class IgniteConfig(extraArgs: Map[String, Set[String]]) + class IgniteContainerFactory(instance: InvokerInstanceId)(implicit actorSystem: ActorSystem, ec: ExecutionContext, logging: Logging, ignite: IgniteApi) extends ContainerFactory { + private implicit val config: IgniteConfig = loadConfigOrThrow[IgniteConfig](ConfigKeys.ignite) + override def createContainer(tid: TransactionId, name: String, actionImage: ExecManifest.ImageName, From 3cb1933ab10d537fe5f850ca3d0b6e270ac01404 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 15:16:38 +0530 Subject: [PATCH 07/23] Add base logic to run commands --- .../org/apache/openwhisk/common/Logging.scala | 5 +++ .../src/main/resources/application.conf | 1 + .../containerpool/ignite/IgniteClient.scala | 42 ++++++++++++++++--- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/common/scala/src/main/scala/org/apache/openwhisk/common/Logging.scala b/common/scala/src/main/scala/org/apache/openwhisk/common/Logging.scala index 01c97542451..5a55b6eec6e 100644 --- a/common/scala/src/main/scala/org/apache/openwhisk/common/Logging.scala +++ b/common/scala/src/main/scala/org/apache/openwhisk/common/Logging.scala @@ -446,6 +446,11 @@ object LoggingMarkers { val CONTAINER_CLIENT_RETRIES = LogMarkerToken(containerClient, "retries", counter)(MeasurementUnit.none) + def INVOKER_IGNITE_CMD(cmd: String) = + LogMarkerToken(invoker, "ignite", start, Some(cmd), Map("cmd" -> cmd))(MeasurementUnit.time.milliseconds) + def INVOKER_IGNITE_CMD_TIMEOUT(cmd: String) = + LogMarkerToken(invoker, "ignite", timeout, Some(cmd), Map("cmd" -> cmd))(MeasurementUnit.none) + val INVOKER_TOTALMEM_BLACKBOX = LogMarkerToken(loadbalancer, "totalCapacityBlackBox", counter)(MeasurementUnit.none) val INVOKER_TOTALMEM_MANAGED = LogMarkerToken(loadbalancer, "totalCapacityManaged", counter)(MeasurementUnit.none) diff --git a/core/invoker/src/main/resources/application.conf b/core/invoker/src/main/resources/application.conf index 7281591f584..5d000b234e9 100644 --- a/core/invoker/src/main/resources/application.conf +++ b/core/invoker/src/main/resources/application.conf @@ -126,6 +126,7 @@ whisk { client { timeouts { create: 10 minutes + version: 10 seconds } } } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala index c6f13fe4b2b..bce0091c9a1 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala @@ -21,17 +21,18 @@ import java.io.FileNotFoundException import java.nio.file.{Files, Paths} import akka.actor.ActorSystem -import org.apache.openwhisk.common.{Logging, TransactionId} +import akka.event.Logging.{ErrorLevel, InfoLevel} +import org.apache.openwhisk.common.{Logging, LoggingMarkers, MetricEmitter, TransactionId} import org.apache.openwhisk.core.ConfigKeys import org.apache.openwhisk.core.containerpool.{ContainerAddress, ContainerId} -import org.apache.openwhisk.core.containerpool.docker.{DockerClientConfig, ProcessRunner} +import org.apache.openwhisk.core.containerpool.docker.{DockerClientConfig, ProcessRunner, ProcessTimeoutException} import pureconfig.loadConfigOrThrow -import scala.concurrent.{ExecutionContext, Future} +import scala.concurrent.{Await, ExecutionContext, Future} import scala.concurrent.duration.Duration -import scala.util.Try +import scala.util.{Failure, Success, Try} -case class IgniteTimeoutConfig(create: Duration) +case class IgniteTimeoutConfig(create: Duration, version: Duration) case class IgniteClientConfig(timeouts: IgniteTimeoutConfig) @@ -52,6 +53,37 @@ class IgniteClient(config: IgniteClientConfig = loadConfigOrThrow[IgniteClientCo } Seq(dockerBin) } + + // Invoke ignite CLI to determine client version. + // If the ignite client version cannot be determined, an exception will be thrown and instance initialization will fail. + // Rationale: if we cannot invoke `ignite version` successfully, it is unlikely subsequent `ignite` invocations will succeed. + protected def getClientVersion(): String = { + //TODO Ignite currently does not support formatting. So just get and log the verbatim version details + val vf = executeProcess(igniteCmd ++ Seq("version"), config.timeouts.version) + .andThen { + case Success(version) => log.info(this, s"Detected ignite client version $version") + case Failure(e) => + log.error(this, s"Failed to determine ignite client version: ${e.getClass} - ${e.getMessage}") + } + Await.result(vf, 2 * config.timeouts.version) + } + val clientVersion: String = getClientVersion() + + protected def runCmd(args: Seq[String], timeout: Duration)(implicit transid: TransactionId): Future[String] = { + val cmd = igniteCmd ++ args + val start = transid.started( + this, + LoggingMarkers.INVOKER_IGNITE_CMD(args.head), + s"running ${cmd.mkString(" ")} (timeout: $timeout)", + logLevel = InfoLevel) + executeProcess(cmd, timeout).andThen { + case Success(_) => transid.finished(this, start) + case Failure(pte: ProcessTimeoutException) => + transid.failed(this, start, pte.getMessage, ErrorLevel) + MetricEmitter.emitCounterMetric(LoggingMarkers.INVOKER_IGNITE_CMD_TIMEOUT(args.head)) + case Failure(t) => transid.failed(this, start, t.getMessage, ErrorLevel) + } + } } trait IgniteApi { From f4a7f297eda868c12a6065e5aa928c95a9bb98c3 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 15:19:52 +0530 Subject: [PATCH 08/23] Pass DockerApi to Ignite client and implement skeleton methods --- .../containerpool/ignite/IgniteClient.scala | 24 ++++++++++++++++--- .../ignite/IgniteContainerFactory.scala | 4 +++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala index bce0091c9a1..a162dc973c4 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala @@ -25,7 +25,12 @@ import akka.event.Logging.{ErrorLevel, InfoLevel} import org.apache.openwhisk.common.{Logging, LoggingMarkers, MetricEmitter, TransactionId} import org.apache.openwhisk.core.ConfigKeys import org.apache.openwhisk.core.containerpool.{ContainerAddress, ContainerId} -import org.apache.openwhisk.core.containerpool.docker.{DockerClientConfig, ProcessRunner, ProcessTimeoutException} +import org.apache.openwhisk.core.containerpool.docker.{ + DockerApi, + DockerClientConfig, + ProcessRunner, + ProcessTimeoutException +} import pureconfig.loadConfigOrThrow import scala.concurrent.{Await, ExecutionContext, Future} @@ -36,12 +41,14 @@ case class IgniteTimeoutConfig(create: Duration, version: Duration) case class IgniteClientConfig(timeouts: IgniteTimeoutConfig) -class IgniteClient(config: IgniteClientConfig = loadConfigOrThrow[IgniteClientConfig](ConfigKeys.igniteClient), +class IgniteClient(dockerApi: DockerApi, + config: IgniteClientConfig = loadConfigOrThrow[IgniteClientConfig](ConfigKeys.igniteClient), dockerConfig: DockerClientConfig = loadConfigOrThrow[DockerClientConfig](ConfigKeys.dockerClient))( implicit ec: ExecutionContext, system: ActorSystem, log: Logging) - extends ProcessRunner { + extends IgniteApi + with ProcessRunner { protected val igniteCmd: Seq[String] = { val alternatives = List("/usr/bin/ignite", "/usr/local/bin/ignite") @@ -84,6 +91,17 @@ class IgniteClient(config: IgniteClientConfig = loadConfigOrThrow[IgniteClientCo case Failure(t) => transid.failed(this, start, t.getMessage, ErrorLevel) } } + + override def inspectIPAddress(containerId: ContainerId)(implicit transid: TransactionId): Future[ContainerAddress] = + ??? + + override def containerId(igniteId: IgniteId)(implicit transid: TransactionId): Future[ContainerId] = ??? + + override def run(imageToUse: String, args: Seq[String])(implicit transid: TransactionId): Future[IgniteId] = ??? + + override def importImage(publicImageName: String)(implicit transid: TransactionId): Future[Boolean] = ??? + + override def rm(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] = ??? } trait IgniteApi { diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala index 6a10f5ec33e..6dbd4c48d6c 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala @@ -19,6 +19,7 @@ package org.apache.openwhisk.core.containerpool.ignite import akka.actor.ActorSystem import org.apache.openwhisk.common.{Logging, TransactionId} +import org.apache.openwhisk.core.containerpool.docker.DockerClientWithFileAccess import org.apache.openwhisk.core.{ConfigKeys, WhiskConfig} import org.apache.openwhisk.core.containerpool.{Container, ContainerFactory, ContainerFactoryProvider} import org.apache.openwhisk.core.entity.{ByteSize, ExecManifest, InvokerInstanceId} @@ -33,11 +34,12 @@ object IgniteContainerFactoryProvider extends ContainerFactoryProvider { instanceId: InvokerInstanceId, parameters: Map[String, Set[String]]): ContainerFactory = { //Ignore parameters as they are specific for Docker based creation. They do not map to Ignite + val dockerApi = new DockerClientWithFileAccess()(actorSystem.dispatcher)(logging, actorSystem) new IgniteContainerFactory(instanceId)( actorSystem, actorSystem.dispatcher, logging, - new IgniteClient()(actorSystem.dispatcher, actorSystem, logging)) + new IgniteClient(dockerApi)(actorSystem.dispatcher, actorSystem, logging)) } } From 5c96ed99830e569a22c6120ef6e598728da992b4 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 15:21:32 +0530 Subject: [PATCH 09/23] Implement ip address api via Docker api --- .../openwhisk/core/containerpool/ignite/IgniteClient.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala index a162dc973c4..362eb4e818a 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala @@ -93,7 +93,7 @@ class IgniteClient(dockerApi: DockerApi, } override def inspectIPAddress(containerId: ContainerId)(implicit transid: TransactionId): Future[ContainerAddress] = - ??? + dockerApi.inspectIPAddress(containerId, "bridge") override def containerId(igniteId: IgniteId)(implicit transid: TransactionId): Future[ContainerId] = ??? From 83ab5c9c0da12f76283ee396e32c6b67eeceb03d Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 15:33:56 +0530 Subject: [PATCH 10/23] Implement logic to determine containerId --- core/invoker/src/main/resources/application.conf | 1 + .../openwhisk/core/containerpool/docker/DockerClient.scala | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/invoker/src/main/resources/application.conf b/core/invoker/src/main/resources/application.conf index 5d000b234e9..b3603ef1256 100644 --- a/core/invoker/src/main/resources/application.conf +++ b/core/invoker/src/main/resources/application.conf @@ -127,6 +127,7 @@ whisk { timeouts { create: 10 minutes version: 10 seconds + inspect: 1 minute } } } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerClient.scala index fbf9d6e85ff..cfebcbdb7a8 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerClient.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerClient.scala @@ -195,7 +195,8 @@ class DockerClient(dockerHost: Option[String] = None, def isOomKilled(id: ContainerId)(implicit transid: TransactionId): Future[Boolean] = runCmd(Seq("inspect", id.asString, "--format", "{{.State.OOMKilled}}"), config.timeouts.inspect).map(_.toBoolean) - protected def runCmd(args: Seq[String], timeout: Duration)(implicit transid: TransactionId): Future[String] = { + protected[containerpool] def runCmd(args: Seq[String], timeout: Duration)( + implicit transid: TransactionId): Future[String] = { val cmd = dockerCmd ++ args val start = transid.started( this, From ba2c4d0f88b9b4670668f51071bf00f2bb000466 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 15:48:10 +0530 Subject: [PATCH 11/23] Implement support getting dockerId and remove --- .../src/main/resources/application.conf | 1 + .../containerpool/ignite/IgniteClient.scala | 51 ++++++++++++++++--- .../ignite/IgniteContainer.scala | 5 +- .../ignite/IgniteContainerFactory.scala | 4 +- 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/core/invoker/src/main/resources/application.conf b/core/invoker/src/main/resources/application.conf index b3603ef1256..00b50374061 100644 --- a/core/invoker/src/main/resources/application.conf +++ b/core/invoker/src/main/resources/application.conf @@ -128,6 +128,7 @@ whisk { create: 10 minutes version: 10 seconds inspect: 1 minute + rm: 1 minute } } } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala index 362eb4e818a..32691abfce2 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala @@ -27,21 +27,23 @@ import org.apache.openwhisk.core.ConfigKeys import org.apache.openwhisk.core.containerpool.{ContainerAddress, ContainerId} import org.apache.openwhisk.core.containerpool.docker.{ DockerApi, + DockerClient, DockerClientConfig, ProcessRunner, ProcessTimeoutException } import pureconfig.loadConfigOrThrow +import scala.collection.concurrent.TrieMap import scala.concurrent.{Await, ExecutionContext, Future} import scala.concurrent.duration.Duration import scala.util.{Failure, Success, Try} -case class IgniteTimeoutConfig(create: Duration, version: Duration) +case class IgniteTimeoutConfig(create: Duration, version: Duration, inspect: Duration, rm: Duration) case class IgniteClientConfig(timeouts: IgniteTimeoutConfig) -class IgniteClient(dockerApi: DockerApi, +class IgniteClient(dockerClient: DockerClient, config: IgniteClientConfig = loadConfigOrThrow[IgniteClientConfig](ConfigKeys.igniteClient), dockerConfig: DockerClientConfig = loadConfigOrThrow[DockerClientConfig](ConfigKeys.dockerClient))( implicit ec: ExecutionContext, @@ -93,15 +95,48 @@ class IgniteClient(dockerApi: DockerApi, } override def inspectIPAddress(containerId: ContainerId)(implicit transid: TransactionId): Future[ContainerAddress] = - dockerApi.inspectIPAddress(containerId, "bridge") - - override def containerId(igniteId: IgniteId)(implicit transid: TransactionId): Future[ContainerId] = ??? + dockerClient.inspectIPAddress(containerId, "bridge") + + override def containerId(igniteId: IgniteId)(implicit transid: TransactionId): Future[ContainerId] = { + //Each ignite vm would be backed by a Docker container whose name would be `ignite-` + //Use that to find the backing containerId + dockerClient + .runCmd(Seq("inspect", "--format", s"{{.Id}}", s"ignite-${igniteId.asString}"), config.timeouts.inspect) + .flatMap { + case "" => Future.failed(new NoSuchElementException) + case stdout => Future.successful(ContainerId(stdout)) + } + } override def run(imageToUse: String, args: Seq[String])(implicit transid: TransactionId): Future[IgniteId] = ??? - override def importImage(publicImageName: String)(implicit transid: TransactionId): Future[Boolean] = ??? + private val importedImages = new TrieMap[String, Boolean]() + private val importsInFlight = TrieMap[String, Future[Boolean]]() + override def importImage(image: String)(implicit transid: TransactionId): Future[Boolean] = { + //TODO Add support for latest + if (importedImages.contains(image)) Future.successful(true) + else { + importsInFlight.getOrElseUpdate( + image, { + runCmd(Seq("image", "import", image), config.timeouts.create) + .map { stdout => + log.info(this, s"Imported image $image - $stdout") + true + } + .andThen { + case _ => + importsInFlight.remove(image) + importedImages.put(image, true) + } + }) + } + } + + override def rm(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] = + runCmd(Seq("vm", "stop", igniteId.asString), config.timeouts.rm).map(_ => ()) - override def rm(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] = ??? + override def stop(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] = + runCmd(Seq("vm", "rm", igniteId.asString), config.timeouts.rm).map(_ => ()) } trait IgniteApi { @@ -114,4 +149,6 @@ trait IgniteApi { def importImage(publicImageName: String)(implicit transid: TransactionId): Future[Boolean] def rm(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] + + def stop(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala index 44f7f3af61b..c36a854415d 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala @@ -104,7 +104,10 @@ class IgniteContainer(protected val id: ContainerId, protected val addr: Contain override def destroy()(implicit transid: TransactionId): Future[Unit] = { super.destroy() - ignite.rm(igniteId) + for { + _ <- ignite.stop(igniteId) + _ <- ignite.rm(igniteId) + } yield Unit } private val logMsg = "LogMessage are collected via Docker CLI" diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala index 6dbd4c48d6c..1d31eb2138d 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala @@ -34,12 +34,12 @@ object IgniteContainerFactoryProvider extends ContainerFactoryProvider { instanceId: InvokerInstanceId, parameters: Map[String, Set[String]]): ContainerFactory = { //Ignore parameters as they are specific for Docker based creation. They do not map to Ignite - val dockerApi = new DockerClientWithFileAccess()(actorSystem.dispatcher)(logging, actorSystem) + val dockerClient = new DockerClientWithFileAccess()(actorSystem.dispatcher)(logging, actorSystem) new IgniteContainerFactory(instanceId)( actorSystem, actorSystem.dispatcher, logging, - new IgniteClient(dockerApi)(actorSystem.dispatcher, actorSystem, logging)) + new IgniteClient(dockerClient)(actorSystem.dispatcher, actorSystem, logging)) } } From 37ab3e6ea7be9b1410c17f692faf83657a2707f5 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 15:51:46 +0530 Subject: [PATCH 12/23] Implement run support --- core/invoker/src/main/resources/application.conf | 1 + .../core/containerpool/ignite/IgniteClient.scala | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/core/invoker/src/main/resources/application.conf b/core/invoker/src/main/resources/application.conf index 00b50374061..0d9a5583b57 100644 --- a/core/invoker/src/main/resources/application.conf +++ b/core/invoker/src/main/resources/application.conf @@ -129,6 +129,7 @@ whisk { version: 10 seconds inspect: 1 minute rm: 1 minute + run: 5 minutes } } } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala index 32691abfce2..4f2caeee179 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala @@ -39,7 +39,7 @@ import scala.concurrent.{Await, ExecutionContext, Future} import scala.concurrent.duration.Duration import scala.util.{Failure, Success, Try} -case class IgniteTimeoutConfig(create: Duration, version: Duration, inspect: Duration, rm: Duration) +case class IgniteTimeoutConfig(create: Duration, version: Duration, inspect: Duration, rm: Duration, run: Duration) case class IgniteClientConfig(timeouts: IgniteTimeoutConfig) @@ -108,7 +108,9 @@ class IgniteClient(dockerClient: DockerClient, } } - override def run(imageToUse: String, args: Seq[String])(implicit transid: TransactionId): Future[IgniteId] = ??? + override def run(image: String, args: Seq[String])(implicit transid: TransactionId): Future[IgniteId] = { + runCmd(Seq("run", image) ++ args, config.timeouts.run).map(IgniteId.apply) + } private val importedImages = new TrieMap[String, Boolean]() private val importsInFlight = TrieMap[String, Future[Boolean]]() @@ -144,9 +146,9 @@ trait IgniteApi { def containerId(igniteId: IgniteId)(implicit transid: TransactionId): Future[ContainerId] - def run(imageToUse: String, args: Seq[String])(implicit transid: TransactionId): Future[IgniteId] + def run(image: String, args: Seq[String])(implicit transid: TransactionId): Future[IgniteId] - def importImage(publicImageName: String)(implicit transid: TransactionId): Future[Boolean] + def importImage(image: String)(implicit transid: TransactionId): Future[Boolean] def rm(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] From 218301ebd56300829fab0b46cd6f24b31404bd44 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 16:33:00 +0530 Subject: [PATCH 13/23] Implement support for cleaning all launched vms --- .../src/main/resources/application.conf | 1 + .../containerpool/ignite/IgniteClient.scala | 36 +++++++++++++++++-- .../ignite/IgniteContainer.scala | 5 +-- .../ignite/IgniteContainerFactory.scala | 28 +++++++++++++-- 4 files changed, 61 insertions(+), 9 deletions(-) diff --git a/core/invoker/src/main/resources/application.conf b/core/invoker/src/main/resources/application.conf index 0d9a5583b57..028fdf0ec76 100644 --- a/core/invoker/src/main/resources/application.conf +++ b/core/invoker/src/main/resources/application.conf @@ -130,6 +130,7 @@ whisk { inspect: 1 minute rm: 1 minute run: 5 minutes + ps: 1 minute } } } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala index 4f2caeee179..667037eea4b 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala @@ -39,14 +39,19 @@ import scala.concurrent.{Await, ExecutionContext, Future} import scala.concurrent.duration.Duration import scala.util.{Failure, Success, Try} -case class IgniteTimeoutConfig(create: Duration, version: Duration, inspect: Duration, rm: Duration, run: Duration) +case class IgniteTimeoutConfig(create: Duration, + version: Duration, + inspect: Duration, + rm: Duration, + run: Duration, + ps: Duration) case class IgniteClientConfig(timeouts: IgniteTimeoutConfig) class IgniteClient(dockerClient: DockerClient, config: IgniteClientConfig = loadConfigOrThrow[IgniteClientConfig](ConfigKeys.igniteClient), dockerConfig: DockerClientConfig = loadConfigOrThrow[DockerClientConfig](ConfigKeys.dockerClient))( - implicit ec: ExecutionContext, + override implicit val ec: ExecutionContext, system: ActorSystem, log: Logging) extends IgniteApi @@ -139,9 +144,27 @@ class IgniteClient(dockerClient: DockerClient, override def stop(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] = runCmd(Seq("vm", "rm", igniteId.asString), config.timeouts.rm).map(_ => ()) + + override def listRunningVMs()(implicit transid: TransactionId): Future[Seq[VMInfo]] = { + //Each ignite vm has a backing container whose label is set to vm name and name to vm id + val filter = "--format='{{.ID }}|{{ .Label \"ignite.name\" }}|{{.Names}}'" + val cmd = Seq("ps", "--no-trunc", filter) + runCmd(cmd, config.timeouts.ps).map(_.linesIterator.toSeq.map(VMInfo.apply)) + } +} + +case class VMInfo(containerId: ContainerId, igniteId: IgniteId, name: String) + +object VMInfo { + def apply(value: String): VMInfo = { + val Array(conatinerId, name, vmId) = value.split("|") + val igniteId = vmId.split("-").last + new VMInfo(ContainerId(conatinerId), IgniteId(igniteId), name) + } } trait IgniteApi { + protected implicit val ec: ExecutionContext def inspectIPAddress(containerId: ContainerId)(implicit transid: TransactionId): Future[ContainerAddress] def containerId(igniteId: IgniteId)(implicit transid: TransactionId): Future[ContainerId] @@ -153,4 +176,13 @@ trait IgniteApi { def rm(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] def stop(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] + + def listRunningVMs()(implicit transid: TransactionId): Future[Seq[VMInfo]] + + def stopAndRemove(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] = { + for { + _ <- stop(igniteId) + _ <- rm(igniteId) + } yield Unit + } } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala index c36a854415d..4be23e54e22 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala @@ -104,10 +104,7 @@ class IgniteContainer(protected val id: ContainerId, protected val addr: Contain override def destroy()(implicit transid: TransactionId): Future[Unit] = { super.destroy() - for { - _ <- ignite.stop(igniteId) - _ <- ignite.rm(igniteId) - } yield Unit + ignite.stopAndRemove(igniteId) } private val logMsg = "LogMessage are collected via Docker CLI" diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala index 1d31eb2138d..caf7d08f721 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala @@ -25,7 +25,8 @@ import org.apache.openwhisk.core.containerpool.{Container, ContainerFactory, Con import org.apache.openwhisk.core.entity.{ByteSize, ExecManifest, InvokerInstanceId} import pureconfig.loadConfigOrThrow -import scala.concurrent.{ExecutionContext, Future} +import scala.concurrent.{Await, ExecutionContext, Future} +import scala.concurrent.duration._ object IgniteContainerFactoryProvider extends ContainerFactoryProvider { override def instance(actorSystem: ActorSystem, @@ -61,7 +62,28 @@ class IgniteContainerFactory(instance: InvokerInstanceId)(implicit actorSystem: IgniteContainer.create(tid, actionImage, memory, cpuShares, Some(name)) } - override def init(): Unit = ??? + override def init(): Unit = removeAllActionContainers() - override def cleanup(): Unit = ??? + override def cleanup(): Unit = { + try { + removeAllActionContainers() + } catch { + case e: Exception => logging.error(this, s"Failed to remove action containers: ${e.getMessage}") + } + } + + private def removeAllActionContainers(): Unit = { + implicit val transid = TransactionId.invoker + val cleaning = + ignite.listRunningVMs().flatMap { vms => + val prefix = s"${ContainerFactory.containerNamePrefix(instance)}_" + val ourVms = vms.filter(_.name.startsWith(prefix)) + logging.info(this, s"removing ${ourVms.size} action containers.") + val removals = ourVms.map { vm => + ignite.stopAndRemove(vm.igniteId) + } + Future.sequence(removals) + } + Await.ready(cleaning, 1.minutes) + } } From 61b66050f1f4d3c3ee895dc51df589147baf6532 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 16:45:28 +0530 Subject: [PATCH 14/23] Add toString impl to log vm details --- .../openwhisk/core/containerpool/ignite/IgniteContainer.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala index 4be23e54e22..15d95f77c7d 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainer.scala @@ -111,4 +111,6 @@ class IgniteContainer(protected val id: ContainerId, protected val addr: Contain override def logs(limit: ByteSize, waitForSentinel: Boolean)( implicit transid: TransactionId): Source[ByteString, Any] = Source.single(ByteString(LogLine(logMsg, "stdout", Instant.now.toString).toJson.compactPrint)) + + override def toString() = s"igniteId: ${igniteId.asString}, docker: ${id.asString}, address: $addr" } From 41253e3a1b9c0e60b0cdc0a5f1ad0f714739bfee Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 16:45:40 +0530 Subject: [PATCH 15/23] Add a ignored test --- .../ignite/IgniteContainerFactoryTests.scala | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/src/test/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactoryTests.scala diff --git a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactoryTests.scala b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactoryTests.scala new file mode 100644 index 00000000000..a958bb4ef7d --- /dev/null +++ b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactoryTests.scala @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.openwhisk.core.containerpool.ignite + +import common.{StreamLogging, WskActorSystem} +import org.apache.openwhisk.common.TransactionId +import org.apache.openwhisk.core.WhiskConfig +import org.apache.openwhisk.core.entity.ExecManifest.ImageName +import org.apache.openwhisk.core.entity.InvokerInstanceId +import org.apache.openwhisk.core.entity.size._ +import org.junit.runner.RunWith +import org.scalatest.concurrent.ScalaFutures +import org.scalatest.junit.JUnitRunner +import org.scalatest.{FlatSpec, Matchers} + +import scala.concurrent.duration._ +@RunWith(classOf[JUnitRunner]) +class IgniteContainerFactoryTests + extends FlatSpec + with Matchers + with WskActorSystem + with StreamLogging + with ScalaFutures { + + implicit override val patienceConfig: PatienceConfig = PatienceConfig(timeout = 5.minutes) + + ignore should "launch the ignite vm" in { + implicit val wskConfig: WhiskConfig = new WhiskConfig(Map.empty) + implicit val tid: TransactionId = TransactionId.testing + val instanceId = InvokerInstanceId(1, userMemory = 100.MB) + val factory = IgniteContainerFactoryProvider.instance(actorSystem, logging, wskConfig, instanceId, Map.empty) + val image = ImageName("whisk/ignite-nodejs-v12:latest") + val container = factory.createContainer(tid, "footest", image, true, 256.MB, 1).futureValue + + println(container) + + container.destroy().futureValue + } +} From 93c01501332420e8983a2a48b48749b0612e352f Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 17:01:18 +0530 Subject: [PATCH 16/23] Fix docker file and add a build script --- tools/ignite/nodejs/Dockerfile | 1 + tools/ignite/nodejs/build.sh | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100755 tools/ignite/nodejs/build.sh diff --git a/tools/ignite/nodejs/Dockerfile b/tools/ignite/nodejs/Dockerfile index f69b3aa3bd6..74e91cc3617 100755 --- a/tools/ignite/nodejs/Dockerfile +++ b/tools/ignite/nodejs/Dockerfile @@ -24,6 +24,7 @@ RUN sudo yum -y install nodejs COPY --from=ownode /nodejsAction /nodejsAction COPY --from=ownode /node_modules /node_modules +COPY ./action.service /etc/systemd/system/ RUN chmod 664 /etc/systemd/system/action.service \ && systemctl enable action.service diff --git a/tools/ignite/nodejs/build.sh b/tools/ignite/nodejs/build.sh new file mode 100755 index 00000000000..6072294b86a --- /dev/null +++ b/tools/ignite/nodejs/build.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +docker build -t whisk/ignite-nodejs-v12:latest . From e379ab3faacf7c01d93df8d9e4b959fa3036f366 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 17:14:45 +0530 Subject: [PATCH 17/23] Fix build issues --- .../core/containerpool/ignite/IgniteClient.scala | 14 +++++++------- .../ignite/IgniteContainerFactory.scala | 5 +++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala index 667037eea4b..f9a03a0582f 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala @@ -24,19 +24,18 @@ import akka.actor.ActorSystem import akka.event.Logging.{ErrorLevel, InfoLevel} import org.apache.openwhisk.common.{Logging, LoggingMarkers, MetricEmitter, TransactionId} import org.apache.openwhisk.core.ConfigKeys -import org.apache.openwhisk.core.containerpool.{ContainerAddress, ContainerId} import org.apache.openwhisk.core.containerpool.docker.{ - DockerApi, DockerClient, DockerClientConfig, ProcessRunner, ProcessTimeoutException } +import org.apache.openwhisk.core.containerpool.{ContainerAddress, ContainerId} import pureconfig.loadConfigOrThrow import scala.collection.concurrent.TrieMap -import scala.concurrent.{Await, ExecutionContext, Future} import scala.concurrent.duration.Duration +import scala.concurrent.{Await, ExecutionContext, Future} import scala.util.{Failure, Success, Try} case class IgniteTimeoutConfig(create: Duration, @@ -51,9 +50,9 @@ case class IgniteClientConfig(timeouts: IgniteTimeoutConfig) class IgniteClient(dockerClient: DockerClient, config: IgniteClientConfig = loadConfigOrThrow[IgniteClientConfig](ConfigKeys.igniteClient), dockerConfig: DockerClientConfig = loadConfigOrThrow[DockerClientConfig](ConfigKeys.dockerClient))( - override implicit val ec: ExecutionContext, - system: ActorSystem, - log: Logging) + override implicit val executionContext: ExecutionContext, + implicit val system: ActorSystem, + implicit val log: Logging) extends IgniteApi with ProcessRunner { @@ -164,7 +163,8 @@ object VMInfo { } trait IgniteApi { - protected implicit val ec: ExecutionContext + protected implicit val executionContext: ExecutionContext + def inspectIPAddress(containerId: ContainerId)(implicit transid: TransactionId): Future[ContainerAddress] def containerId(igniteId: IgniteId)(implicit transid: TransactionId): Future[ContainerId] diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala index caf7d08f721..853408de922 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactory.scala @@ -49,9 +49,10 @@ case class IgniteConfig(extraArgs: Map[String, Set[String]]) class IgniteContainerFactory(instance: InvokerInstanceId)(implicit actorSystem: ActorSystem, ec: ExecutionContext, logging: Logging, - ignite: IgniteApi) + ignite: IgniteApi, + igniteConfig: IgniteConfig = + loadConfigOrThrow[IgniteConfig](ConfigKeys.ignite)) extends ContainerFactory { - private implicit val config: IgniteConfig = loadConfigOrThrow[IgniteConfig](ConfigKeys.ignite) override def createContainer(tid: TransactionId, name: String, From c8d78ad2ecd78bf315145a297a356194d7925f9c Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 17:20:28 +0530 Subject: [PATCH 18/23] Fix config path --- .../src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala b/common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala index 29765ea94e5..8194974e6a3 100644 --- a/common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala +++ b/common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala @@ -265,6 +265,6 @@ object ConfigKeys { val whiskConfig = "whisk.config" val swaggerUi = "whisk.swagger-ui" - val ignite = "whisk.ignite.client" + val ignite = "whisk.ignite" val igniteClient = s"$ignite.client" } From bff66f7492a3ac3bd84ad0a9c6a1a288399770cb Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 17:32:36 +0530 Subject: [PATCH 19/23] fix command names --- .../openwhisk/core/containerpool/ignite/IgniteClient.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala index f9a03a0582f..3ac8312e120 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteClient.scala @@ -64,7 +64,7 @@ class IgniteClient(dockerClient: DockerClient, } getOrElse { throw new FileNotFoundException(s"Couldn't locate ignite binary (tried: ${alternatives.mkString(", ")}).") } - Seq(dockerBin) + Seq(dockerBin, "-q") } // Invoke ignite CLI to determine client version. @@ -139,10 +139,10 @@ class IgniteClient(dockerClient: DockerClient, } override def rm(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] = - runCmd(Seq("vm", "stop", igniteId.asString), config.timeouts.rm).map(_ => ()) + runCmd(Seq("vm", "rm", igniteId.asString), config.timeouts.rm).map(_ => ()) override def stop(igniteId: IgniteId)(implicit transid: TransactionId): Future[Unit] = - runCmd(Seq("vm", "rm", igniteId.asString), config.timeouts.rm).map(_ => ()) + runCmd(Seq("vm", "stop", igniteId.asString), config.timeouts.rm).map(_ => ()) override def listRunningVMs()(implicit transid: TransactionId): Future[Seq[VMInfo]] = { //Each ignite vm has a backing container whose label is set to vm name and name to vm id From b5a220ad45895596c6b392253a3594f7095d3c87 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 17:33:09 +0530 Subject: [PATCH 20/23] Log test run --- .../containerpool/ignite/IgniteContainerFactoryTests.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactoryTests.scala b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactoryTests.scala index a958bb4ef7d..b96f9cc71d3 100644 --- a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactoryTests.scala +++ b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/ignite/IgniteContainerFactoryTests.scala @@ -26,7 +26,7 @@ import org.apache.openwhisk.core.entity.size._ import org.junit.runner.RunWith import org.scalatest.concurrent.ScalaFutures import org.scalatest.junit.JUnitRunner -import org.scalatest.{FlatSpec, Matchers} +import org.scalatest.{BeforeAndAfterAll, FlatSpec, Matchers} import scala.concurrent.duration._ @RunWith(classOf[JUnitRunner]) @@ -34,6 +34,7 @@ class IgniteContainerFactoryTests extends FlatSpec with Matchers with WskActorSystem + with BeforeAndAfterAll with StreamLogging with ScalaFutures { @@ -51,4 +52,8 @@ class IgniteContainerFactoryTests container.destroy().futureValue } + + override def afterAll(): Unit = { + println(logLines.mkString("\n")) + } } From b5bc4157a0e198b0d3890226fd1294a383112a4b Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 17:35:54 +0530 Subject: [PATCH 21/23] Add manifest file to use with standalone for ignite --- tools/ignite/runtimes.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tools/ignite/runtimes.json diff --git a/tools/ignite/runtimes.json b/tools/ignite/runtimes.json new file mode 100644 index 00000000000..476d5dfe36b --- /dev/null +++ b/tools/ignite/runtimes.json @@ -0,0 +1,20 @@ +{ + "runtimes": { + "nodejs": [ + { + "kind": "nodejs:6", + "default": false, + "image": { + "prefix": "whisk", + "name": "ignite-nodejs-v12", + "tag": "latest" + }, + "deprecated": false, + "attached": { + "attachmentName": "codefile", + "attachmentType": "text/plain" + } + } + ] + } +} \ No newline at end of file From 61d61017da9cbb8abb7247b3bad25f7b115ff620 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 17:40:09 +0530 Subject: [PATCH 22/23] Add ignite specific runtime --- tools/ignite/README.md | 33 +++++++++++++++++++ .../{runtimes.json => ignote-runtimes.json} | 0 2 files changed, 33 insertions(+) create mode 100644 tools/ignite/README.md rename tools/ignite/{runtimes.json => ignote-runtimes.json} (100%) diff --git a/tools/ignite/README.md b/tools/ignite/README.md new file mode 100644 index 00000000000..ff3e3620d99 --- /dev/null +++ b/tools/ignite/README.md @@ -0,0 +1,33 @@ + + +## Build + +First build the ignite compatible Docker images for nodejs runtime by executing below command in `nodejs` folder + +```bash +docker build -t whisk/ignite-nodejs-v12:latest . +``` + +## Launch Standalone + +``` +$ ./gradlew :core:standalone:build +$ java -Dwhisk.spi.ContainerFactoryProvider=org.apache.openwhisk.core.containerpool.ignite.IgniteContainerFactoryProvider -jar openwhisk-standalone.jar -m ignite-runtimes.json +``` \ No newline at end of file diff --git a/tools/ignite/runtimes.json b/tools/ignite/ignote-runtimes.json similarity index 100% rename from tools/ignite/runtimes.json rename to tools/ignite/ignote-runtimes.json From dc277db66db8eafa57a24d76cdc0db5e7d929276 Mon Sep 17 00:00:00 2001 From: Chetan Mehrotra Date: Fri, 12 Jul 2019 18:35:48 +0530 Subject: [PATCH 23/23] Rename the file --- tools/ignite/README.md | 4 +++- tools/ignite/{ignote-runtimes.json => ignite-runtimes.json} | 0 2 files changed, 3 insertions(+), 1 deletion(-) rename tools/ignite/{ignote-runtimes.json => ignite-runtimes.json} (100%) diff --git a/tools/ignite/README.md b/tools/ignite/README.md index ff3e3620d99..db966898d45 100644 --- a/tools/ignite/README.md +++ b/tools/ignite/README.md @@ -29,5 +29,7 @@ docker build -t whisk/ignite-nodejs-v12:latest . ``` $ ./gradlew :core:standalone:build -$ java -Dwhisk.spi.ContainerFactoryProvider=org.apache.openwhisk.core.containerpool.ignite.IgniteContainerFactoryProvider -jar openwhisk-standalone.jar -m ignite-runtimes.json +$ sudo java -Dwhisk.spi.ContainerFactoryProvider=org.apache.openwhisk.core.containerpool.ignite.IgniteContainerFactoryProvider \ + -jar bin/openwhisk-standalone.jar \ + -m tools/ignite/ignite-runtimes.json ``` \ No newline at end of file diff --git a/tools/ignite/ignote-runtimes.json b/tools/ignite/ignite-runtimes.json similarity index 100% rename from tools/ignite/ignote-runtimes.json rename to tools/ignite/ignite-runtimes.json