SafeScale is composed of 2 parts:
- a daemon working in background, called
safescaled
- a client interacting with the daemon, called
safescale
safescaled
is the daemon you need to launch on your own computer.
The purpose of this daemon is to execute requests ordered by safescale
client on the providers.
It is composed internally of 2 layers:
Infra
which manages Cloud Provider resources with an abstraction layerPlatform
which allows creating and managing clusters
To dialog with the different providers, the daemon needs authentication parameters to be able to connect to the underlying provider's API.
These credentials are given in the file tenants.toml
(may also be tenants.json
or tenants.yaml
, in their respective corresponding format).
This file is searched in order (first file found is used) in the following directories:
- . (current directory)
- $HOME/.safescale
- $HOME/.config/safescale
- /etc/safescale
The content of this configuration file is explained in TENANTS.md.
Each tenants
section contains specific authentication parameters for each Cloud Provider.
client
can be one of the available provider drivers in:
- aws
- cloudferro
- flexibleengine
- gcp
- openstack (pure OpenStack support)
- outscale
- outscale
- ovh
name
is a logical name representing the tenant
Here is an example of a tenant file:
[[tenants]]
name = "logical_name_for_this_ovh_tenant"
client = "ovh"
[tenants.identity]
ApplicationKey = "your_application_key"
OpenstackID = "your_login"
OpenstackPassword = "your_password"
[tenants.compute]
Region = "your_region"
ProjectName = "your_project_name_or_id"
[tenants.network]
ProviderNetwork = "Ext-Net"
[tenants.objectstorage]
Type = "swift"
AuthURL = "https://auth.cloud.ovh.net/v3"
[[tenants]]
client = "flexibleengine"
name = "logical_name_for_this_flexibleengine_tenant"
[tenants.identity]
Username = "your_login"
Password = "your_password"
DomainName = "your_domaine_name"
[tenants.compute]
ProjectID = "your_project_id"
Region = "your_region"
[tenants.network]
VPCName = "your_VPC_name"
VPCCIDR = "your_VPC_cidr"
[tenants.objectstorage]
Type = "s3"
Endpoint = "https://oss.eu-west-0.prod-cloud-ocb.orange-business.com"
AccessKey = "your_S3_login"
SecretKey = "your_S3_password"
[[tenants]]
client = "opentelekom"
name = "logical_name_for_this_opentelekom_tenant"
[tenants.identity]
Username = "your_login"
Password = "your_password"
DomainName = "your_domaine_name"
[tenants.compute]
ProjectID = "your_project_id"
Region = "your_region"
[tenants.network]
VPCName = "your_VPC_name"
VPCCIDR = "your_VPC_cidr"
[tenants.objectstorage]
Type = "s3"
Endpoint = "https://obs.eu-de.otc.t-systems.com"
AccessKey = "your_S3_login"
SecretKey = "your_S3_password"
If you built SafeScale from source, make install
will install the binaries in $GOPATH/bin.
To launch the SafeScale daemon, simply execute the following command (from a regular user, no need to be root):
$ ${GOPATH}/bin/safescaled &
or if ${GOPATH}/bin
is in your PATH
:
$ safescaled &
It should display in your terminal something like this:
Safescaled version: 21.11.0, build 5c7cc25ed29888ba6f8c9ee6feb6c48b79dde763 (2021/12/17-21:35)
Ready to serve on 'localhost:50051' :-)
By default, safescaled
displays only warnings and errors messages. To have more information, you can use -v
to increase verbosity, and -d
to use debug mode (-d -v
will produce A LOT of messages, it's for debug purposes).
Option | Description |
---|---|
--verbose|-v |
Increase the verbosity. ex: safescale -v host create ... |
--debug|-d |
Displays debugging information. ex: safescale -d host create ... |
--listen|-l |
defines on what interface and what port safescaled will listen; default is localhost:50051 |
Examples:
$ safescaled
will start the daemon, listening on localhost
on default port 50051
; it will be reachable only from the same host.
$ safescaled -v -l :50000
will start the daemon, listening on all interfaces and on port 50000
(instead of default port 50051)
Note: -d -v
will display far more debugging information than simply -d
(used to trace what is going on in details)
You can also set some parameters of safescaled
using environment variables, which are :
SAFESCALED_LISTEN
: equivalent to--listen
, allows to define on what interface and/or what portsafescaled
has to listen on; used also bysafescale
to reach the daemonSAFESCALE_METADATA_SUFFIX
: allows to specify a suffix to add to the name of the Object Storage bucket used to store SafeScale metadata on the tenant. This allows to "isolate" metadata between different users of SafeScale on the same tenant (useful in development for example). There is no equivalent command line parameter.
safescale
is the client part of SafeScale. It consists of a CLI to interact with the SafeScale daemon to manage cloud infrastructures.
The different available commands can be obtained via the --help
option on each command and are listed hereafter. Note that, despite our efforts, the help displayed by the CLI might be more accurate and up-to-date than the following descriptions.
Each command returns its results on the standard output in 2 forms according to the expected result type:
- no result is expected: a simple comment about the execution of the command
- a result is expected: the result is formatted in JSON (or null if no result is produced); for eye-candy formatting, you can use
| jq
at the end of the command. - outputs are expected: the outputs are displayed in sync with the work done on the remote side (for example,
safescale platform kubectl
command)
Each command has an exit status which is 0 if it succeeded, and !=0 if failed. If the command displays a result in JSON format, the JSON code contains the same exit code.
In multiple occasions, it will be necessary to define the Host sizing required. This sizing allows to find the Host templates that match on Cloud Provider side.
The format used by this string representation is:
<component><operator><value>[,...]
where:
<component>
can be:<operator>
can be:=
means exactly<value>
~
means between<value>
and 2x<value>
(not available for component<disk>
)<
means strictly lower than<value>
(not available for component<disk>
)<=
means lower or equal to<value>
(not available for component<disk>
)>
means strictly greater than<value>
(not available for component<disk>
)>=
means greater or equal to<value>
<value>
can be:- an integer
- a float
- an including interval
[<lower_value>-<upper_value>]
<component>
accepts <value>
following these rules:
<cpu>
is expecting an integer as number of cpu cores, or an interval with minimum and maximum number of cpu cores<cpufreq>
is expecting an integer as minimum cpu frequency in MHz<gpu>
is expecting an integer as number of GPU (scanner would have been run first to be able to determine which template proposes GPU)<ram>
is expecting a float as memory size in GB, or an interval with minimum and maximum memory size<disk>
is expecting an integer as system disk size in GB<template>
is expecting the name of a template, example:"template=e2-medium"
"cpu <= 4, ram <= 10, disk >= 100"
Match any Host template with at most 4 cores,at most 10 GB of ram and at least 100 GB of system disk"cpu ~ 4, ram = [14-32]"
Match any Host template with between 4 and 4x2=8 cores, between 14 and 32 GB of ram (it's identical to"cpu=[4-8], ram=[14-32]"
)"cpu <= 8, ram ~ 16"
Match any Host template with at most 8 cores and between 16 and 16x2=32 GB of ram
Every time you will see <sizing>
in this document, you will have to refer to this format.
safescale
accepts global options just before the subcommand, which are:
Option | Description |
--verbose|-v |
Increase the verbosity. example: safescale -v host create ...
|
--debug|-d |
Displays debugging information. example: safescale -d host create ...
|
Example:
$ safescale -v network create --cidr 192.168.1.0/24 mynetwork
There are 3 categories of commands:
- the one dealing with tenants (aka cloud providers): tenant
- the ones dealing with infrastructure resources: network, subnet, host, volume, share, bucket, ssh
- the one dealing with clusters: cluster
The commands are presented in logical order as if the user wanted to create some servers with a shared storage space.
Note: for clarity, the json results are beautified (as if the example is called with | jq
); real outputs are one-liners.
A tenant must be set before using any other command as it indicates to SafeScale which tenant the command must be executed on. _Note that if only one tenant is defined in the tenants.toml
, it will be automatically selected while invoking any other command.
The following actions are proposed:
Action | Description |
safescale tenant list |
List available tenants i.e. those found in the tenants.toml code> file.example: $ safescale tenant listresponse: { "result": { "name": "TestOVH" }, "status":"success" } |
safescale tenant get |
Display the current tenant used for action commands. example: $ safescale tenant getresponse when tenant set: { "result": { "name":"TestOVH" }, "status": "success" }response when tenant not set: { "error": { "exitcode": 6, "message": "Cannot get tenant: no tenant set" }, "result": null, "status": "failure" } |
safescale tenant set <tenant_name> |
Set the tenant to use by the next commands. The <tenant_name> must match one of those present in
the tenants.toml file, from key name ). The name is case sensitive.example: $ safescale tenant set TestOvhresponse on success: { "result": null, "status": "success" }response on failure: { "error": { "exitcode": 6, "message": "Unable to set tenant 'TestOvh': tenant 'TestOvh' not found in configuration" }, "result": null, "status": "failure" } |
safescale tenant scan <tenant_name> |
Scan the given tenant <tenant_name> for templates (see scanner documentation for more details) |
A template represents a predefined host sizing proposed by Cloud Provider. The following actions are available:
Action | Description |
safescale template list |
List available templates from the current tenant. example: $ safescale template listresponse: { "result": [ { "cores": 16, "disk": 400, "id": "0526e13e-dad5-473f-ad61-2f15e0db2a15", "ram": 240 } ], "status": "success" } |
safescale template inspect <template_name> |
Display information about a template. example: safescale template inspect s1-4response on success (without scan): { "result": [ { "cores": 1, "disk": 20, "id": "cbef4222-84ff-4f8b-ba40-e5ba85cfbb53", "name": "s1-4", "ram": 4, } ], "status": "success" }response on success (after scan): { "result": [ { "cores": 1, "disk": 20, "id": "cbef4222-84ff-4f8b-ba40-e5ba85cfbb53", "name": "s1-4", "ram": 4, "scanned": { "cpu_arch": "x86_64", "cpu_frequency_Ghz": 2.39998, "cpu_model": "Intel Core Processor (Haswell, no TSX)", "disk_size_Gb": 20, "hypervisor": "KVM", "image_id": "c48cd747-14be-4e73-9a8b-6c9a1bec6ceb", "image_name": "Ubuntu 20.04", "last_updated": "Wednesday, 24-Feb-21 18:53:22 CET", "main_disk_speed_MBps": 228.61, "main_disk_type": "HDD", "number_of_core": 1, "number_of_cpu": 1, "number_of_socket": 1, "ram_size_Gb": 3.75, "sample_net_speed_KBps": 17.827375, "template_id": "c48cd747-14be-4e73-9a8b-6c9a1bec6ceb", "template_name": "s1-4", "tenant_name": "ovh" } } ], "status": "success" }response on failure: { "error": { "exitcode": 6, "message": "Cannot inspect tenant: template named 's1-4' not found" }, "result": null, "status": "failure" } |
This command manages Networks
, Subnets
and SecurityGroups
on the provider side. In some Cloud Providers terminology, Network
can be called VPC (FlexibleEngine, AWS, ...).
Before release v21.03, Cloud Provider networks and subnets were melted into a SafeScale Network
. Since release v21.03, Subnets are introduced.
For compatibility reason, default behavior of safescale network
has been maintained as before, creating by default a Subnet
named as the Network
with a CIDR derived from the one of the Network.
For example, safescale network create --cidr 172.16.0.0/16 my-net
will create a Network
with a CIDR of 172.16.0.0/16 and a Subnet
inside the Network
with a CIDR of 172.16.0.0/17.
Since v21.03, it's now possible to create a Network
without default Subnet
, using --empty
flag, leaving the responsibility of Subnet
creation to the user. If --empty
is used, the flags --gwname
, --os
, --gw-sizing
and --failover
are meaningless.
A Network
being the owner of a SecurityGroup
, the commands relative to SecurityGroup
resides inside safescale network security group
.
The following actions are proposed:
Action | Description |
safescale network create [command_options] <network_name> |
Creates a network with the given name.command_options :
--empty is not used
example: $ safescale network create example_networkresponse on success: { "result": { "cidr": "192.168.0.0/24", "gateway_id": "48112419-3bc3-46f5-a64d-3634dd8bb1be", "id": "76ee12d6-e0fa-4286-8da1-242e6e95844e", "name": "example_network", "virtual_ip": {} }, "status": "success" }response on failure: { "error": { "exitcode": 6, "message": "Network 'example_network' already exists" }, "result": null, "status": "failure" } |
safescale network list [command_options]
|
List Networks created by SafeScalecommand_options :
|
safescale network inspect <network_name_or_id> |
Get information about a Network created by SafeScale.example: $ safescale network inspect example_networkresponse on success: { "result": { "cidr": "192.168.0.0/24", "gateway_id": "48112419-3bc3-46f5-a64d-3634dd8bb1be", "gateway_name": "gw-example_network", "id": "76ee12d6-e0fa-4286-8da1-242e6e95844e", "name": "example_network" }, "status": "success" }response on failure: { "error": { "exitcode": 6, "message": "Failed to find 'networks/byName/fake_network'" }, "result": null, "status": "failure" } |
safescale network delete <network_name_or_id> |
Delete a Network created by SafeScale.example: $ safescale network delete example_networkresponse on success: { "result": null, "status": "success" }response on failure ( Network does not exist):
{ "error": { "exitcode": 6, "message": "Cannot delete network: failed to find Network 'example_network'" }, "result": null, "status": "failure" }response on failure (hosts still attached to network): { "error": { "exitcode": 6, "message": "Cannot delete network: failed to delete Subnet 'example_network': cannot delete subnet 'example_network': 1 host is still attached to it: example-host" }, "result": null, "status": "failure" } |
safescale network subnet create [command_options] <network_name_or_id> <subnet_name> |
Creates a Subnet with the given name.command_options :
$ safescale network subnet create --cidr 192.168.1.0/24 example_network example_subnetresponse on success: { "result": { "cidr": "192.168.1.0/24", "gateway_ids": [ "8fd9b241-f4fe-4f80-a162-def3858053ee" ], "id": "acca6c3c-f17b-4132-a8a3-cef147fde464", "name": "example_subnet", "state": 3 }, "status": "success" }response on failure: { "error": { "exitcode": 6, "message": "Cannot create Subnet: subnet 'example_subnet' already exists" }, "result": null, "status": "failure" } |
safescale network subnet list [command_options] <network_name_or_id> |
List Subnets created by SafeScale.command_options :
|
safescale network subnet inspect <network_name_or_id> <subnet_name_or_id> |
Get information about a Subnet created by SafeScale.`example: $ safescale network subnet inspect example_network example_subnetresponse on success: { "result": { "cidr": "192.168.1.0/24", "gateway_ids": [ "8fd9b241-f4fe-4f80-a162-def3858053ee" ], "gateway_name": "gw-example_subnet", "gateways": [ "gw-example_subnet" ], "id": "acca6c3c-f17b-4132-a8a3-cef147fde464", "name": "example_subnet", "state": 3 }, "status": "success" }response on failure: { "error": { "exitcode": 6, "message": "Cannot inspect Subnet: failed to find a subnet referenced by 'example_subnet' in network 'example_network'" }, "result": null, "status": "failure" } |
safescale network subnet delete <network_name_or_id> <subnet_name_or_id> |
Delete a Subnet created by SafeScale.If <subnet_name_or_id> contains a name, <network_name_or_id> is mandatory.If <subnet_name_or_id> contains an ID, <network_name_or_id> can be omitted using "" or - .examples:
|
safescale network security group create [command_options] <network_name_or_id> <security_group_name> |
Creates a SecurityGroup in a Network .command_options :
$ safescale network security group create --description "sg for hosts in example_network" example_network sg_example_hostsresponse on success: { "result":{ "default_for_hosts": "", "default_for_subnets": "", "description": "sg for hosts in example_network", "id": "sg-b4c05e51", "name": "sg_example_hosts", "rules": [] }, "status": "success" }response on failure (Security Group name invalid): { "error": { "exitcode": 6, "message": "Cannot create security group: stopping retries: invalid Security Group name" }, "result": null, "status": "failure" }response on failure (Network not found): { "error": { "exitcode": 6, "message": "Cannot create security group: failed to find Network 'example_network'" }, "result": null, "status": "failure" } |
safescale network security group list [command_options] <network_name_or_id> |
List SecurityGroups available in a Network command_options :
|
safescale network security group inspect <network_name_or_id> <security_group_name_or_id> |
Get information about a SecurityGroup example: $ safescale network security group inspect example-net safescale-sg_subnet_publicip.example-net.example-netresponse on success: { "result": { "description": "SG for hosts with public IP in Subnet example-net of Network example-net", "id": "d1eaabcd-765b-49e9-883a-2f34d273bec0", "name": "safescale-sg_subnet_publicip.example-net.example-net" }, "status": "success" }response on failure: { "error": { "exitcode": 6, "message": "cannot inspect security group: failed to find Security Group 'safescale-sg_subnet_publicip.example-net.example-net'" }, "result": null, "status": "failure" } |
safescale network security group delete <network_name_or_id> <security_group_name_or_id> |
Deletes a Security Group example: $ safescale network security group delete example-net sg_example_hostsresponse on success: { "result": null, "status": "success" }response on failure (Security Group does not exist): { "error": { "exitcode": 6, "message": "Cannot delete Security Group: failed to find Security Group 'sg_example_hosts'" }, "result": null, "status": "failure" } |
safescale network security group clear <network_name_or_id> <security_group_name_or_id> |
Removes rules from a Security Group example: $ safescale network security group clear example-net sg_example_hostsresponse on success: { "result": null, "status": "success" }response on failure (Security Group does not exist): { "error": { "exitcode": 6, "message": "Cannot delete Security Group: failed to find Security Group 'sg_example_host'" }, "result": null, "status": "failure" } |
safescale network security group bonds <network_name_or_id> <security_group_name_or_id> |
Lists Security Groups bonds example: $ safescale network security group bonds example-net sg_example_hostsresponse on success: { "result": { "hosts": [ { "id": "i-1e153525", "name": "gw-example-net" } ], "subnets": [ { "id": "subnet-684dff0c", "name": "example-net" } ] }, "status": "success" }response on failure (Security Group does not exist): { "error": { "exitcode": 6, "message": "Cannot delete Security Group: failed to find Security Group 'sg_example_host'" }, "result": null, "status": "failure" } |
safescale network security group rule add [command_options] <network_name_or_id> <security_group_name_or_id> |
Add a Security Group rulecommand_options :
$ safescale network security group rule add --from-port 80 --source 0.0.0.0/0 --description "allow HTTP" example-net sg_for_some_hostsresponse on success: { "result": null, "status": "success" } |
safescale network security group rule delete [command_options] <network_name_or_id> <security_group_name_or_id> |
Delete a rule from a Security Groupcommand_options :
$ safescale network security group rule add --from-port 80 --source 0.0.0.0/0 --description "allow HTTP" example-net sg-for-some-hostsresponse on success: { "result":null, "status":"success" } |
Note: if <subnet_name_or_id>
or <security_group_name_or_id>
contain an ID, value can be empty string ("" or -
); the ID is sufficient to locate what resource is concerned.
This command family deals with host management: creation, list, connection, deletion... The following actions are proposed:
Action | description |
safescale [global_options] host create [command_options] <host_name> |
Creates a new host. This host will be attached to the requested `Subnet`. Note that by default this host is created with a private IP address.command_options :
|
safescale [global_options] host list [options] |
List hostscommand_options code:
|
safescale [global_options] host inspect <host_name_or_id> |
Get detailed information about a host example: $ safescale host inspect example_hostresponse on success: { "result": { "cpu": 1, "disk": 10, "gateway_id": "39a5043a-1790-4a4f-bb87-788bb7252d13", "id": "abcaa3df-6f86-4533-9a29-6e20e16fd957", "name": "myhost", "password": "xxxxxxxxxxxx", "private_ip": "192.168.0.169", "private_key": "-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY-----\n", "ram": 2, "state": 2 }, "status": "success" }response on failure: { "error": { "exitcode": 6, "message": "Cannot inspect host: failed to find host 'myhost'" }, "result": null, "status": "failure" } |
safescale [global_options] host ssh <host_name_or_id> |
Get SSH configuration to connect to host (for use without SafeScale for example) example: $ safescale host ssh myhostresponse on success: { "result": { "GatewayConfig": { "GatewayConfig": null, "Host": "51.83.34.22", "LocalPort": 0, "Port": 22, "PrivateKey": "-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY-----\n", "User": "safescale" }, "Host": "192.168.0.169", "LocalPort": 0, "Port": 22, "PrivateKey": "-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY-----\n", "User": "safescale" }, "status": "success" }response on failure: { "error": { "exitcode": 6, "message": "Failed to find 'hosts/byName/myhost'" }, "result": null, "status": "failure" } |
safescale [global_options] host delete <host_name_or_id> [...] |
Delete host(s) example: $ safescale host delete myhostresponse on success: { "result": null, "status": "success" }response on failure: { "error": { "exitcode": 6, "message": "Failed to find host 'myhost'" }, "result": null, "status": "failure" } |
safescale [global_options] host start <host_name_or_id> |
Starts a Host. example: $ safescale host start example_hostresponse on success: {"result":null,"status":"success"}response on failure: {"error":{"exitcode":6,"message":"Cannot start host: timeout waiting Host 'myhost' to be started: retries timed out after 00h02m30.378s (timeout defined at 00h02m30.000s) (timeout: 2m30s): myhost not started yet: Stopped [ctx: 57df83c7-c2b4-4873-87cc-26eeafda5d17]"},"result":null,"status":"failure"} |
safescale [global_options] host stop <host_name_or_id> |
Stop a Host. example: $ safescale host stop example_hostresponse on success: {"result":null,"status":"success"}response on failure: {"error":{"exitcode":6,"message":"Cannot stop host: timeout waiting Host 'myhost' to be stopped: retries timed out after 00h02m30.326s (timeout defined at 00h02m30.000s) (timeout: 2m30s): myhost not stopped yet: Started [ctx: df57ffb8-71f5-404c-a554-a258c6a43c5e]"},"result":null,"status":"failure"} |
safescale [global_options] host reboot <host_name_or_id> |
Reboots an Host. example: $ safescale host reboot example_hostresponse on success: {"result":null,"status":"success"}response on failure: {"error":{"exitcode":6,"message":"Cannot reboot host: stopping retries: Cannot 'stop' instance ddac95cf-340f-4e89-8b60-ce3b62a43e79 while it is in vm_state stopped [ctx: 2b8c0ad9-dfd8-498f-9736-27c2f80233ec]"},"result":null,"status":"failure"} |
safescale [global_options] host status <host_name_or_id> |
Displays the current status of an Host. example: $ safescale host status example_hostresponse on success: {"result":{"name":"myhost","status_code":0,"status_label":"Stopped"},"status":"success"}response on failure: {"error":{"exitcode":6,"message":"Cannot get host status: host 'boom' not found [ctx: 92290112-acf3-43c8-9257-59bf96d2e95f]"},"result":null,"status":"failure"} |
safescale [global_options] host feature check [command_options] <host_name_or_id> <feature_name> |
Check if a feature is present on the hostcommand_options :
$ safescale host check-feature myhost dockerresponse if feature is present { "result": null, "status": "success" }response if feature is not present: { "error": { "exitcode": 4, "message": "Feature 'docker' not found on host 'myhost'" }, "result": null, "status": "failure" } |
safescale [global_options] host feature add [command_options] <host_name_or_id> <feature_name> |
Adds the feature to the hostcommand_options :
$ safescale host feature add -p Username=<username> -p Password=<password> myhost remotedesktopresponse on success: { "result": null, "status": "success" }response on failure may vary. |
safescale [global_options] host feature delete [command_options] <host_name_or_id> <feature_name> |
Deletes the feature from the hostcommand_options :
$ safescale host feature delete -p Username=<username> -p Password=<password> myhost remotedesktopresponse on success: { "result": null, "status": "success" } |
safescale [global_options] host security group list <host_name_or_id> |
Lists the Security Groups bound to an Host. example: $ safescale host security group list carvedresponse on success: {"result":[{"id":"79ea1d7a-a813-46f0-931e-e77b34056be3","name":"safescale-sg_subnet_internals.carved.carved"}],"status":"success"}response on failure: {"error":{"exitcode":6,"message":"Cannot list security group on host: host 'riot' not found [ctx: af2a9c7c-ca56-48f6-9c88-de47bc7cdd8c]"},"result":null,"status":"failure"} |
safescale [global_options] host security group bind <host_name_or_id> <securitygroup_name_or_id> |
Links a Security Group to an Host. example: $ safescale host security group bind example_host sg-for-some-hostsresponse on success: { "result": null, "status": "success" }response on failure: {"error":{"exitcode":6,"message":"Cannot bind Security Group to Host: neither security-groups/byName/default nor security-groups/byID/default were found in the bucket [ctx: f086fba0-4268-422d-84f0-aab92f62310e]"},"result":null,"status":"failure"} |
safescale [global_options] host security group unbind <host_name_or_id> <securitygroup_name_or_id> |
Unlinks a Security Group from an Host. example: $ safescale host security group bind example_host sg-for-some-hostsresponse on success: { "result": null, "status": "success" }response on failure: {"error":{"exitcode":6,"message":"Cannot unbind Security Group from Host: neither security-groups/byName/default nor security-groups/byID/default were found in the bucket [ctx: f086fba0-4268-422d-84f0-aab92f62310e]"},"result":null,"status":"failure"} |
This command family deals with volume (i.e. block storage) management: creation, list, attachment to a host, deletion... The following actions are proposed:
Action | description |
safescale volume create [command_options] <volume_name>> |
Create a volume with the given name on the current tenant using default sizing values.command_options :
$ safescale volume create myvolumeresponse on success { "result": { "ID": "c409033f-e569-42f5-927a-5b1c35029500", "Name": "myvolume", "Size": 10, "Speed": "HDD" }, "status": "success" }response on failure: { "error": { "exitcode": 6, "message": "Volume myvolume already exists" }, "result": null, "status": "failure" } |
safescale volume list |
List available volumes example: $ safescale volume listresponse: { "result": [ { "id": "4463647d-035b-4e16-8ea9-b3c29acd1887", "name": "myvolume", "size": 10, "speed": 1 } ], "status": "success" } |
safescale volume inspect <volume_name_or_id> |
Get info about a volume. example: $ safescale volume inspect myvolumeresponse on success { "result": { "device_uuid": "cc3bbc5c-bc99-409d-90be-265bcdc5b506", "format": "nfs", "host": "i-086512601f6606319", "id": "vol-02b5a3740f249d2b2", "mount_path": "/data/my-volume", "name": "my-volume", "size": 200, "speed": "VS_HDD" }, "status": "success" }response on failure: { "error": { "exitcode": 6, "message": "Failed to find volume myvolume" }, "result": null, "status": "failure" } |
safescale volume attach [command_options] <volume_name_or_id> <host_name_or_id> |
Attach the Volume to a Host. It mounts the volume in a directory of the Host. The directory is created if it does not already exists.
The Volume is formatted by default.command_options :
$ safescale volume attach myvolume myhostresponse on success: { "result": null, "status": "success" }response on failure (Volume not found): { "error": { "exitcode": 6, "message": "Failed to find volume myvolume" }, "result": null, "status": "failure" }response on failure (Host not found): { "error": { "exitcode": 6, "message": "Failed to find host myhost2" }, "result": null, "status": "failure" } |
safescale volume detach <volume_name_or_id> <host_name_or_id> |
Detach a Volume from a Host example: $ safescale volume detach myvolume myhostresponse on success: { "result": null, "status": "success" }response on failure (Volume not found): { "error": { "exitcode": 6, "message": "Failed to find volume myvolume" }, "result": null, "status": "failure" }response on failure (Host not found): { "error": { "exitcode": 6, "message": "Failed to find host myhost" }, "result": null, "status": "failure" }response on failure (Volume not attached to Host): { "error": { "exitcode": 6, "message": "Cannot detach volume myvolume: not attached to host myhost" }, "result": null, "status": "failure" } |
safescale volume delete <volume_name_or_id> |
Delete the Volume with the given name or ID. example: $ safescale volume delete myvolumeresponse on success: { "result": null, "status": "success" }response on failure (Volume attached): { "error": { "exitcode": 6, "message": "Cannot delete volume myvolume: still attached to 1 host: myhost" }, "result": null, "status": "failure" }response on failure (Volume not found): { "error": { "exitcode": 6, "message": "Cannot delete volume myvolume: failed to find volume myvolume" }, "result": null, "status": "failure" } |
This command family deals with share management: creation, list, deletion... The following actions are proposed:
Action | description |
safescale [global_options] share list |
List existing shares example: $ safescale share listresponse: { "result": [ { "host": { "name": "myhost" }, "id": "d8eed474-dc3b-4a4d-91e6-91dd03cd98dd", "name": "myshare", "path": "/shared/data", "type": "nfs" } ], "status": "success" } |
safescale [global_options] share inspect <share_name> |
Get detailed information about the share. example: $ safescale share inspect myshareresponse on success { "result": { "mount_list": [ { "host": { "name": "myclient" }, "path": "/shared", "share": { "name": "myshare" }, "type": "nfs" } ], "share": { "host": { "name": "myhost" }, "id": "d8eed474-dc3b-4a4d-91e6-91dd03cd98dd", "name": "myshare", "path": "/shared/data", "type": "nfs" } }, "status": "success" }response on failure { "error": { "exitcode": 6, "message": "cannot inspect share myshare [caused by {failed to find share myshare}]" }, "result": null, "status": "failure" } |
safescale [global_options] share create [command_options] <share_name> <host_name_or_id> |
Create a Share on a Host and export the corresponding foldercommand_options :
`$ safescale share create myshare myhost` response on success: `{"result":null,"status":"success"}` reponse on failure: `{"error":{"exitcode":6,"message":"cannot create share 'myshare' [caused by {share 'myshare' already exists}]"},"result":null,"status":"failure"}` |
safescale [global_options] share mount [command_options] <share_name> <host_name_or_id> |
Mount a Share on a Hostcommand_options :
$ safescale share mount myshare myclientresponse on success: {"result":null,"status":"success"}response on failure (Share not found) {"error":{"exitcode":6,"message":"cannot unmount share 'myshare' [caused by {failed to find share 'myshare'}]"},"result":null,"status":"failure"}response on failure (Host not found) {"error":{"exitcode":6,"message":"cannot unmount share 'myshare' [caused by {failed to find host 'myclient'}]"},"result":null,"status":"failure"} |
safescale [global_options] share umount <share_name> <host_name_or_id> |
Unmount a Share from an Host example: $ safescale share umount myshare myclientresponse on success: {"result":null,"status":"success"}response on failure (Host not found) {"error":{"exitcode":6,"message":"cannot unmount share 'myshare' [caused by {failed to find host 'myclient'}]"},"result":null,"status":"failure"}response on failure (Share not found) {"error":{"exitcode":6,"message":"cannot unmount share 'myshare' [caused by {failed to find share 'myshare'}]"},"result":null,"status":"failure"} |
safescale [global_options] share delete <share_name> |
Delete a Share. Note: the content in itself of the Share is not deleted, it remains on the Host acting as server. example: $ safescale share delete myshareresponse on success: {"result":null,"status":"success"}response on failure (Share still mounted): {"error":{"exitcode":6,"message":"error while deleting share myshare: Cannot delete share 'myshare' [caused by {still used by: 'myclient'}]"},"result":null,"status":"failure"}response on failure (Share not found): {"error":{"exitcode":6,"message":"error while deleting share myshare: Failed to find share 'myshare'"},"result":null,"status":"failure"} |
This command family deals with object storage management: creation, list, mounting as filesystem, deleting... The following actions are proposed:
Action | description |
safescale [global_options] bucket create <bucket_name> |
Create a bucket example: $ safescale bucket create mybucketresponse on success {"result":null,"status":"success"}response on failure {"error":{"exitcode":6,"message":"Cannot create bucket [caused by {bucket 'mybucket' already exists}]"},"result":null,"status":"failure"} |
safescale [global_options] bucket list |
List buckets example: $ safescale bucket listresponse {"result":{"buckets":[{"name":"0.safescale-96d245d7cf98171f14f4bc0abd8f8019"},{"name":"mybucket"}]},"status":"success"} |
safescale [global_options] bucket inspect <bucket_name> |
Get info about a bucket example: $ safescale bucket inspect mybucketresponse on success: {"result":{"bucket":"mybucket","host":{}},"status":"success"}response on failure {"error":{"exitcode":6,"message":"Cannot inspect bucket [caused by {failed to find bucket 'mybucket'}]"},"result":null,"status":"failure"} |
safescale [global_options] bucket mount [command_options] <bucket_name> <host_name_or_id> |
Mount a Bucket as a filesystem on an Host.command_options :
$ safescale bucket mount mybucket myhostresponse on success: {"result":null,"status":"success"}response on failure (Host not found) {"error":{"exitcode":6,"message":"No host found with name or id 'myhost2'"},"result":null,"status":"failure"}response on failure (Bucket not found) {"error":{"exitcode":6,"message":"Not found"},"result":null,"status":"failure"} |
safescale [global_options] bucket umount <bucket_name> <host_name_or_id> |
Unmount a Bucket from the filesystem of an Host. example: $ safescale bucket umount mybucket myhostresponse on success: {"result":null,"status":"success"}response on failure (Bucket not found) {"error":{"exitcode":6,"message":"Failed to find bucket 'mybucket'"},"result":null,"status":"failure"}response on failure (Host not found) {"error":{"exitcode":6,"message":"Failed to find host 'myhost'"},"result":null,"status":"failure"} |
safescale [global_options] bucket delete <bucket_name> |
Delete a Bucket example: $ safescale bucket delete mybucketresponse on success: {"result":null,"status":"success"}response on failure (Bucket not found) {"error":{"exitcode":6,"message":"cannot delete bucket [caused by {Container Not Found}]"},"result":null,"status":"failure"}response on failure (Bucket mounted on Host(s)) {"error":{"exitcode":6,"message":"cannot delete bucket [caused by {Container Not Empty}]"},"result":null,"status":"failure"} |
The following commands deals with ssh commands to be executed on a host. The following actions are proposed:
Action | description |
safescale [global_options] ssh run -c "<command>" <host_name_or_id> |
Run a command on the hostcommand is the command to execute remotely.example: $ safescale ssh run -c "ls -la ~" example_hostresponse on success: total 32 drwxr-xr-x 4 safescale safescale 4096 Jun 5 13:25 . drwxr-xr-x 4 root root 4096 Jun 5 13:00 .. -rw------- 1 safescale safescale 15 Jun 5 13:25 .bash_history -rw-r--r-- 1 safescale safescale 220 Aug 31 2015 .bash_logout -rw-r--r-- 1 safescale safescale 3771 Aug 31 2015 .bashrc drwx------ 2 safescale safescale 4096 Jun 5 13:01 .cache -rw-r--r-- 1 safescale safescale 0 Jun 5 13:00 .hushlogin -rw-r--r-- 1 safescale safescale 655 May 16 2017 .profile drwx------ 2 safescale safescale 4096 Jun 5 13:00 .ssh |
safescale [global_options] ssh copy <src> <dest> |
Copy a local file/directory to an Host or copy from an Host to local example $ safescale ssh copy /my/local/file example_host:/remote/path |
safescale [global_options] ssh connect <host_name_or_id> |
Connect to an Host with interactive shell example: $ safescale ssh connect example_hostresponse on success: safescale@example-Host:~$ |
This command family deals with cluster management: creation, inspection, deletion, ...
cluster
has synonyms: platform
, datacenter
, dc
.
The following actions are proposed:
Action | description |
safescale [global_options] cluster list |
List clusters example: $ safescale cluster listresponse on success: {"result":[{"cidr":"192.168.0.0/16","complexity":1,"complexity_label":"Small","default_route_ip":"192.168.2.245","endpoint_ip":"51.83.34.144","flavor":2,"flavor_label":"K8S","last_state":5,"last_state_label":"Created","name":"mycluster","primary_gateway_ip":"192.168.2.245","primary_public_ip":"51.83.34.144","remote_desktop":{"mycluster-master-1":["https://51.83.34.144/_platform/remotedesktop/mycluster-master-1/"]},"tenant":"TestOVH"}],"status":"success"} |
safescale [global_options] cluster create [command_options] <cluster_name> |
Creates a new cluster.command_options :
--sizing , --gw-sizing , --master-sizing and --node-sizing instead
! WARNING ! flags '--' or '-' MUST be used BEFORE arguments like stated in command description: running safescale cluster create mycluster -C large IGNORES -C large , using safescale cluster create -C large mycluster works as expected
example: $ safescale cluster create -F k8s -C small -N 192.168.22.0/24 myclusterresponse on success: {"result":{"admin_login":"cladm","admin_password":"xxxxxxxxxxxx","cidr":"192.168.0.0/16","complexity":1,"complexity_label":"Small","default_route_ip":"192.168.2.245","endpoint_ip":"51.83.34.144","features":{"disabled":{"proxycache":{}},"installed":{}},"flavor":2,"flavor_label":"K8S","gateway_ip":"192.168.2.245","last_state":5,"last_state_label":"Created","name":"mycluster","network_id":"6669a8db-db31-4272-9acd-da49dca07e14","nodes":{"masters":[{"id":"9874cbc6-bd17-4473-9552-1f7c9c7a2d6f","name":"mycluster-master-1","private_ip":"192.168.0.86","public_ip":""}],"nodes":[{"id":"019d2bcc-9d8c-4c76-a638-cf5612322dfa","name":"mycluster-node-1","private_ip":"192.168.1.74","public_ip":""}]},"primary_gateway_ip":"192.168.2.245","primary_public_ip":"51.83.34.144","remote_desktop":{"mycluster-master-1":["https://51.83.34.144/_platform/remotedesktop/mycluster-master-1/"]},"tenant":"XXXX"},"status":"success"}response on failure (cluster already exists): {"error":{"exitcode":8,"message":"Cluster 'mycluster' already exists.\n"},"result":null,"status":"failure"} |
safescale [global_options] cluster inspect <cluster_name> |
Get info about a cluster example: $ safescale cluster inspect myclusterresponse on success: {"result":{"admin_login":"cladm","admin_password":"xxxxxxxxxxxxxx","cidr":"192.168.0.0/16","complexity":1,"complexity_label":"Small","default_route_ip":"192.168.2.245","defaults":{"gateway":{"max_cores":4,"max_ram_size":16,"min_cores":2,"min_disk_size":50,"min_gpu":-1,"min_ram_size":7},"image":"Ubuntu 20.04","master":{"max_cores":8,"max_ram_size":32,"min_cores":4,"min_disk_size":80,"min_gpu":-1,"min_ram_size":15},"node":{"max_cores":8,"max_ram_size":32,"min_cores":4,"min_disk_size":80,"min_gpu":-1,"min_ram_size":15}},"endpoint_ip":"51.83.34.144","features":{"disabled":{"proxycache":{}},"installed":{}},"flavor":2,"flavor_label":"K8S","gateway_ip":"192.168.2.245","last_state":5,"last_state_label":"Created","name":"mycluster","network_id":"6669a8db-db31-4272-9acd-da49dca07e14","nodes":{"masters":[{"id":"9874cbc6-bd17-4473-9552-1f7c9c7a2d6f","name":"mycluster-master-1","private_ip":"192.168.0.86","public_ip":""}],"nodes":[{"id":"019d2bcc-9d8c-4c76-a638-cf5612322dfa","name":"mycluster-node-1","private_ip":"192.168.1.74","public_ip":""}]},"primary_gateway_ip":"192.168.2.245","primary_public_ip":"51.83.34.144","remote_desktop":{"mycluster-master-1":["https://51.83.34.144/_platform/remotedesktop/mycluster-master-1/"]},"tenant":"XXXX"},"status":"success"}response on failure: {"error":{"exitcode":4,"message":"Cluster 'mycluster' not found.\n"},"result":null,"status":"failure"} |
safescale [global_options] cluster state <cluster_name> |
Get current state of a Cluster example: $ safescale cluster state myclusterresponse on success: {"result":{"Name":"mycluster","State":1,"StateLabel":"Nominal"},"status":"success"}response on failure: {"error":{"exitcode":4,"message":"Cluster 'mycluster' not found.\n"},"result":null,"status":"failure"} |
safescale [global_options] cluster delete [command_options] <cluster_name> |
Delete a cluster. By default, ask for user confirmation before doing anythingcommand_options code>:
$ safescale cluster delete -y myclusterresponse on success: {"result":null,"status":"success"}response on failure: {"error":{"exitcode":4,"message":"Cluster 'mycluster' not found.\n"},"result":null,"status":"failure"} |
safescale [global_options] cluster feature check [command_options] <cluster_name> <feature_name> |
Check if a feature is present on the clustercommand_options :
$ safescale cluster feature check mycluster dockerresponse on success: {"result":"Feature 'docker' found on cluster 'mycluster'","status":"success"}response on failure: {"error":{"exitcode":4,"message":"Feature 'docker' not found on cluster 'mycluster'"},"result":null,"status":"failure"} |
safescale [global_options] cluster feature add [command_options] <cluster_name> <feature_name> |
Adds a feature to the clustercommand_options :
$ safescale cluster feature add mycluster remotedesktopresponse on success: {"result":null,"status":"success"}response on failure may vary. |
safescale [global_options] cluster feature delete [command_options] <cluster_name> <feature_name> |
Deletes a Feature from a Clustercommand_options :
$ safescale cluster feature delete my-cluster remote-desktopresponse on success: {"result":null,"status":"success"}response on failure may vary |
safescale [global_options] cluster expand [command_options] <cluster_name> |
Creates new Cluster nodes and add them to Cluster for dutycommand_options :
$ safescale cluster expand myclusterresponse on success: {"result":{"nodes":[{"creation_date":"2023-01-30T17:52:41Z","id":"551e2db3-eb78-4e22-a067-29d7899749c8","kvs":[{"key":"Revision","value":"dce4ee77859e1e249a39ec84d18b41f4ee4de319"},{"key":"Template","value":"906e8259-0340-4856-95b5-4ea2d26fe377"},{"key":"clusterID","value":"ed7fde77-4c6b-495e-afc5-0edcd8b67b67"},{"key":"type","value":"node"},{"key":"CreationDate","value":"2023-01-30T17:52:41Z"},{"key":"DeclaredInBucket","value":"0.safescale-f63b10c1f1d99a0014bfd076b894219f.afraid"},{"key":"Image","value":"75483863-4aee-4e37-a93e-5cb49ea13d1b"},{"key":"ManagedBy","value":"safescale"}],"name":"corvo-node-7","password":"...","private_ip":"192.168.37.9","private_key":"-----BEGIN RSA PRIVATE KEY-----\n.....\n-----END RSA PRIVATE KEY-----","state":2,"state_label":"Started","template":"b2-7"}]},"status":"success"}response on failure: {"error":{"exitcode":4,"message":"Cluster 'mycluster' not found.\n"},"result":null,"status":"failure"} |
safescale [global_options] cluster shrink [command_options] <cluster_name> |
Reduce the numbers of Cluster nodes and deletes the chosen ones example: $ safescale cluster shrink myclusterresponse on success: {"result":null,"status":"success"}response on failure: {"error":{"exitcode":4,"message":"Cluster 'mycluster' not found.\n"},"result":null,"status":"failure"} |
safescale [global_options] cluster stop [command_options] <cluster_name> |
Stop all Hosts composing a Cluster example: $ safescale cluster stop myclusterresponse on success: {"result":null,"status":"success"}response on failure: {"error":{"exitcode":4,"message":"Cluster 'mycluster' not found.\n"},"result":null,"status":"failure"} |
safescale [global_options] cluster start [command_options] <cluster_name> |
Start all Hosts composing a Cluster example: $ safescale cluster start myclusterresponse on success: {"result":null,"status":"success"}response on failure: {"error":{"exitcode":6,"message":"Cannot start cluster: failed to find Cluster 'mycluster'"},"result":null,"status":"failure"} |
safescale [global_options] cluster kubectl [command_options] <cluster_name> -- <kubectl_parameters> |
Executes kubectl command on Clusterexample: $ safescale cluster kubectl mycluster -- get nodesresponse on success: NAME STATUS ROLES AGE VERSION gw-mycluster Ready <none> 11m v1.18.5 mycluster-master-1 Ready master 11m v1.18.5 mycluster-node-1 Ready <none> 10m v1.18.5response on failure: {"error":{"exitcode":4,"message":"Cluster 'mycluster' not found.\n"},"result":null,"status":"failure"} |
safescale [global_options] cluster helm [command_options] <cluster_name> -- <helm_parameters> |
Executes helm command on Cluster example: $ safescale cluster helm mycluster -- install nginxresponse on success: {"result":null,"status":"success"}response on failure: -bash: helm: command not found {"error":{"exitcode":1,"message":""},"result":null,"status":"failure"} |
safescale [global_options] cluster master list [command_options] <cluster_name> |
List the masters of a cluster example: $ safescale cluster master list myclusterresponse on success: {"result":[{"id":"53c56611-5d96-4019-b012-354de282dd33","name":"mycluster-master-1"}],"status":"success"}response on failure: {"error":{"exitcode":4,"message":"Cluster 'mycluster' not found.\n"},"result":null,"status":"failure"} |
safescale [global_options] cluster node list [command_options] <cluster_name> |
List nodes in a Cluster example: $ safescale cluster node list myclusterresponse on success: {"result":[{"id":"7bb5bb44-9c7f-4ec3-9b19-435095c610c6","name":"mycluster-node-1"}],"status":"success"}response on failure: {"error":{"exitcode":1,"message":"rpc error: code = NotFound desc = cannot list cluster nodes: failed to find Cluster 'mycluster': rpc error: code = NotFound desc = cannot list cluster nodes: failed to find Cluster 'mycluster'"},"result":null,"status":"failure"} |
Some parameters of safescale
can be set using environment variables:
SAFESCALED_LISTEN
: equivalent to--listen
, allows to tellsafescale
how to reach the daemonsafescaled
.SAFESCALE_METADATA_SUFFIX
: allows to specify a suffix to add to the name of the Object Storage bucket used to store SafeScale metadata on the tenant. This allows to "isolate" metadata between different users of SafeScale (practical in development for example). There is no equivalent command line parameter. This environment variable must be on par betweensafescale
andsafescaled
, otherwise strange things may happen...