blob: df5127c47b5d3df59c1e5786787ccf2bd7c379de [file] [log] [blame]
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.hadoop.ozone.csi;
import java.util.concurrent.Callable;
import org.apache.hadoop.hdds.cli.GenericCli;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.conf.Config;
import org.apache.hadoop.hdds.conf.ConfigGroup;
import org.apache.hadoop.hdds.conf.ConfigTag;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.ozone.client.OzoneClient;
import org.apache.hadoop.ozone.client.OzoneClientFactory;
import org.apache.hadoop.util.StringUtils;
import io.grpc.Server;
import io.grpc.netty.NettyServerBuilder;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerDomainSocketChannel;
import io.netty.channel.unix.DomainSocketAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine.Command;
/**
* CLI entrypoint of the CSI service daemon.
*/
@Command(name = "ozone csi",
hidden = true, description = "CSI service daemon.",
versionProvider = HddsVersionProvider.class,
mixinStandardHelpOptions = true)
public class CsiServer extends GenericCli implements Callable<Void> {
private final static Logger LOG = LoggerFactory.getLogger(CsiServer.class);
@Override
public Void call() throws Exception {
OzoneConfiguration ozoneConfiguration = createOzoneConfiguration();
CsiConfig csiConfig = ozoneConfiguration.getObject(CsiConfig.class);
OzoneClient rpcClient = OzoneClientFactory.getRpcClient(ozoneConfiguration);
EpollEventLoopGroup group = new EpollEventLoopGroup();
if (csiConfig.getVolumeOwner().isEmpty()) {
throw new IllegalArgumentException(
"ozone.csi.owner is not set. You should set this configuration "
+ "variable to define which user should own all the created "
+ "buckets.");
}
Server server =
NettyServerBuilder
.forAddress(new DomainSocketAddress(csiConfig.getSocketPath()))
.channelType(EpollServerDomainSocketChannel.class)
.workerEventLoopGroup(group)
.bossEventLoopGroup(group)
.addService(new IdentitiyService())
.addService(new ControllerService(rpcClient,
csiConfig.getDefaultVolumeSize(), csiConfig.getVolumeOwner()))
.addService(new NodeService(csiConfig))
.build();
server.start();
server.awaitTermination();
rpcClient.close();
return null;
}
public static void main(String[] args) {
StringUtils.startupShutdownMessage(CsiServer.class, args, LOG);
new CsiServer().run(args);
}
/**
* Configuration settings specific to the CSI server.
*/
@ConfigGroup(prefix = "ozone.csi")
public static class CsiConfig {
private String socketPath;
private long defaultVolumeSize;
private String s3gAddress;
private String volumeOwner;
public String getSocketPath() {
return socketPath;
}
public String getVolumeOwner() {
return volumeOwner;
}
@Config(key = "owner",
defaultValue = "",
description =
"This is the username which is used to create the requested "
+ "storage. Used as a hadoop username and the generated ozone"
+ " volume used to store all the buckets. WARNING: It can "
+ "be a security hole to use CSI in a secure environments as "
+ "ALL the users can request the mount of a specific bucket "
+ "via the CSI interface.",
tags = ConfigTag.STORAGE)
public void setVolumeOwner(String volumeOwner) {
this.volumeOwner = volumeOwner;
}
@Config(key = "socket",
defaultValue = "/var/lib/csi.sock",
description =
"The socket where all the CSI services will listen (file name).",
tags = ConfigTag.STORAGE)
public void setSocketPath(String socketPath) {
this.socketPath = socketPath;
}
public long getDefaultVolumeSize() {
return defaultVolumeSize;
}
@Config(key = "default-volume-size",
defaultValue = "1000000000",
description =
"The default size of the create volumes (if not specified).",
tags = ConfigTag.STORAGE)
public void setDefaultVolumeSize(long defaultVolumeSize) {
this.defaultVolumeSize = defaultVolumeSize;
}
public String getS3gAddress() {
return s3gAddress;
}
@Config(key = "s3g.address",
defaultValue = "http://localhost:9878",
description =
"The default size of the created volumes (if not specified in the"
+ " requests).",
tags = ConfigTag.STORAGE)
public void setS3gAddress(String s3gAddress) {
this.s3gAddress = s3gAddress;
}
}
}