Mini Shell
"""
GoGrid Cloud Module
====================
The GoGrid cloud module. This module interfaces with the gogrid public cloud
service. To use Salt Cloud with GoGrid log into the GoGrid web interface and
create an api key. Do this by clicking on "My Account" and then going to the
API Keys tab.
Set up the cloud configuration at ``/etc/salt/cloud.providers`` or
``/etc/salt/cloud.providers.d/gogrid.conf``:
.. code-block:: yaml
my-gogrid-config:
# The generated api key to use
apikey: asdff7896asdh789
# The apikey's shared secret
sharedsecret: saltybacon
driver: gogrid
.. note::
A Note about using Map files with GoGrid:
Due to limitations in the GoGrid API, instances cannot be provisioned in parallel
with the GoGrid driver. Map files will work with GoGrid, but the ``-P``
argument should not be used on maps referencing GoGrid instances.
.. note::
A Note about using Map files with GoGrid:
Due to limitations in the GoGrid API, instances cannot be provisioned in parallel
with the GoGrid driver. Map files will work with GoGrid, but the ``-P``
argument should not be used on maps referencing GoGrid instances.
"""
import logging
import pprint
import time
import salt.config as config
import salt.utils.cloud
import salt.utils.hashutils
from salt.exceptions import SaltCloudException, SaltCloudSystemExit
# Get logging started
log = logging.getLogger(__name__)
__virtualname__ = "gogrid"
# Only load in this module if the GoGrid configurations are in place
def __virtual__():
"""
Check for GoGrid configs
"""
if get_configured_provider() is False:
return False
return __virtualname__
def _get_active_provider_name():
try:
return __active_provider_name__.value()
except AttributeError:
return __active_provider_name__
def get_configured_provider():
"""
Return the first configured instance.
"""
return config.is_provider_configured(
__opts__,
_get_active_provider_name() or __virtualname__,
("apikey", "sharedsecret"),
)
def create(vm_):
"""
Create a single VM from a data dict
"""
try:
# Check for required profile parameters before sending any API calls.
if (
vm_["profile"]
and config.is_profile_configured(
__opts__,
_get_active_provider_name() or "gogrid",
vm_["profile"],
vm_=vm_,
)
is False
):
return False
except AttributeError:
pass
__utils__["cloud.fire_event"](
"event",
"starting create",
"salt/cloud/{}/creating".format(vm_["name"]),
args=__utils__["cloud.filter_event"](
"creating", vm_, ["name", "profile", "provider", "driver"]
),
sock_dir=__opts__["sock_dir"],
transport=__opts__["transport"],
)
if len(vm_["name"]) > 20:
raise SaltCloudException("VM names must not be longer than 20 characters")
log.info("Creating Cloud VM %s", vm_["name"])
image_id = avail_images()[vm_["image"]]["id"]
if "assign_public_ip" in vm_:
host_ip = vm_["assign_public_ip"]
else:
public_ips = list_public_ips()
if not public_ips:
raise SaltCloudException("No more IPs available")
host_ip = next(iter(public_ips))
create_kwargs = {
"name": vm_["name"],
"image": image_id,
"ram": vm_["size"],
"ip": host_ip,
}
__utils__["cloud.fire_event"](
"event",
"requesting instance",
"salt/cloud/{}/requesting".format(vm_["name"]),
args={
"kwargs": __utils__["cloud.filter_event"](
"requesting", create_kwargs, list(create_kwargs)
),
},
sock_dir=__opts__["sock_dir"],
transport=__opts__["transport"],
)
try:
data = _query("grid", "server/add", args=create_kwargs)
except Exception: # pylint: disable=broad-except
log.error(
"Error creating %s on GOGRID\n\n"
"The following exception was thrown when trying to "
"run the initial deployment:\n",
vm_["name"],
# Show the traceback if the debug logging level is enabled
exc_info_on_loglevel=logging.DEBUG,
)
return False
ssh_username = config.get_cloud_config_value(
"ssh_username", vm_, __opts__, default="root"
)
def wait_for_apipass():
"""
Wait for the password to become available, via the API
"""
try:
passwords = list_passwords()
return passwords[vm_["name"]][0]["password"]
except KeyError:
pass
time.sleep(5)
return False
vm_["password"] = salt.utils.cloud.wait_for_fun(
wait_for_apipass,
timeout=config.get_cloud_config_value(
"wait_for_fun_timeout", vm_, __opts__, default=15 * 60
),
)
vm_["ssh_host"] = host_ip
ret = __utils__["cloud.bootstrap"](vm_, __opts__)
ret.update(data)
log.info("Created Cloud VM '%s'", vm_["name"])
log.debug("'%s' VM creation details:\n%s", vm_["name"], pprint.pformat(data))
__utils__["cloud.fire_event"](
"event",
"created instance",
"salt/cloud/{}/created".format(vm_["name"]),
args=__utils__["cloud.filter_event"](
"created", vm_, ["name", "profile", "provider", "driver"]
),
sock_dir=__opts__["sock_dir"],
transport=__opts__["transport"],
)
return ret
def list_nodes(full=False, call=None):
"""
List of nodes, keeping only a brief listing
CLI Example:
.. code-block:: bash
salt-cloud -Q
"""
if call == "action":
raise SaltCloudSystemExit(
"The list_nodes function must be called with -f or --function."
)
ret = {}
nodes = list_nodes_full("function")
if full:
return nodes
for node in nodes:
ret[node] = {}
for item in ("id", "image", "size", "public_ips", "private_ips", "state"):
ret[node][item] = nodes[node][item]
return ret
def list_nodes_full(call=None):
"""
List nodes, with all available information
CLI Example:
.. code-block:: bash
salt-cloud -F
"""
response = _query("grid", "server/list")
ret = {}
for item in response["list"]:
name = item["name"]
ret[name] = item
ret[name]["image_info"] = item["image"]
ret[name]["image"] = item["image"]["friendlyName"]
ret[name]["size"] = item["ram"]["name"]
ret[name]["public_ips"] = [item["ip"]["ip"]]
ret[name]["private_ips"] = []
ret[name]["state_info"] = item["state"]
if "active" in item["state"]["description"]:
ret[name]["state"] = "RUNNING"
return ret
def list_nodes_select(call=None):
"""
Return a list of the VMs that are on the provider, with select fields
CLI Example:
.. code-block:: bash
salt-cloud -S
"""
return salt.utils.cloud.list_nodes_select(
list_nodes_full("function"),
__opts__["query.selection"],
call,
)
def avail_locations():
"""
Available locations
"""
response = list_common_lookups(kwargs={"lookup": "ip.datacenter"})
ret = {}
for item in response["list"]:
name = item["name"]
ret[name] = item
return ret
def avail_sizes():
"""
Available sizes
"""
response = list_common_lookups(kwargs={"lookup": "server.ram"})
ret = {}
for item in response["list"]:
name = item["name"]
ret[name] = item
return ret
def avail_images():
"""
Available images
"""
response = _query("grid", "image/list")
ret = {}
for item in response["list"]:
name = item["friendlyName"]
ret[name] = item
return ret
def list_passwords(kwargs=None, call=None):
"""
List all password on the account
.. versionadded:: 2015.8.0
"""
response = _query("support", "password/list")
ret = {}
for item in response["list"]:
if "server" in item:
server = item["server"]["name"]
if server not in ret:
ret[server] = []
ret[server].append(item)
return ret
def list_public_ips(kwargs=None, call=None):
"""
List all available public IPs.
CLI Example:
.. code-block:: bash
salt-cloud -f list_public_ips <provider>
To list unavailable (assigned) IPs, use:
CLI Example:
.. code-block:: bash
salt-cloud -f list_public_ips <provider> state=assigned
.. versionadded:: 2015.8.0
"""
if kwargs is None:
kwargs = {}
args = {}
if "state" in kwargs:
if kwargs["state"] == "assigned":
args["ip.state"] = "Assigned"
else:
args["ip.state"] = "Unassigned"
else:
args["ip.state"] = "Unassigned"
args["ip.type"] = "Public"
response = _query("grid", "ip/list", args=args)
ret = {}
for item in response["list"]:
name = item["ip"]
ret[name] = item
return ret
def list_common_lookups(kwargs=None, call=None):
"""
List common lookups for a particular type of item
.. versionadded:: 2015.8.0
"""
if kwargs is None:
kwargs = {}
args = {}
if "lookup" in kwargs:
args["lookup"] = kwargs["lookup"]
response = _query("common", "lookup/list", args=args)
return response
def destroy(name, call=None):
"""
Destroy a machine by name
CLI Example:
.. code-block:: bash
salt-cloud -d vm_name
"""
if call == "function":
raise SaltCloudSystemExit(
"The destroy action must be called with -d, --destroy, -a or --action."
)
__utils__["cloud.fire_event"](
"event",
"destroying instance",
f"salt/cloud/{name}/destroying",
args={"name": name},
sock_dir=__opts__["sock_dir"],
transport=__opts__["transport"],
)
response = _query("grid", "server/delete", args={"name": name})
__utils__["cloud.fire_event"](
"event",
"destroyed instance",
f"salt/cloud/{name}/destroyed",
args={"name": name},
sock_dir=__opts__["sock_dir"],
transport=__opts__["transport"],
)
if __opts__.get("update_cachedir", False) is True:
__utils__["cloud.delete_minion_cachedir"](
name, _get_active_provider_name().split(":")[0], __opts__
)
return response
def reboot(name, call=None):
"""
Reboot a machine by name
CLI Example:
.. code-block:: bash
salt-cloud -a reboot vm_name
.. versionadded:: 2015.8.0
"""
return _query("grid", "server/power", args={"name": name, "power": "restart"})
def stop(name, call=None):
"""
Stop a machine by name
CLI Example:
.. code-block:: bash
salt-cloud -a stop vm_name
.. versionadded:: 2015.8.0
"""
return _query("grid", "server/power", args={"name": name, "power": "stop"})
def start(name, call=None):
"""
Start a machine by name
CLI Example:
.. code-block:: bash
salt-cloud -a start vm_name
.. versionadded:: 2015.8.0
"""
return _query("grid", "server/power", args={"name": name, "power": "start"})
def show_instance(name, call=None):
"""
Start a machine by name
CLI Example:
.. code-block:: bash
salt-cloud -a show_instance vm_name
.. versionadded:: 2015.8.0
"""
response = _query("grid", "server/get", args={"name": name})
ret = {}
for item in response["list"]:
name = item["name"]
ret[name] = item
ret[name]["image_info"] = item["image"]
ret[name]["image"] = item["image"]["friendlyName"]
ret[name]["size"] = item["ram"]["name"]
ret[name]["public_ips"] = [item["ip"]["ip"]]
ret[name]["private_ips"] = []
ret[name]["state_info"] = item["state"]
if "active" in item["state"]["description"]:
ret[name]["state"] = "RUNNING"
return ret
def _query(
action=None, command=None, args=None, method="GET", header_dict=None, data=None
):
"""
Make a web call to GoGrid
.. versionadded:: 2015.8.0
"""
vm_ = get_configured_provider()
apikey = config.get_cloud_config_value("apikey", vm_, __opts__, search_global=False)
sharedsecret = config.get_cloud_config_value(
"sharedsecret", vm_, __opts__, search_global=False
)
path = "https://api.gogrid.com/api/"
if action:
path += action
if command:
path += f"/{command}"
log.debug("GoGrid URL: %s", path)
if not isinstance(args, dict):
args = {}
epoch = str(int(time.time()))
hashtext = "".join((apikey, sharedsecret, epoch))
args["sig"] = salt.utils.hashutils.md5_digest(hashtext)
args["format"] = "json"
args["v"] = "1.0"
args["api_key"] = apikey
if header_dict is None:
header_dict = {}
if method != "POST":
header_dict["Accept"] = "application/json"
decode = True
if method == "DELETE":
decode = False
return_content = None
result = salt.utils.http.query(
path,
method,
params=args,
data=data,
header_dict=header_dict,
decode=decode,
decode_type="json",
text=True,
status=True,
opts=__opts__,
)
log.debug("GoGrid Response Status Code: %s", result["status"])
return result["dict"]
Zerion Mini Shell 1.0